org.eclipse.collections.api.map.MutableMapIterable Maven / Gradle / Ivy
/*
* Copyright (c) 2019 Goldman Sachs and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v. 1.0 which accompany this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*/
package org.eclipse.collections.api.map;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import org.eclipse.collections.api.bag.MutableBag;
import org.eclipse.collections.api.block.function.Function;
import org.eclipse.collections.api.block.function.Function0;
import org.eclipse.collections.api.block.function.Function2;
import org.eclipse.collections.api.block.function.primitive.DoubleFunction;
import org.eclipse.collections.api.block.function.primitive.FloatFunction;
import org.eclipse.collections.api.block.function.primitive.IntFunction;
import org.eclipse.collections.api.block.function.primitive.LongFunction;
import org.eclipse.collections.api.block.predicate.Predicate;
import org.eclipse.collections.api.block.predicate.Predicate2;
import org.eclipse.collections.api.block.procedure.Procedure;
import org.eclipse.collections.api.block.procedure.Procedure2;
import org.eclipse.collections.api.collection.MutableCollection;
import org.eclipse.collections.api.factory.Maps;
import org.eclipse.collections.api.map.primitive.MutableObjectDoubleMap;
import org.eclipse.collections.api.map.primitive.MutableObjectLongMap;
import org.eclipse.collections.api.multimap.MutableMultimap;
import org.eclipse.collections.api.partition.PartitionMutableCollection;
import org.eclipse.collections.api.tuple.Pair;
/**
* @since 6.0
*/
public interface MutableMapIterable extends MapIterable, Map
{
/**
* This method allows mutable map the ability to add an element in the form of {@code Pair extends K, ? extends V>}.
*
* @see #put(Object, Object)
* @since 9.1.0
*/
default V putPair(Pair extends K, ? extends V> keyValuePair)
{
return this.put(keyValuePair.getOne(), keyValuePair.getTwo());
}
/**
* This method allows mutable map the ability to add an element in the form of {@code Pair extends K, ? extends V>}.
*
* @return previous value in the map for the key, or null if no value exists for the key.
* @see #put(Object, Object)
*/
default V add(Pair extends K, ? extends V> keyValuePair)
{
return this.putPair(keyValuePair);
}
/**
* Remove an entry from the map at the specified {@code key}.
*
* @return The value removed from entry at key, or null if not found.
* @see #remove(Object)
*/
V removeKey(K key);
/**
* Remove entries from the map at the specified {@code keys}.
*
* @return {@code true} if this map changed as a result of the call
* @since 10.0
*/
default boolean removeAllKeys(Set extends K> keys)
{
Objects.requireNonNull(keys);
int previousSize = this.size();
keys.forEach(this::removeKey);
return previousSize != this.size();
}
/**
* Remove an entry from the map if the {@code predicate} evaluates to true.
*
* @return true if any entry is removed.
* @since 10.0
*/
default boolean removeIf(Predicate2 super K, ? super V> predicate)
{
return this.entrySet().removeIf(entry -> predicate.accept(entry.getKey(), entry.getValue()));
}
/**
* Get and return the value in the Map at the specified key. Alternatively, if there is no value in the map at the key,
* return the result of evaluating the specified Function0, and put that value in the map at the specified key.
*/
V getIfAbsentPut(K key, Function0 extends V> function);
/**
* Get and return the value in the Map at the specified key. Alternatively, if there is no value in the map at the key,
* return the specified value, and put that value in the map at the specified key.
*
* @since 5.0
*/
V getIfAbsentPut(K key, V value);
/**
* Get and return the value in the Map at the specified key. Alternatively, if there is no value in the map for that key
* return the result of evaluating the specified Function using the specified key, and put that value in the
* map at the specified key.
*/
V getIfAbsentPutWithKey(K key, Function super K, ? extends V> function);
/**
* Get and return the value in the Map at the specified key. Alternatively, if there is no value in the map for that key
* return the result of evaluating the specified Function using the specified parameter, and put that value in the
* map at the specified key.
*/
V getIfAbsentPutWith(K key, Function super P, ? extends V> function, P parameter);
/**
* Looks up the value associated with {@code key}, applies the {@code function} to it, and replaces the value. If there
* is no value associated with {@code key}, starts it off with a value supplied by {@code factory}.
*/
V updateValue(K key, Function0 extends V> factory, Function super V, ? extends V> function);
/**
* Same as {@link #updateValue(Object, Function0, Function)} with a Function2 and specified parameter which is
* passed to the function.
*/
V updateValueWith(K key, Function0 extends V> factory, Function2 super V, ? super P, ? extends V> function, P parameter);
/**
* This method allows mutable, fixed size, and immutable maps the ability to add elements to their existing
* elements. In order to support fixed size maps, a new instance of a map would have to be returned including the
* keys and values of the original plus the additional key and value. In the case of mutable maps, the original map
* is modified and then returned. In order to use this method properly with mutable and fixed size maps the
* following approach must be taken:
*
*
* map = map.withKeyValue("new key", "new value");
*
* In the case of FixedSizeMap, a new instance will be returned by withKeyValue, and any variables that
* previously referenced the original map will need to be redirected to reference the new instance. In the case
* of a FastMap or UnifiedMap, you will be replacing the reference to map with map, since FastMap and UnifiedMap
* will both return "this" after calling put on themselves.
*
* @see #put(Object, Object)
*/
MutableMapIterable withKeyValue(K key, V value);
/**
* Similar to {@link #putAll(Map)}, but returns this instead of void
*
* @see #putAll(Map)
*
* @since 10.3.0
*/
default MutableMapIterable withMap(Map extends K, ? extends V> map)
{
this.putAll(map);
return this;
}
/**
* This method allows mutable, fixed size, and immutable maps the ability to add elements to their existing
* elements. In order to support fixed size maps, a new instance of a map would have to be returned including the
* keys and values of the original plus all of the additional keys and values. In the case of mutable maps, the
* original map is modified and then returned. In order to use this method properly with mutable and fixed size
* maps the following approach must be taken:
*
*
* map = map.withAllKeyValues(FastList.newListWith(PairImpl.of("new key", "new value")));
*
* In the case of FixedSizeMap, a new instance will be returned by withAllKeyValues, and any variables that
* previously referenced the original map will need to be redirected to reference the new instance. In the case
* of a FastMap or UnifiedMap, you will be replacing the reference to map with map, since FastMap and UnifiedMap
* will both return "this" after calling put on themselves.
*
* @see #put(Object, Object)
*/
MutableMapIterable withAllKeyValues(Iterable extends Pair extends K, ? extends V>> keyValues);
/**
* Convenience var-args version of withAllKeyValues
*
* @see #withAllKeyValues(Iterable)
*/
MutableMapIterable withAllKeyValueArguments(Pair extends K, ? extends V>... keyValuePairs);
/**
* This method allows mutable, fixed size, and immutable maps the ability to remove elements from their existing
* elements. In order to support fixed size maps, a new instance of a map would have to be returned including the
* keys and values of the original minus the key and value to be removed. In the case of mutable maps, the original
* map is modified and then returned. In order to use this method properly with mutable and fixed size maps the
* following approach must be taken:
*
*
* map = map.withoutKey("key");
*
* In the case of FixedSizeMap, a new instance will be returned by withoutKey, and any variables that previously
* referenced the original map will need to be redirected to reference the new instance. In the case of a FastMap
* or UnifiedMap, you will be replacing the reference to map with map, since FastMap and UnifiedMap will both return
* "this" after calling remove on themselves.
*
* @see #remove(Object)
*/
MutableMapIterable withoutKey(K key);
/**
* This method allows mutable, fixed size, and immutable maps the ability to remove elements from their existing
* elements. In order to support fixed size maps, a new instance of a map would have to be returned including the
* keys and values of the original minus all of the keys and values to be removed. In the case of mutable maps, the
* original map is modified and then returned. In order to use this method properly with mutable and fixed size
* maps the following approach must be taken:
*
*
* map = map.withoutAllKeys(FastList.newListWith("key1", "key2"));
*
* In the case of FixedSizeMap, a new instance will be returned by withoutAllKeys, and any variables that previously
* referenced the original map will need to be redirected to reference the new instance. In the case of a FastMap
* or UnifiedMap, you will be replacing the reference to map with map, since FastMap and UnifiedMap will both return
* "this" after calling remove on themselves.
*
* @see #remove(Object)
*/
MutableMapIterable withoutAllKeys(Iterable extends K> keys);
/**
* Creates a new instance of the same type, using the default capacity and growth parameters.
*/
MutableMapIterable newEmpty();
/**
* Returns an unmodifiable view of this map. This is the equivalent of using
* {@code Collections.unmodifiableMap(this)} only with a return type that supports the full
* iteration protocols available on {@code MutableMapIterable}. Methods which would
* mutate the underlying map will throw UnsupportedOperationExceptions.
*
* @return an unmodifiable view of this map.
* @see java.util.Collections#unmodifiableMap(Map)
*/
MutableMapIterable asUnmodifiable();
/**
* Returns a synchronized wrapper backed by this map. This is the equivalent of calling
* {@code Collections.synchronizedMap(this)} only with the more feature rich return type of
* {@code MutableMapIterable}.
*
* The preferred way of iterating over a synchronized map is to use the forEachKey(), forEachValue()
* and forEachKeyValue() methods which are properly synchronized internally.
*
* MutableMap synchedMap = map.asSynchronized();
*
* synchedMap.forEachKey(key -> ... );
* synchedMap.forEachValue(value -> ... );
* synchedMap.forEachKeyValue((key, value) -> ... );
*
*
* If you want to iterate imperatively over the keySet(), values(), or entrySet(), you will
* need to protect the iteration by wrapping the code in a synchronized block on the map.
*
* @see java.util.Collections#synchronizedMap(Map)
*/
MutableMapIterable asSynchronized();
/**
* Returns an immutable copy of this map.
* If the map is immutable, it returns itself.
*/
@Override
ImmutableMapIterable toImmutable();
// TODO
// MutableSetIterable keySet();
@Override
MutableMapIterable tap(Procedure super V> procedure);
@Override
MutableMapIterable flipUniqueValues();
@Override
MutableMultimap flip();
@Override
MutableMapIterable select(Predicate2 super K, ? super V> predicate);
@Override
MutableMapIterable reject(Predicate2 super K, ? super V> predicate);
@Override
MutableMapIterable collect(Function2 super K, ? super V, Pair> function);
@Override
MutableMapIterable collectValues(Function2 super K, ? super V, ? extends R> function);
@Override
MutableCollection select(Predicate super V> predicate);
@Override
MutableCollection selectWith(Predicate2 super V, ? super P> predicate, P parameter);
@Override
MutableCollection reject(Predicate super V> predicate);
@Override
MutableCollection rejectWith(Predicate2 super V, ? super P> predicate, P parameter);
@Override
PartitionMutableCollection partition(Predicate super V> predicate);
@Override
MutableCollection selectInstancesOf(Class clazz);
@Override
MutableObjectLongMap sumByInt(Function super V, ? extends V1> groupBy, IntFunction super V> function);
@Override
MutableObjectDoubleMap sumByFloat(Function super V, ? extends V1> groupBy, FloatFunction super V> function);
@Override
MutableObjectLongMap sumByLong(Function super V, ? extends V1> groupBy, LongFunction super V> function);
@Override
MutableObjectDoubleMap sumByDouble(Function super V, ? extends V1> groupBy, DoubleFunction super V> function);
/**
* @since 9.0
*/
@Override
default MutableBag countBy(Function super V, ? extends V1> function)
{
return this.asLazy().collect(function).toBag();
}
/**
* @since 9.0
*/
@Override
default MutableBag countByWith(Function2 super V, ? super P, ? extends V1> function, P parameter)
{
return this.asLazy().collectWith(function, parameter).toBag();
}
/**
* @since 10.0.0
*/
@Override
default MutableBag countByEach(Function super V, ? extends Iterable> function)
{
return this.asLazy().flatCollect(function).toBag();
}
@Override
MutableMultimap groupBy(Function super V, ? extends V1> function);
@Override
MutableMultimap groupByEach(Function super V, ? extends Iterable> function);
@Override
MutableMapIterable groupByUniqueKey(Function super V, ? extends V1> function);
@Override
MutableCollection> zip(Iterable that);
@Override
MutableCollection> zipWithIndex();
// TODO: Return MutableMapIterable
@Override
default MutableMap aggregateInPlaceBy(
Function super V, ? extends KK> groupBy,
Function0 extends VV> zeroValueFactory,
Procedure2 super VV, ? super V> mutatingAggregator)
{
MutableMap map = Maps.mutable.empty();
this.forEach(each ->
{
KK key = groupBy.valueOf(each);
VV value = map.getIfAbsentPut(key, zeroValueFactory);
mutatingAggregator.value(value, each);
});
return map;
}
// TODO: Return MutableMapIterable
@Override
default MutableMap aggregateBy(
Function super V, ? extends KK> groupBy,
Function0 extends VV> zeroValueFactory,
Function2 super VV, ? super V, ? extends VV> nonMutatingAggregator)
{
return this.aggregateBy(
groupBy,
zeroValueFactory,
nonMutatingAggregator,
Maps.mutable.empty());
}
}