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
Create a Multimap #1131
Comments
Hi Ruslan, interface MultiMap<K, V, TYPE extends Traversable<V>> {
TYPE values();
} We could have factory methods for the default-value container Set: static <...> Multimap<..., Set<V>> empty();
static <...> Multimap<..., Set<V>> ofEntries(...);
... Because we need appropriate create and add methods for construction and element addition, we could pre-define known Traversable types that can be used as value-containers. These enum knows all necessary operations. interface Multimap {
enum Type {
INDEXED_SEQ(Vector::new, Vector::append),
LINEAR_SEQ(...),
SET(...),
SORTED_SET(...)
Type(...) {
...
}
}
static Multimap<..., Set<V>> empty(Type type);
static Multimap<..., Set<V>> ofEntries(Type type, ...);
...
} To have the most flexibility, we could provide also a factory method that allows to create arbitrary value containers: static <...> Multimap<..., Set<V>> empty(Supplier<TYPE> unit, BiFunction<TYPE, V, TYPE> add);
// maybe we omit all other factory methods for the general case to keep it simple?
// static <...> Multimap<..., Set<V>> ofEntries(...);
... |
Yes, I thought about it. |
Cool, one Multimap will rule all :-) |
My original naive implementation was https://gist.github.com/talios/97c27fe577894e96cc46 - which was basically doing the bare minimum of what I was wanting. And when I say naive - I mean incredibly so :) |
partly blocked by #1132 |
MultimapSeq can store duplicate key-value pairs unlike MultimapSet |
Why can't we have just I guess it is because Seq and Set are orthogonal return types and they can't be overridden? Do you have examples where it does not work? I think the Seq/Set return type problem could be solved if we make use of (Btw Kind has to be properly implemented by all Javaslang classes, I will do that) |
If we specifiy the container type at construction type, e.g. HashMultimap.emptyWithSeq(); // List is chosen
HashMultimap.emptyWithSet(); // HashSet is chosen or import javaslang.collection.TreeMultimap.ContainerType.*;
TreeMultimap.empty(SEQ); // List is chosen
TreeMultimap.empty(SET); // TreeSet is chosen |
I will check it
Yes, looks good 👍 P.S. I saw your comment about deadline at 15.03.2016 and I believe |
Ok - let's try to meet that date. I've s.th. todo with Match, too. If you need longer it should be no problem. |
@danieldietrich is there something which I could help you guys with ? |
Until release we have two things: Pattern Matching (me on it) + Multimap (Ruslan on it). I think helping out with the features makes not much sense at this state because they are under 'heavy' development, right @ruslansennov? But... tests, tests, tests! We aim 100% coverage and there is still much missing. A helping hand would be awesome! |
|
ok, then I'll try to add some tests - is there an easy way to check which fragments of code are not covered ? |
thanks @ruslansennov , I've already started to drill down to sub directories to find some blind spots. |
great! |
haha...
I have no idea how this can be implemented 😞 For example, Current state you can see in my branch 'multimap' |
I know that feeling - 99% are straight forward, but the last 1%... I will take a look! |
I've created a workspace with your branch and started reading the code. The type signatures of the classes / interfaces look good.
I would remove the |
I've thought about it. We should not use Kind1 or Kind2 in the Multimaps at all. It introduces problems. (It should be only used as marker interface which can be further used in javaslang-algebra.) |
empty Option
Of course, it is just stub... |
Then
I still not fully understand it. Is it not good to return |
Btw - I'm pretty impressed! The code looks great :-) Nice implementation. |
It is good! And it works fine everywhere except |
Ok, now I understand. I check that... |
It is not possible because of the lack of higher-kinded types / type constructors in Java. We have two (practicable) options: 1) Create specific implementations for all possible value container types. --> I'm no friend of that. I think multimaps are rarely used compared to other collections. If they count more than all other collections summed up it would not be good for the readability of the collection library. 2) We just use --> We may add check methods for characteristics, such as
These in conjunction with conversion methods What do you think? 2) or 2)? ;-) Update: internally the multimap of course still uses a specific Traversable impl. I think we still need the factory instance you implemented. I will look into that tomorrow. Need sleep! The last days were a little bit exhausting... |
Now Multimap has only 2 generics and it is good (branch updated) |
Fine, looks good! I'm looking forward to the code review. I've seen some minor things:
enum Container {
SET(HashSet::empty, (Set<Object> set, Object elem) -> set.add(elem), (Set<Object> set, Object elem) -> set.remove(elem)),
SORTED_SET(TreeSet::empty, ...),
SEQ(List::empty, ...);
final Supplier<Traversable<?>> emptySupplier;
final BiFunction<Traversable<?>, Object, Traversable<?>> add;
final BiFunction<Traversable<?>, Object, Traversable<?>> remove;
<T> Container(Supplier<Traversable<?>> emptySupplier,
BiFunction<? extends Traversable<?>, Object, Traversable<?>> add,
BiFunction<? extends Traversable<T>, T, Traversable<T>> remove) {
this.emptySupplier = emptySupplier;
this.add = add;
this.remove = remove;
}
@SuppressWarnings("unchecked")
<T> Traversable<T> empty() {
return (Traversable<T>) emptySupplier.get();
}
@SuppressWarnings("unchecked")
<T> Traversable<T> add(Traversable<T> container, T elem) {
return (Traversable<T>) add.apply(container, elem);
}
@SuppressWarnings("unchecked")
<T> Traversable<T> remove(Traversable<T> container, T elem) {
return (Traversable<T>) remove.apply(container, elem);
}
} I'm in a hurry and can't get the generics right. But should be possible somehow... |
Hey @ruslansennov, I want to prepare closed shop for 2.0.0 final. Is it ok to take the Multimap to 2.1.0 which should be short after 2.0.0 (e.g. 1 month?). Then we have time to test. Once we are final with 2.0.0 I don't want to modify existing interface methods if possible. (However, I will take a last look at the Xxx.match() methods). The next days I will concentrate on the web-page and the documentation. Is that ok for you? |
Fine, let's move it to 2.x.x |
Ok, will do it. |
Done by Ruslan in #1240 |
We have to make a decision about the type of container that holds values. Scala uses Set but I would use Traversable like in Guava. This allows us to store the same values in containers in certain multimap implementations. On the other side, using the Set as container is much easier to implement and much shorter API
The text was updated successfully, but these errors were encountered: