org.infinispan.commons.util.InfinispanCollections Maven / Gradle / Ivy
package org.infinispan.commons.util;
import static java.util.Collections.singletonMap;
import static java.util.Collections.unmodifiableMap;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Supplier;
/**
* Static helpers for Infinispan-specific collections
*
* @author Manik Surtani
* @since 4.0
*/
public final class InfinispanCollections {
private InfinispanCollections() {
// ensuring non-instantiability
}
/**
* A function that converts a type into another one.
*
* @param Input type.
* @param Output type.
*/
public interface Function {
/**
* Transforms an instance of the given input into an instace of the
* type to be returned.
*
* @param input Instance of the input type.
* @return Instance of the output type.
*/
T transform(E input);
}
/**
* A function that converts an entry into a key/value pair for use in a map.
* @param generated key
* @param generated value
* @param entry input
*/
public interface MapMakerFunction {
/**
* Transforms the given input into a key/value pair for use in a map
* @param input instance of the input type
* @return a Map.Entry parameterized with K and V
*/
Map.Entry transform(E input);
}
/**
* Given a map of well known key/value types, it makes a shallow copy of it
* while at the same time transforming it's value type to a desired output
* type. The transformation of the value type is done using a given a
* function.
*
* @param input contains the input key/value pair map
* @param f function instance to use to transform the value part of the map
* @param input map's key type
* @param desired output type of the map's value
* @param input map's value type
* @return a shallow copy of the input Map with all its values transformed.
*/
public static Map transformMapValue(Map input, Function f) {
// This screams for a map function! Gimme functional programming pleasee...
if (input.isEmpty()) return Collections.emptyMap();
if (input.size() == 1) {
Map.Entry single = input.entrySet().iterator().next();
return singletonMap(single.getKey(), f.transform(single.getValue()));
} else {
Map copy = new HashMap<>(input.size());
for (Map.Entry entry : input.entrySet())
copy.put(entry.getKey(), f.transform(entry.getValue()));
return unmodifiableMap(copy);
}
}
/**
* Given a collection, transforms the collection to a map given a {@link MapMakerFunction}
*
* @param input contains a collection of type E
* @param f MapMakerFunction instance to use to transform the collection to a key/value pair
* @param output map's key type
* @param output type of the map's value
* @param input collection's entry type
* @return a Map with keys and values generated from the input collection
*/
public static Map transformCollectionToMap(Collection extends E> input, MapMakerFunction f) {
// This screams for a map function! Gimme functional programming pleasee...
if (input.isEmpty()) return Collections.emptyMap();
if (input.size() == 1) {
E single = input.iterator().next();
Map.Entry entry = f.transform(single);
return singletonMap(entry.getKey(), entry.getValue());
} else {
Map map = new HashMap<>(input.size());
for (E e : input) {
Map.Entry entry = f.transform(e);
map.put(entry.getKey(), entry.getValue());
}
return unmodifiableMap(map);
}
}
/**
* Returns the elements that are present in s1 but which are not present
* in s2, without changing the contents of neither s1, nor s2.
*
* @param s1 first set
* @param s2 second set
* @param type of objects in Set
* @return the elements in s1 that are not in s2
*/
public static Set difference(Set extends E> s1, Set extends E> s2) {
Set copy1 = new HashSet<>(s1);
copy1.removeAll(new HashSet<>(s2));
return copy1;
}
public static boolean containsAny(Collection haystack, Collection needles) {
for (T element : needles) {
if (haystack.contains(element))
return true;
}
return false;
}
public static void forEach(T[] array, Consumer consumer) {
final int size = Objects.requireNonNull(array, "Array must be non-null.").length;
for (int i = 0; i < size; ++i) {
consumer.accept(array[i]);
}
}
public static void assertNotNullEntries(Map, ?> map, String name) {
Objects.requireNonNull(map, () -> "Map '" + name + "' must be non null.");
Supplier keySupplier = () -> "Map '" + name + "' contains null key.";
Supplier valueSupplier = () -> "Map '" + name + "' contains null value.";
map.forEach((k, v) -> {
Objects.requireNonNull(k, keySupplier);
Objects.requireNonNull(v, valueSupplier);
});
}
public static void assertNotNullEntries(Collection> collection, String name) {
Objects.requireNonNull(collection, () -> "Collection '" + name + "' must be non null.");
Supplier entrySupplier = () -> "Collection '" + name + "' contains null entry.";
collection.forEach(k -> Objects.requireNonNull(k, entrySupplier));
}
public static Map mergeMaps(Map one, Map second) {
if (one == null) {
return second;
} else if (second == null) {
return one;
} else {
one.putAll(second);
return one;
}
}
public static List mergeLists(List one, List second) {
if (one == null) {
return second;
} else if (second == null) {
return one;
} else {
one.addAll(second);
return one;
}
}
public static Set