es.iti.wakamiti.api.util.MapUtils Maven / Gradle / Ivy
The newest version!
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package es.iti.wakamiti.api.util;
import java.util.AbstractMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collector;
@SuppressWarnings({"java:S107"})
public class MapUtils {
private MapUtils() {
}
/**
* Returns a linked map containing zero mappings.
* See Unmodifiable Maps for details.
*
* @param the {@code Map}'s key type
* @param the {@code Map}'s value type
* @return an empty {@code Map}
*/
public static Map map() {
return new MapN<>();
}
/**
* Returns a linked map containing one mapping.
* See {@link LinkedHashMap} for details.
*
* @param the {@code Map}'s key type
* @param the {@code Map}'s value type
* @return a {@code Map} containing the specified mappings
* @throws IllegalArgumentException if there are any duplicate keys
* @throws NullPointerException if any key or value is {@code null}
*/
public static Map map(K k, V v) {
return new MapN<>(k, v);
}
/**
* Returns a linked map containing two mappings.
* See {@link LinkedHashMap} for details.
*
* @param the {@code Map}'s key type
* @param the {@code Map}'s value type
* @param k1 the first mapping's key
* @param v1 the first mapping's value
* @param k2 the second mapping's key
* @param v2 the second mapping's value
* @return a {@code Map} containing the specified mappings
* @throws IllegalArgumentException if there are any duplicate keys
* @throws NullPointerException if any key or value is {@code null}
*/
public static Map map(K k1, V v1, K k2, V v2) {
return new MapN<>(k1, v1, k2, v2);
}
/**
* Returns a linked map containing three mappings.
* See {@link LinkedHashMap} for details.
*
* @param the {@code Map}'s key type
* @param the {@code Map}'s value type
* @param k1 the first mapping's key
* @param v1 the first mapping's value
* @param k2 the second mapping's key
* @param v2 the second mapping's value
* @param k3 the third mapping's key
* @param v3 the third mapping's value
* @return a {@code Map} containing the specified mappings
* @throws IllegalArgumentException if there are any duplicate keys
* @throws NullPointerException if any key or value is {@code null}
*/
public static Map map(K k1, V v1, K k2, V v2, K k3, V v3) {
return new MapN<>(k1, v1, k2, v2, k3, v3);
}
/**
* Returns a linked map containing four mappings.
* See {@link LinkedHashMap} for details.
*
* @param the {@code Map}'s key type
* @param the {@code Map}'s value type
* @param k1 the first mapping's key
* @param v1 the first mapping's value
* @param k2 the second mapping's key
* @param v2 the second mapping's value
* @param k3 the third mapping's key
* @param v3 the third mapping's value
* @param k4 the fourth mapping's key
* @param v4 the fourth mapping's value
* @return a {@code Map} containing the specified mappings
* @throws IllegalArgumentException if there are any duplicate keys
* @throws NullPointerException if any key or value is {@code null}
*/
public static Map map(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
return new MapN<>(k1, v1, k2, v2, k3, v3, k4, v4);
}
/**
* Returns a linked map containing five mappings.
* See {@link LinkedHashMap} for details.
*
* @param the {@code Map}'s key type
* @param the {@code Map}'s value type
* @param k1 the first mapping's key
* @param v1 the first mapping's value
* @param k2 the second mapping's key
* @param v2 the second mapping's value
* @param k3 the third mapping's key
* @param v3 the third mapping's value
* @param k4 the fourth mapping's key
* @param v4 the fourth mapping's value
* @param k5 the fifth mapping's key
* @param v5 the fifth mapping's value
* @return a {@code Map} containing the specified mappings
* @throws IllegalArgumentException if there are any duplicate keys
* @throws NullPointerException if any key or value is {@code null}
*/
public static Map map(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
return new MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5);
}
/**
* Returns a linked map containing six mappings.
* See {@link LinkedHashMap} for details.
*
* @param the {@code Map}'s key type
* @param the {@code Map}'s value type
* @param k1 the first mapping's key
* @param v1 the first mapping's value
* @param k2 the second mapping's key
* @param v2 the second mapping's value
* @param k3 the third mapping's key
* @param v3 the third mapping's value
* @param k4 the fourth mapping's key
* @param v4 the fourth mapping's value
* @param k5 the fifth mapping's key
* @param v5 the fifth mapping's value
* @param k6 the sixth mapping's key
* @param v6 the sixth mapping's value
* @return a {@code Map} containing the specified mappings
* @throws IllegalArgumentException if there are any duplicate keys
* @throws NullPointerException if any key or value is {@code null}
*/
public static Map map(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
K k6, V v6) {
return new MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6);
}
/**
* Returns a linked map containing seven mappings.
* See {@link LinkedHashMap} for details.
*
* @param the {@code Map}'s key type
* @param the {@code Map}'s value type
* @param k1 the first mapping's key
* @param v1 the first mapping's value
* @param k2 the second mapping's key
* @param v2 the second mapping's value
* @param k3 the third mapping's key
* @param v3 the third mapping's value
* @param k4 the fourth mapping's key
* @param v4 the fourth mapping's value
* @param k5 the fifth mapping's key
* @param v5 the fifth mapping's value
* @param k6 the sixth mapping's key
* @param v6 the sixth mapping's value
* @param k7 the seventh mapping's key
* @param v7 the seventh mapping's value
* @return a {@code Map} containing the specified mappings
* @throws IllegalArgumentException if there are any duplicate keys
* @throws NullPointerException if any key or value is {@code null}
*/
public static Map map(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
K k6, V v6, K k7, V v7) {
return new MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7);
}
/**
* Returns a linked map containing eight mappings.
* See {@link LinkedHashMap} for details.
*
* @param the {@code Map}'s key type
* @param the {@code Map}'s value type
* @param k1 the first mapping's key
* @param v1 the first mapping's value
* @param k2 the second mapping's key
* @param v2 the second mapping's value
* @param k3 the third mapping's key
* @param v3 the third mapping's value
* @param k4 the fourth mapping's key
* @param v4 the fourth mapping's value
* @param k5 the fifth mapping's key
* @param v5 the fifth mapping's value
* @param k6 the sixth mapping's key
* @param v6 the sixth mapping's value
* @param k7 the seventh mapping's key
* @param v7 the seventh mapping's value
* @param k8 the eighth mapping's key
* @param v8 the eighth mapping's value
* @return a {@code Map} containing the specified mappings
* @throws IllegalArgumentException if there are any duplicate keys
* @throws NullPointerException if any key or value is {@code null}
*/
public static Map map(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
K k6, V v6, K k7, V v7, K k8, V v8) {
return new MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8);
}
/**
* Returns a linked map containing nine mappings.
* See {@link LinkedHashMap} for details.
*
* @param the {@code Map}'s key type
* @param the {@code Map}'s value type
* @param k1 the first mapping's key
* @param v1 the first mapping's value
* @param k2 the second mapping's key
* @param v2 the second mapping's value
* @param k3 the third mapping's key
* @param v3 the third mapping's value
* @param k4 the fourth mapping's key
* @param v4 the fourth mapping's value
* @param k5 the fifth mapping's key
* @param v5 the fifth mapping's value
* @param k6 the sixth mapping's key
* @param v6 the sixth mapping's value
* @param k7 the seventh mapping's key
* @param v7 the seventh mapping's value
* @param k8 the eighth mapping's key
* @param v8 the eighth mapping's value
* @param k9 the ninth mapping's key
* @param v9 the ninth mapping's value
* @return a {@code Map} containing the specified mappings
* @throws IllegalArgumentException if there are any duplicate keys
* @throws NullPointerException if any key or value is {@code null}
*/
public static Map map(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9) {
return new MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9);
}
/**
* Returns a linked map containing ten mappings.
* See {@link LinkedHashMap} for details.
*
* @param the {@code Map}'s key type
* @param the {@code Map}'s value type
* @param k1 the first mapping's key
* @param v1 the first mapping's value
* @param k2 the second mapping's key
* @param v2 the second mapping's value
* @param k3 the third mapping's key
* @param v3 the third mapping's value
* @param k4 the fourth mapping's key
* @param v4 the fourth mapping's value
* @param k5 the fifth mapping's key
* @param v5 the fifth mapping's value
* @param k6 the sixth mapping's key
* @param v6 the sixth mapping's value
* @param k7 the seventh mapping's key
* @param v7 the seventh mapping's value
* @param k8 the eighth mapping's key
* @param v8 the eighth mapping's value
* @param k9 the ninth mapping's key
* @param v9 the ninth mapping's value
* @param k10 the tenth mapping's key
* @param v10 the tenth mapping's value
* @return a {@code Map} containing the specified mappings
* @throws IllegalArgumentException if there are any duplicate keys
* @throws NullPointerException if any key or value is {@code null}
*/
public static Map map(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9, K k10, V v10) {
return new MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10);
}
/**
* Returns a linked map containing eleven mappings.
* See {@link LinkedHashMap} for details.
*
* @param the {@code Map}'s key type
* @param the {@code Map}'s value type
* @param k1 the first mapping's key
* @param v1 the first mapping's value
* @param k2 the second mapping's key
* @param v2 the second mapping's value
* @param k3 the third mapping's key
* @param v3 the third mapping's value
* @param k4 the fourth mapping's key
* @param v4 the fourth mapping's value
* @param k5 the fifth mapping's key
* @param v5 the fifth mapping's value
* @param k6 the sixth mapping's key
* @param v6 the sixth mapping's value
* @param k7 the seventh mapping's key
* @param v7 the seventh mapping's value
* @param k8 the eighth mapping's key
* @param v8 the eighth mapping's value
* @param k9 the ninth mapping's key
* @param v9 the ninth mapping's value
* @param k10 the tenth mapping's key
* @param v10 the tenth mapping's value
* @param k11 the eleventh mapping's key
* @param v11 the eleventh mapping's value
* @return a {@code Map} containing the specified mappings
* @throws IllegalArgumentException if there are any duplicate keys
* @throws NullPointerException if any key or value is {@code null}
*/
public static Map map(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5,
K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9, K k10, V v10,
K k11, V v11) {
return new MapN<>(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10, k11, v11);
}
/**
* Returns a linked map containing keys and values extracted from the given entries.
* The entries themselves are not stored in the map.
* See {@link LinkedHashMap} for details.
*
* @apiNote
* It is convenient to create the map entries using the {@link #entry} method.
* For example,
*
* {@code
* import static java.util.Map.entry;
*
* Map map = MapUtils.mapEntries(
* entry(1, "a"),
* entry(2, "b"),
* entry(3, "c"),
* ...
* entry(26, "z"));
* }
*
* @param the {@code Map}'s key type
* @param the {@code Map}'s value type
* @param entries {@code Map.Entry}s containing the keys and values from which the map is populated
* @return a {@code Map} containing the specified mappings
* @throws IllegalArgumentException if there are any duplicate keys
* @throws NullPointerException if any entry, key, or value is {@code null}, or if
* the {@code entries} array is {@code null}
*
* @see #entry
*/
@SafeVarargs
@SuppressWarnings("varargs")
public static Map mapEntries(Map.Entry... entries) {
if (entries.length == 0) { // implicit null check of entries array
@SuppressWarnings("unchecked")
var map = (LinkedHashMap) map();
return map;
} else if (entries.length == 1) {
// implicit null check of the array slot
return map(entries[0].getKey(), entries[0].getValue());
} else {
Object[] kva = new Object[entries.length << 1];
int a = 0;
for (Map.Entry extends K, ? extends V> entry : entries) {
// implicit null checks of each array slot
kva[a++] = entry.getKey();
kva[a++] = entry.getValue();
}
return new MapN<>(kva);
}
}
/**
* Returns a {@link Map.Entry} containing the given key and value.
* These entries are suitable for populating {@code Map} instances using the
* {@link #mapEntries MapUtils.mapEntries()} method.
* The {@code Entry} instances created by this method have the following characteristics:
*
*
* - They disallow {@code null} keys and values. Attempts to create them using a {@code null}
* key or value result in {@code NullPointerException}.
*
- They are unmodifiable. Calls to {@link Map.Entry#setValue Entry.setValue()}
* on a returned {@code Entry} result in {@code UnsupportedOperationException}.
*
- They are not serializable.
*
- They are value-based.
* Programmers should treat instances that are {@linkplain #equals(Object) equal}
* as interchangeable and should not use them for synchronization, or
* unpredictable behavior may occur. For example, in a future release,
* synchronization may fail. Callers should make no assumptions
* about the identity of the returned instances. This method is free to
* create new instances or reuse existing ones.
*
*
* @apiNote
* For a serializable {@code Entry}, see {@link AbstractMap.SimpleEntry}.
*
* @param the key's type
* @param the value's type
* @param k the key
* @param v the value
* @return an {@code Entry} containing the specified key and value
* @throws NullPointerException if the key or value is {@code null}
*
* @see #mapEntries MapUtils.mapEntries()
*/
public static Map.Entry entry(K k, V v) {
return new AbstractMap.SimpleEntry<>(k, v);
}
/**
* An array-based Map implementation.
* It must also be strictly larger than the size (the number of key-value pairs contained
* in the map) so that at least one null key is always present.
* @param the key type
* @param the value type
*/
static final class MapN extends LinkedHashMap {
MapN (Object... input) {
if ((input.length & 1) != 0) { // implicit nullcheck of input
throw new InternalError("length is odd");
}
for (int i = 0; i < input.length; i += 2) {
@SuppressWarnings("unchecked")
K k = Objects.requireNonNull((K) input[i]);
@SuppressWarnings("unchecked")
V v = (V) input[i + 1];
if (containsKey(k)) {
throw new IllegalArgumentException("duplicate key: " + k);
} else {
put(k, v);
}
}
}
}
/**
* Collects elements into a map using the specified key and value mappers.
*
* @param keyMapper A function to extract keys from elements
* @param valueMapper A function to extract values from elements
* @param The type of elements to collect
* @param The type of keys
* @param The type of values
* @return A collector that accumulates elements into a map
*/
public static , K, U> Collector> entryCollector(
Function super T, ? extends K> keyMapper,
Function super T, ? extends U> valueMapper
) {
return Collector.of(
LinkedHashMap::new,
(m, e) -> m.put(keyMapper.apply(e), valueMapper.apply(e)),
(m, r) -> m
);
}
public static Collector, ?, Map> toMap(
Function super K1, ? extends K2> keyMapper,
Function super U1, ? extends U2> valueMapper
) {
return Collector.of(
LinkedHashMap::new,
(m, e) -> m.put(keyMapper.apply(e.getKey()), valueMapper.apply(e.getValue())),
(m, r) -> m
);
}
public static Collector, ?, Map> toMap(
Function super U1, ? extends U2> valueMapper
) {
return toMap(Function.identity(), valueMapper);
}
public static Collector, ?, Map> toMap() {
return toMap(Function.identity());
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy