aQute.lib.collections.MultiMap Maven / Gradle / Ivy
The newest version!
package aQute.lib.collections;
import static java.util.stream.Collectors.toList;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Formatter;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Stream;
public class MultiMap implements Map> {
private final boolean noduplicates;
private final Class keyClass;
private final Class valueClass;
private final Map> map;
public MultiMap() {
this(false);
}
@SuppressWarnings("unchecked")
public MultiMap(boolean noduplicates) {
this((Class) Object.class, (Class) Object.class, noduplicates);
}
@SuppressWarnings("unchecked")
public MultiMap(Class extends K> keyClass, Class extends V> valueClass, boolean noduplicates) {
this.noduplicates = noduplicates;
this.keyClass = (Class) keyClass;
this.valueClass = (Class) valueClass;
this.map = new LinkedHashMap<>();
}
public MultiMap(Map extends K, ? extends Collection extends V>> other) {
this();
addAll(other);
}
public MultiMap(MultiMap other) {
this(other.keyClass, other.valueClass, other.noduplicates);
addAll(other);
}
private List newValue(K key) {
if (valueClass != Object.class) {
return Collections.checkedList(new ArrayList<>(), valueClass);
}
return new ArrayList<>();
}
public boolean add(K key, V value) {
assert keyClass.isInstance(key);
assert valueClass.isInstance(value);
List values = computeIfAbsent(key, this::newValue);
if (noduplicates && values.contains(value)) {
return false;
}
return values.add(value);
}
public boolean addAll(K key, Collection extends V> value) {
assert keyClass.isInstance(key);
if ((value == null) || value.isEmpty()) {
return false;
}
List values = computeIfAbsent(key, this::newValue);
if (noduplicates) {
boolean added = false;
for (V v : value) {
assert valueClass.isInstance(v);
if (!values.contains(v)) {
values.add(v);
added = true;
}
}
return added;
}
return values.addAll(value);
}
public boolean addAll(Map extends K, ? extends Collection extends V>> other) {
boolean added = false;
for (Map.Entry extends K, ? extends Collection extends V>> entry : other.entrySet()) {
if (addAll(entry.getKey(), entry.getValue())) {
added = true;
}
}
return added;
}
public boolean removeValue(K key, V value) {
assert keyClass.isInstance(key);
assert valueClass.isInstance(value);
List values = get(key);
if (values == null) {
return false;
}
boolean result = values.remove(value);
if (values.isEmpty()) {
remove(key);
}
return result;
}
public boolean removeAll(K key, Collection extends V> value) {
assert keyClass.isInstance(key);
List values = get(key);
if (values == null) {
return false;
}
boolean result = values.removeAll(value);
if (values.isEmpty()) {
remove(key);
}
return result;
}
public Iterator iterate(K key) {
assert keyClass.isInstance(key);
List values = get(key);
if (values == null) {
return Collections.emptyIterator();
}
return values.iterator();
}
private Stream valuesStream() {
return values().stream()
.filter(Objects::nonNull)
.flatMap(List::stream);
}
public Iterator all() {
return valuesStream().iterator();
}
public Map flatten() {
Map flattened = new LinkedHashMap<>();
for (Map.Entry> entry : entrySet()) {
List values = entry.getValue();
if ((values == null) || values.isEmpty()) {
continue;
}
flattened.put(entry.getKey(), values.get(0));
}
return flattened;
}
public MultiMap transpose() {
return transpose(false);
}
public MultiMap transpose(boolean noduplicates) {
MultiMap transposed = new MultiMap<>(valueClass, keyClass, noduplicates);
for (Map.Entry> entry : entrySet()) {
List keys = entry.getValue();
if (keys == null) {
continue;
}
K value = entry.getKey();
for (V key : keys) {
if (key == null) {
continue;
}
transposed.add(key, value);
}
}
return transposed;
}
/**
* Return a collection with all values
*
* @return all values
*/
public List allValues() {
return valuesStream().collect(toList());
}
public static > String format(Map> map) {
try (Formatter f = new Formatter()) {
SortedList keys = new SortedList<>(map.keySet());
for (Object key : keys) {
String name = key.toString();
SortedList
© 2015 - 2024 Weber Informatics LLC | Privacy Policy