You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@ignite.apache.org by "Amir Akhmedov (JIRA)" <ji...@apache.org> on 2016/08/14 18:47:20 UTC

[jira] [Comment Edited] (IGNITE-640) Implement IgniteMultimap data structures

    [ https://issues.apache.org/jira/browse/IGNITE-640?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15420437#comment-15420437 ] 

Amir Akhmedov edited comment on IGNITE-640 at 8/14/16 6:46 PM:
---------------------------------------------------------------

I'm proposing IgniteMultimap interface to be as Guava has: IgniteMultimap is a base interface and also there will be 3 derived interfaces: IgniteListMultimap, IgniteSetMultimap, IgniteSortedSetMultimap. All 3 subinterfaces will have Atomic and Transactional implementations.

Please review it, any comments and concerns will be highly appreciated.

{code:title=IgniteMultimap.java|borderStyle=solid}
public interface IgniteMultimap<K, V> extends Closeable {

    /**
     * Returns collection of values to which the specified key is mapped,
     * or empty collection if this multimap 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 empty collection if this multimap contains no mapping for the key.
     * @throws ClassCastException if the key is of an inappropriate type for this multimap
     */
    public Collection<V> get(K key);

    /**
     * Returns the list of values for a collection of keys to which the keys are mapped.
     * Empty collection will be added to resulting list if this multimap 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.
     * Empty collection will be added to resulting list if this multimap contains no mapping for the key.
     * @throws ClassCastException if the key is of an inappropriate type for this multimap
     */
    public Map<K, Collection<V>> getAll(Collection<K> keys);

    /**
     * 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 multimap is to be tested
     * @return {@code true} if this multimap contains a mapping for the specified key
     * @throws ClassCastException if the key is of an inappropriate type for this multimap
     */
    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 multimap 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 multimap
     */
    public boolean containsValue(V value);

    /**
     * Returns whether the multimap contains the given key-value pair.
     *
     * @param key key whose presence in this multimap is to be tested
     * @param value value whose presence in this multimap 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 multimap
     */
    public boolean containsEntry(K key, V value);

    /**
     * Returns a {@link Collection} view of the mappings contained in this multimap.
     *
     * @return a {@link Collection} view of the mappings contained in this multimap.
     */
    public Collection<Map.Entry<K, V>> entries();

    /**
     * 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 multimap.
     *
     * @return a {@link Set} view of the keys contained in this multimap.
     */
    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 multimap
     */
    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 multimap
     */
    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 {@code Collection} of values that were removed, or empty {@code Collection}
     * if this multimap contains no mapping for the key.
     * @throws ClassCastException if the key is of an inappropriate type for this multimap
     */
    public Collection<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 multimap
     */
    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 {@code Collection } of replaced values, or empty {@code Collection}
     * if this multimap contains no mapping for the key.
     * @throws ClassCastException if the key is of an inappropriate type for this multimap
     */
    Collection<V> replaceValues(K key, Iterable<? extends V> values);

    /**
     * Returns {@code true} if this multimap contains no key-value mappings.
     *
     * @return {@code true} if this multimap contains no key-value mappings
     */

    public boolean isEmpty();

    /**
     * Returns the number of keys in this multimap. If the multimap contains more than {@code Integer.MAX_VALUE}
     * elements, returns {@code Integer.MAX_VALUE}.
     *
     * @return the number of keys in this multimap
     */
    public int size();

    /**
     * Returns a collection containing the <i>value</i> from each key-value
     * pair contained in this multimap, without collapsing duplicates.
     *
     * @return a collection containing the <i>value</i> from each key-value
     * pair contained in this multimap, without collapsing duplicates.
     */
    public Collection<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;
}
{code}

{code:title=IgniteListMultimap.java|borderStyle=solid}
public interface IgniteListMultimap<K, V> extends IgniteMultimap<K, V> {

    /**
     * {@inheritDoc}
     *
     * <p>Because the values for a given key may have duplicates and follow the
     * insertion ordering, this method returns a {@link List}, instead of the
     * {@link java.util.Collection} specified in the {@link IgniteMultimap} interface.
     */
    @Override public List<V> get(K key);

    /**
     * {@inheritDoc}
     *
     * <p>Because the values for a given key may have duplicates and follow the
     * insertion ordering, this method returns a {@link List}, instead of the
     * {@link java.util.Collection} specified in the {@link IgniteMultimap} interface.
     */
    @Override public List<V> remove(K key);

    /**
     * {@inheritDoc}
     *
     * <p>Because the values for a given key may have duplicates and follow the
     * insertion ordering, this method returns a {@link List}, instead of the
     * {@link java.util.Collection} specified in the {@link IgniteMultimap} interface.
     */
    @Override public List<V> replaceValues(K key, Iterable<? extends V> values);

    /**
     * Returns the value at a certain index to which the specified key is mapped,
     * or empty collection if this multimap 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 empty collection if this multimap contains no mapping for the key.
     * @throws ClassCastException if the key is of an inappropriate type for this multimap
     * @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 multimap 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 multimap contains
     * no mapping for the key.
     * @throws ClassCastException if the key is of an inappropriate type for this multimap
     * @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 multimap 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 multimap contains no mapping for the key.
     * @throws ClassCastException if the key is of an inappropriate type for this multimap
     * @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 a value at a certain index for a collection of keys to which the keys are mapped.
     * Empty collection will be added to resulting list if this multimap 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.
     * Empty collection will be added to resulting list if this multimap contains no mapping for the key.
     * @throws ClassCastException if the key is of an inappropriate type for this multimap
     * @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. Empty collection will be added to resulting list if this
     * multimap 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. Empty collection will be added to resulting list if this
     * multimap contains no mapping for the key.
     * @throws ClassCastException if the key is of an inappropriate type for this multimap
     * @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. Empty collection will be added to resulting list if this multimap 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. Empty collection will be added to resulting list if this multimap contains no mapping for the key.
     * @throws ClassCastException if the key is of an inappropriate type for this multimap
     * @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);
}
{code}

{code:title=IgniteSetMultimap.java|borderStyle=solid}
public interface IgniteSetMultimap<K, V> extends IgniteMultimap<K, V> {

    /**
     * {@inheritDoc}
     *
     * <p>Because a {@code IgniteSetMultimap} has unique values for a given key, this
     * method returns a {@link Set}, instead of the {@link java.util.Collection}
     * specified in the {@link IgniteMultimap} interface.
     */
    @Override public Set<V> get(K key);

    /**
     * {@inheritDoc}
     *
     * <p>Because a {@code IgniteSetMultimap} has unique values for a given key, this
     * method returns a {@link Set}, instead of the {@link java.util.Collection}
     * specified in the {@link IgniteMultimap} interface.
     */
    @Override public Set<V> remove(K key);

    /**
     * {@inheritDoc}
     *
     * <p>Because a {@code IgniteSetMultimap} has unique values for a given key, this
     * method returns a {@link Set}, instead of the {@link java.util.Collection}
     * specified in the {@link IgniteMultimap} interface.
     *
     * <p>Any duplicates in {@code values} will be stored in the multimap once.
     */
    @Override public Set<V> replaceValues(K key, Iterable<? extends V> values);

    /**
     * {@inheritDoc}
     *
     * <p>Because a {@code IgniteSetMultimap} has unique values for a given key, this
     * method returns a {@link Set}, instead of the {@link java.util.Collection}
     * specified in the {@link IgniteMultimap} interface.
     */
    @Override public Set<Map.Entry<K, V>> entries();
}
{code}

{code:title=IgniteSetMultimap.java|borderStyle=solid}
public interface IgniteSortedSetMultimap<K,V> extends IgniteSetMultimap<K, V> {

    /**
     * {@inheritDoc}
     *
     * <p>Because a {@code IgniteSortedSetMultimap} has unique sorted values for a given
     * key, this method returns a {@link SortedSet}, instead of the
     * {@link java.util.Collection} specified in the {@link IgniteMultimap} interface.
     */
    @Override public SortedSet<V> get(K key);

    /**
     * {@inheritDoc}
     *
     * <p>Because a {@code IgniteSortedSetMultimap} has unique sorted values for a given
     * key, this method returns a {@link SortedSet}, instead of the
     * {@link java.util.Collection} specified in the {@link IgniteMultimap} interface.
     */
    @Override public SortedSet<V> remove(K key);

    /**
     * {@inheritDoc}
     *
     * <p>Because a {@code IgniteSortedSetMultimap} has unique sorted values for a given
     * key, this method returns a {@link SortedSet}, instead of the
     * {@link java.util.Collection} specified in the {@link IgniteMultimap} interface.
     *
     * <p>Any duplicates in {@code values} will be stored in the multimap once.
     */
    @Override public SortedSet<V> replaceValues(K key, Iterable<? extends V> values);

    /**
     * Returns the comparator that orders the multimap values, with {@code null}
     * indicating that natural ordering is used.
     */
    public Comparator<? super V> valueComparator();
}
{code}


was (Author: aakhmedov):
I'm proposing IgniteMultimap interface to be as Guava has: IgniteMultimap is a base interface and also there will be 3 derived interfaces: IgniteListMultimap, IgniteSetMultimap, IgniteSortedSetMultimap. All 3 subinterfaces will have Atomic and Transactional implementations.

Please review it, any comments and concerns will be highly appreciated.

{code:title=IgniteMultimap.java|borderStyle=solid}
public interface IgniteMultimap<K, V> extends Closeable {

    /**
     * Returns collection of values to which the specified key is mapped,
     * or empty collection if this multimap 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 empty collection if this multimap contains no mapping for the key.
     * @throws ClassCastException if the key is of an inappropriate type for this multimap
     */
    public Collection<V> get(K key);

    /**
     * Returns the list of values for a collection of keys to which the keys are mapped.
     * Empty collection will be added to resulting list if this multimap 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.
     * Empty collection will be added to resulting list if this multimap contains no mapping for the key.
     * @throws ClassCastException if the key is of an inappropriate type for this multimap
     */
    public Map<K, Collection<V>> getAll(Collection<K> keys);

    /**
     * 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 multimap is to be tested
     * @return {@code true} if this multimap contains a mapping for the specified key
     * @throws ClassCastException if the key is of an inappropriate type for this multimap
     */
    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 multimap 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 multimap
     */
    public boolean containsValue(V value);

    /**
     * Returns whether the multimap contains the given key-value pair.
     *
     * @param key key whose presence in this multimap is to be tested
     * @param value value whose presence in this multimap 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 multimap
     */
    public boolean containsEntry(K key, V value);

    /**
     * Returns a {@link Collection} view of the mappings contained in this multimap.
     *
     * @return a {@link Collection} view of the mappings contained in this multimap.
     */
    public Collection<Map.Entry<K, V>> entries();

    /**
     * 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 multimap.
     *
     * @return a {@link Set} view of the keys contained in this multimap.
     */
    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 multimap
     */
    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 multimap
     */
    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 {@code Collection} of values that were removed, or empty {@code Collection}
     * if this multimap contains no mapping for the key.
     * @throws ClassCastException if the key is of an inappropriate type for this multimap
     */
    public Collection<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 multimap
     */
    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 {@code Collection } of replaced values, or empty {@code Collection}
     * if this multimap contains no mapping for the key.
     * @throws ClassCastException if the key is of an inappropriate type for this multimap
     */
    Collection<V> replaceValues(K key, Iterable<? extends V> values);

    /**
     * Returns {@code true} if this multimap contains no key-value mappings.
     *
     * @return {@code true} if this multimap contains no key-value mappings
     */

    public boolean isEmpty();

    /**
     * Returns the number of keys in this multimap. If the multimap contains more than {@code Integer.MAX_VALUE}
     * elements, returns {@code Integer.MAX_VALUE}.
     *
     * @return the number of keys in this multimap
     */
    public int size();

    /**
     * Returns a collection containing the <i>value</i> from each key-value
     * pair contained in this multimap, without collapsing duplicates.
     *
     * @return a collection containing the <i>value</i> from each key-value
     * pair contained in this multimap, without collapsing duplicates.
     */
    public Collection<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;
}
{code}

{code:title=IgniteListMultimap.java|borderStyle=solid}
public interface IgniteListMultimap<K, V> extends IgniteMultimap<K, V> {

    /**
     * {@inheritDoc}
     *
     * <p>Because the values for a given key may have duplicates and follow the
     * insertion ordering, this method returns a {@link List}, instead of the
     * {@link java.util.Collection} specified in the {@link IgniteMultimap} interface.
     */
    @Override List<V> get(K key);

    /**
     * {@inheritDoc}
     *
     * <p>Because the values for a given key may have duplicates and follow the
     * insertion ordering, this method returns a {@link List}, instead of the
     * {@link java.util.Collection} specified in the {@link IgniteMultimap} interface.
     */
    @Override List<V> remove(K key);

    /**
     * {@inheritDoc}
     *
     * <p>Because the values for a given key may have duplicates and follow the
     * insertion ordering, this method returns a {@link List}, instead of the
     * {@link java.util.Collection} specified in the {@link IgniteMultimap} interface.
     */
    @Override List<V> replaceValues(K key, Iterable<? extends V> values);

    /**
     * Returns the value at a certain index to which the specified key is mapped,
     * or empty collection if this multimap 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 empty collection if this multimap contains no mapping for the key.
     * @throws ClassCastException if the key is of an inappropriate type for this multimap
     * @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 multimap 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 multimap contains
     * no mapping for the key.
     * @throws ClassCastException if the key is of an inappropriate type for this multimap
     * @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 multimap 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 multimap contains no mapping for the key.
     * @throws ClassCastException if the key is of an inappropriate type for this multimap
     * @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 a value at a certain index for a collection of keys to which the keys are mapped.
     * Empty collection will be added to resulting list if this multimap 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.
     * Empty collection will be added to resulting list if this multimap contains no mapping for the key.
     * @throws ClassCastException if the key is of an inappropriate type for this multimap
     * @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. Empty collection will be added to resulting list if this
     * multimap 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. Empty collection will be added to resulting list if this
     * multimap contains no mapping for the key.
     * @throws ClassCastException if the key is of an inappropriate type for this multimap
     * @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. Empty collection will be added to resulting list if this multimap 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. Empty collection will be added to resulting list if this multimap contains no mapping for the key.
     * @throws ClassCastException if the key is of an inappropriate type for this multimap
     * @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);
}
{code}

{code:title=IgniteSetMultimap.java|borderStyle=solid}
public interface IgniteSetMultimap<K, V> extends IgniteMultimap<K, V> {

    /**
     * {@inheritDoc}
     *
     * <p>Because a {@code IgniteSetMultimap} has unique values for a given key, this
     * method returns a {@link Set}, instead of the {@link java.util.Collection}
     * specified in the {@link IgniteMultimap} interface.
     */
    @Override Set<V> get(K key);

    /**
     * {@inheritDoc}
     *
     * <p>Because a {@code IgniteSetMultimap} has unique values for a given key, this
     * method returns a {@link Set}, instead of the {@link java.util.Collection}
     * specified in the {@link IgniteMultimap} interface.
     */
    @Override Set<V> remove(K key);

    /**
     * {@inheritDoc}
     *
     * <p>Because a {@code IgniteSetMultimap} has unique values for a given key, this
     * method returns a {@link Set}, instead of the {@link java.util.Collection}
     * specified in the {@link IgniteMultimap} interface.
     *
     * <p>Any duplicates in {@code values} will be stored in the multimap once.
     */
    @Override Set<V> replaceValues(K key, Iterable<? extends V> values);

    /**
     * {@inheritDoc}
     *
     * <p>Because a {@code IgniteSetMultimap} has unique values for a given key, this
     * method returns a {@link Set}, instead of the {@link java.util.Collection}
     * specified in the {@link IgniteMultimap} interface.
     */
    @Override Set<Map.Entry<K, V>> entries();
}
{code}

{code:title=IgniteSetMultimap.java|borderStyle=solid}
public interface IgniteSortedSetMultimap<K,V> extends IgniteSetMultimap<K, V> {

    /**
     * {@inheritDoc}
     *
     * <p>Because a {@code IgniteSortedSetMultimap} has unique sorted values for a given
     * key, this method returns a {@link SortedSet}, instead of the
     * {@link java.util.Collection} specified in the {@link IgniteMultimap} interface.
     */
    @Override SortedSet<V> get(K key);

    /**
     * {@inheritDoc}
     *
     * <p>Because a {@code IgniteSortedSetMultimap} has unique sorted values for a given
     * key, this method returns a {@link SortedSet}, instead of the
     * {@link java.util.Collection} specified in the {@link IgniteMultimap} interface.
     */
    @Override SortedSet<V> remove(K key);

    /**
     * {@inheritDoc}
     *
     * <p>Because a {@code IgniteSortedSetMultimap} has unique sorted values for a given
     * key, this method returns a {@link SortedSet}, instead of the
     * {@link java.util.Collection} specified in the {@link IgniteMultimap} interface.
     *
     * <p>Any duplicates in {@code values} will be stored in the multimap once.
     */
    @Override SortedSet<V> replaceValues(K key, Iterable<? extends V> values);

    /**
     * Returns the comparator that orders the multimap values, with {@code null}
     * indicating that natural ordering is used.
     */
    Comparator<? super V> valueComparator();
}
{code}

> Implement IgniteMultimap data structures
> ----------------------------------------
>
>                 Key: IGNITE-640
>                 URL: https://issues.apache.org/jira/browse/IGNITE-640
>             Project: Ignite
>          Issue Type: Sub-task
>          Components: data structures
>            Reporter: Dmitriy Setrakyan
>            Assignee: Amir Akhmedov
>
> We need to add {{IgniteMultimap}} data structure in addition to other data structures provided by Ignite. {{IgniteMultiMap}} should have similar API to {{java.util.Map}} class in JDK, but support the semantics of multiple values per key, similar to [Guava Multimap|http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/Multimap.html]. 
> However, unlike in Guava, our multi-map should work with Lists, not Collections. Lists should make it possible to support the following methods:
> {code}
> // Gets value at a certain index for a key.
> V get(K, index);
> // Gets all values for a collection of keys at a certain index.
> Map<K, V> getAll(Collection<K>, index);
> // Gets values for specified indexes for a key.
> List<V> get(K, Iterable<Integer> indexes);
> // Gets all values for a collection of keys at specified indexes.
> Map<K, Collection<V>> getAll(Collection<K>, Iterable<Integer> indexes);
> // Gets values for specified range of indexes, between min and max.
> List<V> get(K, int min, int max);
> // Gets all values for a collection of keys for a specified index range, between min and max.
> Map<K, Collection<V>> getAll(Collection<K>, int min, int max);
> // Gets all values for a specific key.
> List<V> get(K);
> // Gets all values for a collection of keys.
> Map<K, List<V>> getAll(Collection<K>);
> // Iterate through all elements with a certain index.
> Iterator<Map.Entry<K, V>> iterate(int idx);
> // Do we need this?
> Collection<IgniteTuple<Integer V>> get(K, IgniteBiPredicate<Integer, V>)
> {code}
> Multimap should also support colocated and non-colocated modes, similar to [IgniteQueue|https://github.com/apache/incubator-ignite/blob/master/modules/core/src/main/java/org/apache/ignite/IgniteQueue.java] and its implementation, [GridAtomicCacheQueueImpl|https://github.com/apache/incubator-ignite/blob/master/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/GridAtomicCacheQueueImpl.java].
> h2. Design Details
> The most natural way to implement such map, would be to store every value under a separate key in an Ignite cache. For example, let's say that we have a key {{K}} with multiple values: {{V0, V1, V2, ...}}. Then the cache should end up with the following values {{K0, V0}}, {{K1, V1}}, {{K2, V2}}, etc. This means that we need to wrap user key into our own, internal key, which will also have {{index}} field. 
> Also note that we need to collocate all the values for the same key on the same node, which means that we need to define user key K as the affinity key, like so:
> {code}
> class MultiKey<K> {
>     @CacheAffinityMapped
>     private K key;
>     int index;
> }
> {code}
> Look ups of values at specific indexes becomes very simple. Just attach a specific index to a key and do a cache lookup. Look ups for all values for a key should work as following:
> {code}
> MultiKey key;
> V v = null;
> int index = 0;
> List<V> res = new LinkedList<>();
> do {
>     v = cache.get(MultiKey(K, index));
>     if (v != null)
>         res.add(v);
>     index++;
> }
> while (v != null);
> return res;
> {code}
> We could also use batching for performance reason. In this case the batch size should be configurable.
> {code}
> int index = 0;
> List<V> res = new LinkedList<>();
> while (true) {
>     List<Key> batch = new ArrayList<>(batchSize);
>     // Populate batch.
>     for (; index < batchSize; index++)
>         batch.add(new MultiKey(K, index % batchSize);
>     Map<Key, V> batchRes = cache.getAll(batch);
>     // Potentially need to properly sort values, based on the key order,
>     // if the returning map does not do it automatically.
>     res.addAll(batchRes.values());
>     if (res.size() < batch.size())
>         break;
> }
> return res;
> {code}
> h2. Evictions
> Evictions in the {{IgniteMultiMap}} should have 2 levels: maximum number of keys, and maximum number of values for a key. The maximum number of keys should be controlled by Ignite standard eviction policy. The maximum number of values for a key should be controlled by the implementation of the multi-map. Either eviction parameter should be configurable.



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)