New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adds asSet() to Bag for #726 #797
Conversation
f341d90
to
79fa2a8
Compare
79fa2a8
to
23366eb
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The main feedback is that returning mutable views breaks bag invariants.
...e-collections-api/src/main/java/org/eclipse/collections/api/bag/sorted/MutableSortedBag.java
Show resolved
Hide resolved
...-collections/src/main/java/org/eclipse/collections/impl/bag/immutable/ImmutableArrayBag.java
Outdated
Show resolved
Hide resolved
...-collections/src/main/java/org/eclipse/collections/impl/bag/immutable/ImmutableArrayBag.java
Outdated
Show resolved
Hide resolved
...-collections/src/main/java/org/eclipse/collections/impl/bag/immutable/ImmutableArrayBag.java
Outdated
Show resolved
Hide resolved
...e-collections/src/main/java/org/eclipse/collections/impl/bag/immutable/ImmutableHashBag.java
Show resolved
Hide resolved
eclipse-collections/src/main/java/org/eclipse/collections/impl/bag/mutable/AbstractHashBag.java
Outdated
Show resolved
Hide resolved
23366eb
to
590fda8
Compare
@motlin any feedbacks on the best way to tackle the problems discussed above? |
@victornoel my recommendation would still be to just use |
@motlin yes, I will go with that then, thanks |
@motlin one more advice request: if we use |
Okay, so I pushed a final version with:
|
918c869
to
f07cec3
Compare
eclipse-collections-api/src/main/java/org/eclipse/collections/api/bag/ImmutableBag.java
Show resolved
Hide resolved
...collections-api/src/main/java/org/eclipse/collections/api/bag/sorted/ImmutableSortedBag.java
Show resolved
Hide resolved
...-collections/src/main/java/org/eclipse/collections/impl/bag/immutable/ImmutableArrayBag.java
Outdated
Show resolved
Hide resolved
...e-collections/src/main/java/org/eclipse/collections/impl/bag/immutable/ImmutableHashBag.java
Outdated
Show resolved
Hide resolved
eclipse-collections/src/main/java/org/eclipse/collections/impl/bag/mutable/AbstractHashBag.java
Outdated
Show resolved
Hide resolved
{ | ||
return false; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems out of place.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@motlin why is that? Maybe we don't want to test for being in instance of Set
and let AbstractCollectionAdapter
define equals
directly?
...llections/src/main/java/org/eclipse/collections/impl/set/mutable/UnmodifiableMutableSet.java
Show resolved
Hide resolved
{ | ||
return false; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does this catch exceptions? Can we have hashcode here too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@motlin some of the implementations of equals that rely on Collection.containsAll
do catch those exception because Collection.containsAll
document them and if they are thrown, it's not an error, it means the element are not contained (because of different types or things like that).
I can add hashCode
, I didn't because I expected that all subclass should be more relevant to implement it, but if I add it, I'm not sure what is the best default implementation? An hashCode
of all elements?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@motlin concerning hashCode, actually findbugs is complaining about it, so I moved it to the two subclasses that needed it.
{ | ||
return false; | ||
} | ||
|
||
return this.delegate.equals(obj); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems out of place
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@motlin what do you mean? Should I move equals
and hashCode
to AbstractCollectionAdapter maybe? But I wouldn't be able to test for instance of Set
though
...ons/src/main/java/org/eclipse/collections/impl/set/sorted/mutable/SynchronizedSortedSet.java
Outdated
Show resolved
Hide resolved
I see the problem with the types. If the view has no way of supporting
mutation, then it's ok.
…On Sat, Mar 14, 2020 at 2:10 PM Victor Noël ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In
eclipse-collections/src/main/java/org/eclipse/collections/impl/bag/mutable/UnmodifiableBag.java
<#797 (comment)>
:
> @@ -438,4 +439,10 @@ protected Object readResolve()
{
return this.getMutableBag().selectUnique();
}
+
+ @OverRide
+ public SetIterable<T> asSet()
+ {
+ return this.getMutableBag().asSet();
@motlin <https://github.com/motlin> I can't call asUnmodifiable() because
the return type of asSet() here is SetIterable: I am expecting it to be
unmodifiable if needed be. I will add a test to ensure it is the case
though!
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#797 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAB3UISK25LGG5O7AM2UEH3RHPB7RANCNFSM4KV2JJUA>
.
|
Using inner class views makes me nervous, especially in the immutable collections. I was imagining a class like SetFromBagAdapter that's almost like SetAdapter, but implemented by delegating to a Bag. As long as it doesn't delegate to a MutableBag, we can have high confidence that it never allows mutation as well as unsynchronized access. |
5325b39
to
b3e7fbb
Compare
@motlin trying back to work on this, you said:
How would that work? In order to implement |
b3e7fbb
to
8d597e3
Compare
@motlin I have pushed some changes that I think all together make sense, here is a rundown of the changes that could raise discussion and rationale for the choices I made:
|
c5cca0f
to
92a25b8
Compare
Can't it return
Something sounds backwards in this sentence
This isn't what I meant - I'll have to take a closer look. Why does the wrapper need access to the Bag internals? |
what I mean is that if you wrap a bag, to implement some of the set method, you need to have access to the underlying datatstructure, for example to implement iterator, and in our situation there are two cases when this happens:
it was, I will fix my comment :) |
92a25b8
to
2a0215a
Compare
I tried to write a set-from-bag adapter to see how feasible it is. It's nearly possible, it would need one new method on Bags for a distinct keys view. Take a look at the iterator() method to see what I mean. public class SetFromBagAdapter<T>
extends AbstractImmutableSet<T>
{
private final Bag<T> bag;
public SetFromBagAdapter(Bag<T> bag)
{
this.bag = bag;
}
@Override
public int size()
{
return this.bag.sizeDistinct();
}
@Override
public T getFirst()
{
return this.bag.getFirst();
}
@Override
public T getLast()
{
return this.bag.getLast();
}
@Override
public void each(Procedure<? super T> procedure)
{
this.bag.forEachWithOccurrences((each, parameter) -> procedure.accept(each));
}
@Override
public Iterator<T> iterator()
{
// This works but is inefficient. It really creates the map in O(n) time and space.
Iterator<T> iterator = this.bag.toMapOfItemToCount().keysView().iterator();
// This doesn't work today, but it could without too much effort.
return this.bag.distinctView().iterator();
}
} |
The in places like AbstractHashBag, it's pretty easy to implement the distinct view. @Override
public RichIterable<T> distinctView()
{
return this.items.keysView();
} |
I did forget that context but I think this shows we can implement both with just a few lines of code? |
@motlin no, because of all the other implementation of Bag that do not rely on a Map as in your example. For example The purpose of this PR is to:
Hence this proposal for Honestly I've tried many alternative to arrive to this solution, with various iterations that can we witnessed here, I think we did go around all the possibilities and that the design proposed here is the best. Maybe to better understand that, it would make sense for you to play with the code and experience with the alternative you propose to either see why it doesn't work or to show me how it would work. |
- Prevent useless locking - Prevent potentially costly delegation Signed-off-by: Victor Noël <victor.noel@brennus-analytics.com>
Better protect against exceptions in some cases Signed-off-by: Victor Noël <victor.noel@brennus-analytics.com>
This is limited to returning immutable or unmodifiable sets. Signed-off-by: Victor Noël <victor.noel@brennus-analytics.com>
2a0215a
to
19568ea
Compare
Closing this as this will most certainly never be merged and based on very outdated code |
Finally had the time to finish my PR for #726.
I made the following design decisions:
Bag
interfaces exposesasSet()
which is a view on the unique elements of the bagSetIterable
or aMutableSet
Bag
as aSet
IMHOImmutableArrayBag
andImmutableSortedBagImpl
, I had to implement it by subclassingAbstractImmutableSet
inline: since they are both based on arrays, I only implemented the minimum because I don't think it would have much impact on performance to do more.One open question is: should the inline subclassing be extracted in a separate class that wraps an array maybe?