Vova, Denis, How do you see this API-wise? What if user actually wants to get a sublist of values, without fetching the whole collection? Are you suggesting to have subinterfaces, similar to Guava [1]?
[1] https://google.github.io/guava/releases/snapshot/api/docs/com/google/common/collect/ListMultimap.html -Val On Fri, Aug 12, 2016 at 12:14 PM, Denis Magda <[email protected]> wrote: > Fully agree with Vovan’s suggestion. It’s not a good idea to hard code the > interface to the usage of List. > > Moreover, I would provide an implementation of the IgniteMultimap with > TreeSet under the hood out of the box. A user will be able to use this > implementation if performance of multi map updates is more critical for a > use case. > > — > Denis > > > > On Aug 12, 2016, at 12:01 PM, Vladimir Ozerov <[email protected]> > wrote: > > > > Correct me if I am wrong, but I always thought that multimap is about > > associating multiple values with a single key without explicit > > specification on how these values are stored. E.g.: > > Google Guava - > > https://google.github.io/guava/releases/snapshot/api/ > docs/com/google/common/collect/Multimap.html#get(K) > > Apache Commons - > > https://commons.apache.org/proper/commons-collections/ > apidocs/org/apache/commons/collections4/MultiValuedMap.html#get(K) > > > > I would rather return *Collection*, but with ability to specify > underlying > > data structure using some factory. > > > > On Fri, Aug 12, 2016 at 6:35 PM, Dmitriy Setrakyan < > [email protected]> > > wrote: > > > >> Amir, > >> > >> It is great that you decided to pick this ticket. I suggest to handle > the > >> design discussions in the ticket itself, as Jira allows for better code > >> formatting. It still makes sense, though, to notify the dev list that > you > >> have updated the ticket, so folks remember to look at it. > >> > >> D. > >> > >> On Thu, Aug 11, 2016 at 7:26 PM, Amir Akhmedov <[email protected] > > > >> wrote: > >> > >>> Hi guys, > >>> > >>> I noticed that IgniteMultimap waits too long to be implemented and I > >>> decided to pick it up :-) > >>> > >>> For now I want to bring to community up a draft version for > >> IgniteMultimap > >>> interface. Will appreciate any feedback and once it's fine I will start > >> its > >>> implementation > >>> > >>> > >>> package org.apache.ignite; > >>> > >>> import org.apache.ignite.lang.IgniteCallable; > >>> import org.apache.ignite.lang.IgniteRunnable; > >>> > >>> import java.io.Closeable; > >>> import java.util.*; > >>> > >>> public interface IgniteMultimap<K, V> extends Closeable { > >>> > >>> /** > >>> * Returns the list of values to which the specified key is mapped, > >>> * or {@code null} if this map contains no mapping for the key. > >>> * > >>> * @param key the key whose associated values are to be returned > >>> * @return the list of values to which the specified key is mapped, > >>> * or {@code null} if this map contains no mapping for the key. > >>> * @throws ClassCastException if the key is of an inappropriate > >>> type for this map > >>> */ > >>> public List<V> get(K key); > >>> > >>> /** > >>> * Returns the value at a certain index to which the specified key > >>> is mapped, > >>> * or {@code null} if this map contains no mapping for the key. > >>> * > >>> * @param key the key whose associated values are to be returned > >>> * @param index index to lookup > >>> * @return the value at a certain index to which the specified key > >>> is mapped, > >>> * or {@code null} if this map contains no mapping for the key. > >>> * @throws ClassCastException if the key is of an inappropriate > >>> type for this map > >>> * @throws IndexOutOfBoundsException if the index is out of range > >>> (index < 0 || index >= list.size()) > >>> */ > >>> public V get(K key, int index); > >>> > >>> /** > >>> * Returns the values for specified range of indexes, between min > and > >>> max > >>> * to which the specified key is mapped, or {@code null} if this > >>> map contains > >>> * no mapping for the key. > >>> * > >>> * @param key the key whose associated values are to be returned > >>> * @param min min index to lookup > >>> * @param max max index to lookup > >>> * @return the values for specified range of indexes, between min > and > >>> max > >>> * to which the specified key is mapped, or {@code null} if this > >>> map contains > >>> * no mapping for the key. > >>> * @throws ClassCastException if the key is of an inappropriate > >>> type for this map > >>> * @throws IndexOutOfBoundsException if either of indexes min or > >>> max is out of > >>> * range (index < 0 || index >= list.size()) > >>> */ > >>> public List<V> get(K key, int min, int max); > >>> > >>> /** > >>> * Returns the list of values for specified indexes to which the > >>> specified key > >>> * is mapped, or {@code null} if this map contains no mapping for > the > >>> key. > >>> * @param key the key whose associated values are to be returned > >>> * @param indexes the indexes to lookup > >>> * @return the list of values for specified indexes to which the > >>> specified key > >>> * is mapped, or {@code null} if this map contains no mapping for > the > >>> key. > >>> * @throws ClassCastException if the key is of an inappropriate > >>> type for this map > >>> * @throws IndexOutOfBoundsException if either of indexes is out of > >>> * range (index < 0 || index >= list.size()) > >>> */ > >>> public List<V> get(K key, Iterable<Integer> indexes); > >>> > >>> /** > >>> * Returns the list of values for a collection of keys to which > >>> the keys are mapped. > >>> * {@code null} will be added to resulting list if this map > >>> contains no mapping for the key. > >>> * @param keys collection of keys > >>> * @return the list of values for a collection of keys to which > >>> the keys are mapped. > >>> * @throws ClassCastException if the key is of an inappropriate > >>> type for this map > >>> * {@code null} will be added to resulting list if this map > >>> contains no mapping for the key. > >>> */ > >>> public Map<K, List<V>> getAll(Collection<K> keys); > >>> > >>> /** > >>> * Returns a value at a certain index for a collection of keys to > >>> which the keys are mapped. > >>> * {@code null} will be added to resulting list if this map > >>> contains no mapping for the key. > >>> * @param keys collection of keys > >>> * @param index the index to lookup > >>> * @return a value at a certain index for a collection of keys to > >>> which the keys are mapped. > >>> * {@code null} will be added to resulting list if this map > >>> contains no mapping for the key. > >>> * @throws ClassCastException if the key is of an inappropriate > >>> type for this map > >>> * @throws IndexOutOfBoundsException if the indexes is out of > >>> range (index < 0 || index >= list.size()) > >>> */ > >>> public Map<K, V> getAll(Collection<K> keys, int index); > >>> > >>> /** > >>> * Returns the list of values for the range of indexes, between > >>> min and max for a collection > >>> * of keys to which the keys are mapped. {@code null} will be > >>> added to resulting list if this > >>> * map contains no mapping for the key. > >>> * @param keys collection of keys > >>> * @param min min index to lookup > >>> * @param max max index to lookup > >>> * @return the list of values for the range of indexes, between > >>> min and max for a collection > >>> * of keys to which the keys are mapped. {@code null} will be > >>> added to resulting list if this > >>> * map contains no mapping for the key. > >>> * @throws ClassCastException if the key is of an inappropriate > >>> type for this map > >>> * @throws IndexOutOfBoundsException if either of indexes min or > >>> max is out of > >>> * range (index < 0 || index >= list.size()) > >>> */ > >>> public Map<K, List<V>> getAll(Collection<K> keys, int min, int max); > >>> > >>> /** > >>> * Returns the list of values for specified indexes or a > >>> collection of keys to which the keys are > >>> * mapped. {@code null} will be added to resulting list if this > >>> map contains no mapping for the key. > >>> * @param keys collection of keys > >>> * @param indexes the indexes to lookup > >>> * @return the list of values for specified indexes or a > >>> collection of keys to which the keys are > >>> * mapped. {@code null} will be added to resulting list if this > >>> map contains no mapping for the key. > >>> * @throws ClassCastException if the key is of an inappropriate > >>> type for this map > >>> * @throws IndexOutOfBoundsException if either of indexes is out > >>> of range (index < 0 || index >= list.size()) > >>> */ > >>> public Map<K, List<V>> getAll(Collection<K> keys, > >>> Iterable<Integer> indexes); > >>> > >>> /** > >>> * Iterate through all elements with a certain index. > >>> * @param index the index to lookup > >>> * @return Iterator through all elements with a certain index. > >>> * @throws IndexOutOfBoundsException index is out of range for any > >>> list of values > >>> * (index < 0 || index >= list.size()) > >>> */ > >>> public Iterator<Map.Entry<K, V>> iterate(int index); > >>> > >>> /** > >>> * Clears the multimap. Removes all key-value pairs. > >>> */ > >>> public void clear(); > >>> > >>> /** > >>> * Returns {@code true} if this multimap contains a mapping for > >>> the specified key. > >>> * > >>> * @param key key whose presence in this map is to be tested > >>> * @return {@code true} if this map contains a mapping for the > >>> specified key > >>> * @throws ClassCastException if the key is of an inappropriate > >>> type for this map > >>> */ > >>> public boolean containsKey(K key); > >>> > >>> /** > >>> * Returns {@code true} if this multimap contains at least one > >>> key-value pair > >>> * with the value {@code value}. > >>> * > >>> * @param value value whose presence in this map is to be tested > >>> * @return {@code true} if this multimap contains at least one > >>> key-value pair > >>> * with the value {@code value}. > >>> * @throws ClassCastException if the key is of an inappropriate > >>> type for this map > >>> */ > >>> public boolean containsValue(V value); > >>> > >>> /** > >>> * Returns whether the multimap contains the given key-value pair. > >>> * > >>> * @param key key whose presence in this map is to be tested > >>> * @param value value whose presence in this map is to be tested > >>> * > >>> * @return {@code true} if the multimap contains the key-value > >>> pair, {@code false} otherwise > >>> * @throws ClassCastException if the key is of an inappropriate > >>> type for this map > >>> */ > >>> public boolean containsEntry(K key, V value); > >>> > >>> /** > >>> * Returns a {@link Set} view of the mappings contained in this map. > >>> * > >>> * @return a {@link Set} view of the mappings contained in this map. > >>> */ > >>> public Set<Map.Entry<K, V>> entrySet(); > >>> > >>> /** > >>> * Returns the locally owned set of keys. > >>> * > >>> * @return the locally owned set of keys. > >>> */ > >>> public Set<K> localKeySet(); > >>> > >>> /** > >>> * Returns a {@link Set} view of the keys contained in this map. > >>> * > >>> * @return a {@link Set} view of the keys contained in this map. > >>> */ > >>> public Set<K> keySet(); > >>> > >>> /** > >>> * Associates the specified value with the specified key in this > >>> multimap > >>> * > >>> * @param key key with which the specified value is to be associated > >>> * @param value value to be associated with the specified key > >>> * @return {@code true} if the method increased the size of the > >>> multimap, or > >>> * {@code false} if the multimap already contained the key-value > pair > >>> and > >>> * doesn't allow duplicates > >>> * @throws ClassCastException if the class of the specified key or > >>> value > >>> * prevents it from being stored in this map > >>> */ > >>> public boolean put(K key, V value); > >>> > >>> /** > >>> * Stores a key-value pair in this multimap for each of {@code > >>> values}, all > >>> * using the same key, {@code key}. Equivalent to (but expected to > be > >>> more > >>> * efficient than): <pre> {@code > >>> * > >>> * for (V value : values) { > >>> * put(key, value); > >>> * }}</pre> > >>> * > >>> * <p>In particular, this is a no-op if {@code values} is empty. > >>> * > >>> * @return {@code true} if the multimap changed > >>> * @throws ClassCastException if the class of the specified key or > >>> value > >>> * prevents it from being stored in this map > >>> */ > >>> public boolean putAll(K key, Iterable<? extends V> values); > >>> > >>> /** > >>> * Stores all key-value pairs of {@code multimap} in this multimap, > >> in > >>> the > >>> * order returned by {@code multimap.entries()}. > >>> * > >>> * @return {@code true} if the multimap changed > >>> */ > >>> public boolean putAll(IgniteMultimap<? extends K, ? extends V> > >>> multimap); > >>> > >>> /** > >>> * Removes the key and all values associated with the key {@code > >> key}. > >>> * > >>> * @return the list of values that were removed, or {@code null} > >>> * if this map contains no mapping for the key. > >>> * @throws ClassCastException if the key is of an inappropriate > >>> type for this map > >>> */ > >>> public List<V> remove(K key); > >>> > >>> /** > >>> * Removes a single key-value pair with the key {@code key} and the > >>> value > >>> * {@code value} from this multimap, if such exists. If multiple > >>> key-value > >>> * pairs in the multimap fit this description, which one is removed > >> is > >>> * unspecified. > >>> * > >>> * @return {@code true} if the multimap changed > >>> * @throws ClassCastException if the key is of an inappropriate > >>> type for this map > >>> */ > >>> public boolean remove(K key, V value); > >>> > >>> /** > >>> * Stores a collection of values with the same key, replacing any > >>> existing > >>> * values for that key. > >>> * > >>> * @return the collection of replaced values, or {@code null} > >>> * if this map contains no mapping for the key. > >>> * @throws ClassCastException if the key is of an inappropriate > >>> type for this map > >>> */ > >>> List<V> replaceValues(K key, Iterable<? extends V> values); > >>> > >>> /** > >>> * Returns {@code true} if this map contains no key-value mappings. > >>> * > >>> * @return {@code true} if this map contains no key-value mappings > >>> */ > >>> > >>> public boolean isEmpty(); > >>> > >>> /** > >>> * Returns the number of keys in this map. If the map contains > >>> more than {@code Integer.MAX_VALUE} > >>> * elements, returns {@code Integer.MAX_VALUE}. > >>> * > >>> * @return the number of keys in this map > >>> */ > >>> public int size(); > >>> > >>> /** > >>> * Returns a list containing the <i>value</i> from each key-value > >>> * pair contained in this multimap, without collapsing duplicates. > >>> * > >>> * @return a list containing the <i>value</i> from each key-value > >>> * pair contained in this multimap, without collapsing duplicates. > >>> */ > >>> public List<V> values(); > >>> > >>> /** > >>> * Returns the number of values that match the given key in the > >>> multimap. > >>> * > >>> * @param key the key whose values count is to be returned > >>> * @return the number of values that match the given key in the > >>> multimap > >>> */ > >>> public int valueCount(K key); > >>> > >>> /** > >>> * Gets multimap name. > >>> * > >>> * @return Multimap name. > >>> */ > >>> public String name(); > >>> > >>> /** > >>> * Removes this multimap. > >>> * > >>> * @throws IgniteException If operation failed. > >>> */ > >>> @Override public void close() throws IgniteException; > >>> > >>> /** > >>> * Returns {@code true} if this multimap can be kept on the one node > >>> only. > >>> * Returns {@code false} if this multimap can be kept on the many > >>> nodes. > >>> * > >>> * @return {@code true} if this multimap is in {@code collocated} > >>> mode {@code false} otherwise. > >>> */ > >>> public boolean collocated(); > >>> > >>> /** > >>> * Executes given job on collocated multimap on the node where the > >>> multimap is located > >>> * (a.k.a. affinity co-location). > >>> * <p> > >>> * This is not supported for non-collocated multimaps. > >>> * > >>> * @param job Job which will be co-located with the multimap. > >>> * @throws IgniteException If job failed. > >>> */ > >>> public void affinityRun(IgniteRunnable job) throws IgniteException; > >>> > >>> /** > >>> * Executes given job on collocated multimap on the node where the > >>> multimap is located > >>> * (a.k.a. affinity co-location). > >>> * <p> > >>> * This is not supported for non-collocated multimaps. > >>> * > >>> * @param job Job which will be co-located with the multimap. > >>> * @throws IgniteException If job failed. > >>> */ > >>> public <R> R affinityCall(IgniteCallable<R> job) throws > >>> IgniteException; > >>> } > >>> > >>> > >>> > >>> -- > >>> Sincerely Yours Amir Akhmedov > >>> > >> > >
