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

Reply via email to