io.vavr.collection.LinkedHashMap 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.Objects;
import java.util.function.*;
import java.util.stream.Collector;
/**
* An immutable {@code LinkedHashMap} implementation that has predictable (insertion-order) iteration.
*
* @author Ruslan Sennov
*/
public final class LinkedHashMap implements Map, Serializable {
private static final long serialVersionUID = 1L;
private static final LinkedHashMap, ?> EMPTY = new LinkedHashMap<>(Queue.empty(), HashMap.empty());
private final Queue> list;
private final HashMap map;
private LinkedHashMap(Queue> list, HashMap map) {
this.list = list;
this.map = map;
}
/**
* 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 LinkedHashMap}.
*
* @param The key type
* @param The value type
* @return A {@link LinkedHashMap} Collector.
*/
public static Collector, ArrayList>, LinkedHashMap> collector() {
final Supplier>> supplier = ArrayList::new;
final BiConsumer>, Tuple2> accumulator = ArrayList::add;
final BinaryOperator>> combiner = (left, right) -> {
left.addAll(right);
return left;
};
final Function>, LinkedHashMap> finisher = LinkedHashMap::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 LinkedHashMap}.
*
* @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 LinkedHashMap} Collector.
*/
public static Collector, LinkedHashMap> collector(Function super T, ? extends K> keyMapper) {
Objects.requireNonNull(keyMapper, "keyMapper is null");
return LinkedHashMap.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 LinkedHashMap}.
*
* @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 LinkedHashMap} Collector.
*/
public static Collector, LinkedHashMap> 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, LinkedHashMap> finisher = arr -> LinkedHashMap.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 LinkedHashMap empty() {
return (LinkedHashMap) EMPTY;
}
/**
* Narrows a widened {@code LinkedHashMap extends K, ? extends V>} to {@code LinkedHashMap}
* by performing a type-safe cast. This is eligible because immutable/read-only
* collections are covariant.
*
* @param linkedHashMap A {@code LinkedHashMap}.
* @param Key type
* @param Value type
* @return the given {@code linkedHashMap} instance as narrowed type {@code LinkedHashMap}.
*/
@SuppressWarnings("unchecked")
public static LinkedHashMap narrow(LinkedHashMap extends K, ? extends V> linkedHashMap) {
return (LinkedHashMap) linkedHashMap;
}
/**
* Returns a singleton {@code LinkedHashMap}, i.e. a {@code LinkedHashMap} of one element.
*
* @param entry A map entry.
* @param The key type
* @param The value type
* @return A new Map containing the given entry
*/
@SuppressWarnings("unchecked")
public static LinkedHashMap of(Tuple2 extends K, ? extends V> entry) {
final HashMap map = HashMap.of(entry);
final Queue> list = Queue.of((Tuple2) entry);
return wrap(list, map);
}
/**
* Returns a {@code LinkedHashMap}, 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 LinkedHashMap ofAll(java.util.Map extends K, ? extends V> map) {
Objects.requireNonNull(map, "map is null");
LinkedHashMap result = LinkedHashMap.empty();
for (java.util.Map.Entry extends K, ? extends V> entry : map.entrySet()) {
result = result.put(entry.getKey(), entry.getValue());
}
return result;
}
/**
* Returns a {@code LinkedHashMap}, 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 LinkedHashMap 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 {@code LinkedHashMap}, 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 LinkedHashMap 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 singleton {@code LinkedHashMap}, i.e. a {@code LinkedHashMap} 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 LinkedHashMap of(K key, V value) {
final HashMap map = HashMap.of(key, value);
final Queue> list = Queue.of(Tuple.of(key, value));
return wrap(list, map);
}
/**
* Creates a LinkedHashMap 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 LinkedHashMap of(K k1, V v1, K k2, V v2) {
final HashMap map = HashMap.of(k1, v1, k2, v2);
final Queue> list = Queue.of(Tuple.of(k1, v1), Tuple.of(k2, v2));
return wrapNonUnique(list, map);
}
/**
* Creates a LinkedHashMap 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 LinkedHashMap of(K k1, V v1, K k2, V v2, K k3, V v3) {
final HashMap map = HashMap.of(k1, v1, k2, v2, k3, v3);
final Queue> list = Queue.of(Tuple.of(k1, v1), Tuple.of(k2, v2), Tuple.of(k3, v3));
return wrapNonUnique(list, map);
}
/**
* Creates a LinkedHashMap 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 The key type
* @param The value type
* @return A new Map containing the given entries
*/
public static LinkedHashMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
final HashMap map = HashMap.of(k1, v1, k2, v2, k3, v3, k4, v4);
final Queue> list = Queue.of(Tuple.of(k1, v1), Tuple.of(k2, v2), Tuple.of(k3, v3), Tuple.of(k4, v4));
return wrapNonUnique(list, map);
}
/**
* Creates a LinkedHashMap 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 LinkedHashMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
final HashMap map = HashMap.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5);
final Queue> list = Queue.of(Tuple.of(k1, v1), Tuple.of(k2, v2), Tuple.of(k3, v3), Tuple.of(k4, v4), Tuple.of(k5, v5));
return wrapNonUnique(list, map);
}
/**
* Creates a LinkedHashMap 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 LinkedHashMap 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) {
final HashMap map = HashMap.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6);
final Queue> list = Queue.of(Tuple.of(k1, v1), Tuple.of(k2, v2), Tuple.of(k3, v3), Tuple.of(k4, v4), Tuple.of(k5, v5), Tuple.of(k6, v6));
return wrapNonUnique(list, map);
}
/**
* Creates a LinkedHashMap 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 LinkedHashMap 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) {
final HashMap map = HashMap.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7);
final Queue> list = Queue.of(Tuple.of(k1, v1), Tuple.of(k2, v2), Tuple.of(k3, v3), Tuple.of(k4, v4), Tuple.of(k5, v5), Tuple.of(k6, v6), Tuple.of(k7, v7));
return wrapNonUnique(list, map);
}
/**
* Creates a LinkedHashMap 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 LinkedHashMap 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) {
final HashMap map = HashMap.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8);
final Queue> list = Queue.of(Tuple.of(k1, v1), Tuple.of(k2, v2), Tuple.of(k3, v3), Tuple.of(k4, v4), Tuple.of(k5, v5), Tuple.of(k6, v6), Tuple.of(k7, v7), Tuple.of(k8, v8));
return wrapNonUnique(list, map);
}
/**
* Creates a LinkedHashMap 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 LinkedHashMap 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) {
final HashMap map = HashMap.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9);
final Queue> list = Queue.of(Tuple.of(k1, v1), Tuple.of(k2, v2), Tuple.of(k3, v3), Tuple.of(k4, v4), Tuple.of(k5, v5), Tuple.of(k6, v6), Tuple.of(k7, v7), Tuple.of(k8, v8), Tuple.of(k9, v9));
return wrapNonUnique(list, map);
}
/**
* Creates a LinkedHashMap 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 LinkedHashMap 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) {
final HashMap map = HashMap.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10);
final Queue> list = Queue.of(Tuple.of(k1, v1), Tuple.of(k2, v2), Tuple.of(k3, v3), Tuple.of(k4, v4), Tuple.of(k5, v5), Tuple.of(k6, v6), Tuple.of(k7, v7), Tuple.of(k8, v8), Tuple.of(k9, v9), Tuple.of(k10, v10));
return wrapNonUnique(list, map);
}
/**
* Returns a LinkedHashMap 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 LinkedHashMap
* @param f The Function computing element values
* @return A LinkedHashMap consisting of elements {@code f(0),f(1), ..., f(n - 1)}
* @throws NullPointerException if {@code f} is null
*/
@SuppressWarnings("unchecked")
public static LinkedHashMap 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 LinkedHashMap 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 LinkedHashMap
* @param s The Supplier computing element values
* @return A LinkedHashMap 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 LinkedHashMap 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 LinkedHashMap 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 LinkedHashMap ofEntries(java.util.Map.Entry extends K, ? extends V>... entries) {
HashMap map = HashMap.empty();
Queue> list = Queue.empty();
for (java.util.Map.Entry extends K, ? extends V> entry : entries) {
final Tuple2 tuple = Tuple.of(entry.getKey(), entry.getValue());
map = map.put(tuple);
list = list.append(tuple);
}
return wrapNonUnique(list, map);
}
/**
* Creates a LinkedHashMap 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 LinkedHashMap ofEntries(Tuple2 extends K, ? extends V>... entries) {
final HashMap map = HashMap.ofEntries(entries);
final Queue> list = Queue.of((Tuple2[]) entries);
return wrapNonUnique(list, map);
}
/**
* Creates a LinkedHashMap 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 LinkedHashMap ofEntries(Iterable extends Tuple2 extends K, ? extends V>> entries) {
Objects.requireNonNull(entries, "entries is null");
if (entries instanceof LinkedHashMap) {
return (LinkedHashMap) entries;
} else {
HashMap map = HashMap.empty();
Queue> list = Queue.empty();
for (Tuple2 extends K, ? extends V> entry : entries) {
map = map.put(entry);
list = list.append((Tuple2) entry);
}
return wrapNonUnique(list, map);
}
}
@Override
public LinkedHashMap 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 LinkedHashMap.ofEntries(entries);
}
@Override
public Tuple2> computeIfAbsent(K key, Function super K, ? extends V> mappingFunction) {
return Maps.computeIfAbsent(this, key, mappingFunction);
}
@Override
public Tuple2