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 >>> >>
