io.vavr.collection.HashMap Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of vavr Show documentation
Show all versions of vavr Show documentation
Vavr is an object-functional library for Java 8+
/* __ __ __ __ __ ___
* \ \ / / \ \ / / __/
* \ \/ / /\ \ \/ / /
* \____/__/ \__\____/__/
*
* Copyright 2014-2019 Vavr, http://vavr.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.vavr.collection;
import io.vavr.Tuple;
import io.vavr.Tuple2;
import io.vavr.control.Option;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.function.*;
import java.util.stream.Collector;
/**
* An immutable {@code HashMap} implementation based on a
* Hash array mapped trie (HAMT).
*
* @author Ruslan Sennov, Patryk Najda, Daniel Dietrich
*/
public final class HashMap implements Map, Serializable {
private static final long serialVersionUID = 1L;
private static final HashMap, ?> EMPTY = new HashMap<>(HashArrayMappedTrie.empty());
private final HashArrayMappedTrie trie;
private HashMap(HashArrayMappedTrie trie) {
this.trie = trie;
}
/**
* Returns a {@link java.util.stream.Collector} which may be used in conjunction with
* {@link java.util.stream.Stream#collect(java.util.stream.Collector)} to obtain a {@link HashMap}.
*
* @param The key type
* @param The value type
* @return A {@link HashMap} Collector.
*/
public static Collector, ArrayList>, HashMap> collector() {
final Supplier>> supplier = ArrayList::new;
final BiConsumer>, Tuple2> accumulator = ArrayList::add;
final BinaryOperator>> combiner = (left, right) -> {
left.addAll(right);
return left;
};
final Function>, HashMap> finisher = HashMap::ofEntries;
return Collector.of(supplier, accumulator, combiner, finisher);
}
/**
* Returns a {@link java.util.stream.Collector} which may be used in conjunction with
* {@link java.util.stream.Stream#collect(java.util.stream.Collector)} to obtain a {@link HashMap}.
*
* @param keyMapper The key mapper
* @param The key type
* @param The value type
* @param Initial {@link java.util.stream.Stream} elements type
* @return A {@link HashMap} Collector.
*/
public static Collector, HashMap> collector(Function super T, ? extends K> keyMapper) {
Objects.requireNonNull(keyMapper, "keyMapper is null");
return HashMap.collector(keyMapper, v -> v);
}
/**
* Returns a {@link java.util.stream.Collector} which may be used in conjunction with
* {@link java.util.stream.Stream#collect(java.util.stream.Collector)} to obtain a {@link HashMap}.
*
* @param keyMapper The key mapper
* @param valueMapper The value mapper
* @param The key type
* @param The value type
* @param Initial {@link java.util.stream.Stream} elements type
* @return A {@link HashMap} Collector.
*/
public static Collector, HashMap> collector(
Function super T, ? extends K> keyMapper, Function super T, ? extends V> valueMapper) {
Objects.requireNonNull(keyMapper, "keyMapper is null");
Objects.requireNonNull(valueMapper, "valueMapper is null");
final Supplier> supplier = ArrayList::new;
final BiConsumer, T> accumulator = ArrayList::add;
final BinaryOperator> combiner = (left, right) -> {
left.addAll(right);
return left;
};
final Function, HashMap> finisher = arr -> HashMap.ofEntries(Iterator.ofAll(arr)
.map(t -> Tuple.of(keyMapper.apply(t), valueMapper.apply(t))));
return Collector.of(supplier, accumulator, combiner, finisher);
}
@SuppressWarnings("unchecked")
public static HashMap empty() {
return (HashMap) EMPTY;
}
/**
* Narrows a widened {@code HashMap extends K, ? extends V>} to {@code HashMap}
* by performing a type-safe cast. This is eligible because immutable/read-only
* collections are covariant.
*
* @param hashMap A {@code HashMap}.
* @param Key type
* @param Value type
* @return the given {@code hashMap} instance as narrowed type {@code HashMap}.
*/
@SuppressWarnings("unchecked")
public static HashMap narrow(HashMap extends K, ? extends V> hashMap) {
return (HashMap) hashMap;
}
/**
* Returns a singleton {@code HashMap}, i.e. a {@code HashMap} of one element.
*
* @param entry A map entry.
* @param The key type
* @param The value type
* @return A new Map containing the given entry
*/
public static HashMap of(Tuple2 extends K, ? extends V> entry) {
return new HashMap<>(HashArrayMappedTrie. empty().put(entry._1, entry._2));
}
/**
* Returns a {@code HashMap}, from a source java.util.Map.
*
* @param map A map
* @param The key type
* @param The value type
* @return A new Map containing the given map
*/
public static HashMap ofAll(java.util.Map extends K, ? extends V> map) {
Objects.requireNonNull(map, "map is null");
HashArrayMappedTrie tree = HashArrayMappedTrie.empty();
for (java.util.Map.Entry extends K, ? extends V> entry : map.entrySet()) {
tree = tree.put(entry.getKey(), entry.getValue());
}
return wrap(tree);
}
/**
* Returns a {@code HashMap}, from entries mapped from stream.
*
* @param stream the source stream
* @param keyMapper the key mapper
* @param valueMapper the value mapper
* @param The stream element type
* @param The key type
* @param The value type
* @return A new Map
*/
public static HashMap ofAll(java.util.stream.Stream extends T> stream,
Function super T, ? extends K> keyMapper,
Function super T, ? extends V> valueMapper) {
return Maps.ofStream(empty(), stream, keyMapper, valueMapper);
}
/**
* Returns a {@code HashMap}, from entries mapped from stream.
*
* @param stream the source stream
* @param entryMapper the entry mapper
* @param The stream element type
* @param The key type
* @param The value type
* @return A new Map
*/
public static HashMap ofAll(java.util.stream.Stream extends T> stream,
Function super T, Tuple2 extends K, ? extends V>> entryMapper) {
return Maps.ofStream(empty(), stream, entryMapper);
}
/**
* Returns a singleton {@code HashMap}, i.e. a {@code HashMap} of one element.
*
* @param key A singleton map key.
* @param value A singleton map value.
* @param The key type
* @param The value type
* @return A new Map containing the given entry
*/
public static HashMap of(K key, V value) {
return new HashMap<>(HashArrayMappedTrie. empty().put(key, value));
}
/**
* Creates a HashMap of the given list of key-value pairs.
*
* @param k1 a key for the map
* @param v1 the value for k1
* @param k2 a key for the map
* @param v2 the value for k2
* @param The key type
* @param The value type
* @return A new Map containing the given entries
*/
public static HashMap of(K k1, V v1, K k2, V v2) {
return of(k1, v1).put(k2, v2);
}
/**
* Creates a HashMap of the given list of key-value pairs.
*
* @param k1 a key for the map
* @param v1 the value for k1
* @param k2 a key for the map
* @param v2 the value for k2
* @param k3 a key for the map
* @param v3 the value for k3
* @param The key type
* @param The value type
* @return A new Map containing the given entries
*/
public static HashMap of(K k1, V v1, K k2, V v2, K k3, V v3) {
return of(k1, v1, k2, v2).put(k3, v3);
}
/**
* Creates a HashMap of the given list of key-value pairs.
*
* @param The key type
* @param The value type
* @param k1 a key for the map
* @param v1 the value for k1
* @param k2 a key for the map
* @param v2 the value for k2
* @param k3 a key for the map
* @param v3 the value for k3
* @param k4 a key for the map
* @param v4 the value for k4
* @return A new Map containing the given entries
*/
public static HashMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
return of(k1, v1, k2, v2, k3, v3).put(k4, v4);
}
/**
* Creates a HashMap of the given list of key-value pairs.
*
* @param k1 a key for the map
* @param v1 the value for k1
* @param k2 a key for the map
* @param v2 the value for k2
* @param k3 a key for the map
* @param v3 the value for k3
* @param k4 a key for the map
* @param v4 the value for k4
* @param k5 a key for the map
* @param v5 the value for k5
* @param The key type
* @param The value type
* @return A new Map containing the given entries
*/
public static HashMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
return of(k1, v1, k2, v2, k3, v3, k4, v4).put(k5, v5);
}
/**
* Creates a HashMap of the given list of key-value pairs.
*
* @param k1 a key for the map
* @param v1 the value for k1
* @param k2 a key for the map
* @param v2 the value for k2
* @param k3 a key for the map
* @param v3 the value for k3
* @param k4 a key for the map
* @param v4 the value for k4
* @param k5 a key for the map
* @param v5 the value for k5
* @param k6 a key for the map
* @param v6 the value for k6
* @param The key type
* @param The value type
* @return A new Map containing the given entries
*/
public static HashMap of(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 of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5).put(k6, v6);
}
/**
* Creates a HashMap of the given list of key-value pairs.
*
* @param k1 a key for the map
* @param v1 the value for k1
* @param k2 a key for the map
* @param v2 the value for k2
* @param k3 a key for the map
* @param v3 the value for k3
* @param k4 a key for the map
* @param v4 the value for k4
* @param k5 a key for the map
* @param v5 the value for k5
* @param k6 a key for the map
* @param v6 the value for k6
* @param k7 a key for the map
* @param v7 the value for k7
* @param The key type
* @param The value type
* @return A new Map containing the given entries
*/
public static HashMap of(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 of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6).put(k7, v7);
}
/**
* Creates a HashMap of the given list of key-value pairs.
*
* @param k1 a key for the map
* @param v1 the value for k1
* @param k2 a key for the map
* @param v2 the value for k2
* @param k3 a key for the map
* @param v3 the value for k3
* @param k4 a key for the map
* @param v4 the value for k4
* @param k5 a key for the map
* @param v5 the value for k5
* @param k6 a key for the map
* @param v6 the value for k6
* @param k7 a key for the map
* @param v7 the value for k7
* @param k8 a key for the map
* @param v8 the value for k8
* @param The key type
* @param The value type
* @return A new Map containing the given entries
*/
public static HashMap of(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 of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7).put(k8, v8);
}
/**
* Creates a HashMap of the given list of key-value pairs.
*
* @param k1 a key for the map
* @param v1 the value for k1
* @param k2 a key for the map
* @param v2 the value for k2
* @param k3 a key for the map
* @param v3 the value for k3
* @param k4 a key for the map
* @param v4 the value for k4
* @param k5 a key for the map
* @param v5 the value for k5
* @param k6 a key for the map
* @param v6 the value for k6
* @param k7 a key for the map
* @param v7 the value for k7
* @param k8 a key for the map
* @param v8 the value for k8
* @param k9 a key for the map
* @param v9 the value for k9
* @param The key type
* @param The value type
* @return A new Map containing the given entries
*/
public static HashMap of(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 of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8).put(k9, v9);
}
/**
* Creates a HashMap of the given list of key-value pairs.
*
* @param k1 a key for the map
* @param v1 the value for k1
* @param k2 a key for the map
* @param v2 the value for k2
* @param k3 a key for the map
* @param v3 the value for k3
* @param k4 a key for the map
* @param v4 the value for k4
* @param k5 a key for the map
* @param v5 the value for k5
* @param k6 a key for the map
* @param v6 the value for k6
* @param k7 a key for the map
* @param v7 the value for k7
* @param k8 a key for the map
* @param v8 the value for k8
* @param k9 a key for the map
* @param v9 the value for k9
* @param k10 a key for the map
* @param v10 the value for k10
* @param The key type
* @param The value type
* @return A new Map containing the given entries
*/
public static HashMap of(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 of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9).put(k10, v10);
}
/**
* Returns an HashMap containing {@code n} values of a given Function {@code f}
* over a range of integer values from 0 to {@code n - 1}.
*
* @param The key type
* @param The value type
* @param n The number of elements in the HashMap
* @param f The Function computing element values
* @return An HashMap consisting of elements {@code f(0),f(1), ..., f(n - 1)}
* @throws NullPointerException if {@code f} is null
*/
@SuppressWarnings("unchecked")
public static HashMap tabulate(int n, Function super Integer, ? extends Tuple2 extends K, ? extends V>> f) {
Objects.requireNonNull(f, "f is null");
return ofEntries(Collections.tabulate(n, (Function super Integer, ? extends Tuple2>) f));
}
/**
* Returns a HashMap containing tuples returned by {@code n} calls to a given Supplier {@code s}.
*
* @param The key type
* @param The value type
* @param n The number of elements in the HashMap
* @param s The Supplier computing element values
* @return An HashMap of size {@code n}, where each element contains the result supplied by {@code s}.
* @throws NullPointerException if {@code s} is null
*/
@SuppressWarnings("unchecked")
public static HashMap fill(int n, Supplier extends Tuple2 extends K, ? extends V>> s) {
Objects.requireNonNull(s, "s is null");
return ofEntries(Collections.fill(n, (Supplier extends Tuple2>) s));
}
/**
* Creates a HashMap of the given entries.
*
* @param entries Map entries
* @param The key type
* @param The value type
* @return A new Map containing the given entries
*/
@SafeVarargs
public static HashMap ofEntries(java.util.Map.Entry extends K, ? extends V>... entries) {
Objects.requireNonNull(entries, "entries is null");
HashArrayMappedTrie trie = HashArrayMappedTrie.empty();
for (java.util.Map.Entry extends K, ? extends V> entry : entries) {
trie = trie.put(entry.getKey(), entry.getValue());
}
return wrap(trie);
}
/**
* Creates a HashMap of the given entries.
*
* @param entries Map entries
* @param The key type
* @param The value type
* @return A new Map containing the given entries
*/
@SafeVarargs
public static HashMap ofEntries(Tuple2 extends K, ? extends V>... entries) {
Objects.requireNonNull(entries, "entries is null");
HashArrayMappedTrie trie = HashArrayMappedTrie.empty();
for (Tuple2 extends K, ? extends V> entry : entries) {
trie = trie.put(entry._1, entry._2);
}
return wrap(trie);
}
/**
* Creates a HashMap of the given entries.
*
* @param entries Map entries
* @param The key type
* @param The value type
* @return A new Map containing the given entries
*/
@SuppressWarnings("unchecked")
public static HashMap ofEntries(Iterable extends Tuple2 extends K, ? extends V>> entries) {
Objects.requireNonNull(entries, "entries is null");
if (entries instanceof HashMap) {
return (HashMap) entries;
} else {
HashArrayMappedTrie trie = HashArrayMappedTrie.empty();
for (Tuple2 extends K, ? extends V> entry : entries) {
trie = trie.put(entry._1, entry._2);
}
return trie.isEmpty() ? empty() : wrap(trie);
}
}
@Override
public HashMap bimap(Function super K, ? extends K2> keyMapper, Function super V, ? extends V2> valueMapper) {
Objects.requireNonNull(keyMapper, "keyMapper is null");
Objects.requireNonNull(valueMapper, "valueMapper is null");
final Iterator> entries = iterator().map(entry -> Tuple.of(keyMapper.apply(entry._1), valueMapper.apply(entry._2)));
return HashMap.ofEntries(entries);
}
@Override
public Tuple2> computeIfAbsent(K key, Function super K, ? extends V> mappingFunction) {
return Maps.computeIfAbsent(this, key, mappingFunction);
}
@Override
public Tuple2