package edu.stanford.nlp.util;
import java.io.Serializable;
import java.util.Iterator;
import java.util.Set;
/**
* Wrap a TwoDimensionalMap as a TwoDimensionalSet.
*
* @author John Bauer
*/
public class TwoDimensionalSet<K1, K2> implements Serializable, Iterable<Pair<K1, K2>> {
private static final long serialVersionUID = 2L;
private final TwoDimensionalMap<K1, K2, Boolean> backingMap;
public TwoDimensionalSet() {
this(new TwoDimensionalMap<>());
}
public TwoDimensionalSet(TwoDimensionalMap<K1, K2, Boolean> backingMap) {
this.backingMap = backingMap;
}
public static <K1, K2> TwoDimensionalSet<K1, K2> treeSet() {
return new TwoDimensionalSet<>(TwoDimensionalMap.<K1, K2, Boolean>treeMap());
}
public static <K1, K2> TwoDimensionalSet<K1, K2> hashSet() {
return new TwoDimensionalSet<>(TwoDimensionalMap.<K1, K2, Boolean>hashMap());
}
public boolean add(K1 k1, K2 k2) {
return (backingMap.put(k1, k2, true) != null);
}
public boolean addAll(TwoDimensionalSet<? extends K1, ? extends K2> set) {
boolean result = false;
for (Pair<? extends K1, ? extends K2> pair : set) {
if (add(pair.first, pair.second)) {
result = true;
}
}
return result;
}
/**
* Adds all the keys in the given TwoDimensionalMap. Returns true iff at least one key is added.
*/
public boolean addAllKeys(TwoDimensionalMap<? extends K1, ? extends K2, ?> map) {
boolean result = false;
for (TwoDimensionalMap.Entry<? extends K1, ? extends K2, ?> entry : map) {
if (add(entry.getFirstKey(), entry.getSecondKey())) {
result = true;
}
}
return result;
}
public void clear() {
backingMap.clear();
}
public boolean contains(K1 k1, K2 k2) {
return backingMap.contains(k1, k2);
}
public boolean containsAll(TwoDimensionalSet<? extends K1, ? extends K2> set) {
for (Pair<? extends K1, ? extends K2> pair : set) {
if (!contains(pair.first, pair.second)) {
return false;
}
}
return true;
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof TwoDimensionalSet)) {
return false;
}
TwoDimensionalSet<?, ?> other = (TwoDimensionalSet) o;
return backingMap.equals(other.backingMap);
}
@Override
public int hashCode() {
return backingMap.hashCode();
}
public boolean isEmpty() {
return backingMap.isEmpty();
}
public boolean remove(K1 k1, K2 k2) {
return backingMap.remove(k1, k2);
}
public boolean removeAll(TwoDimensionalSet<? extends K1, ? extends K2> set) {
boolean removed = false;
for (Pair<? extends K1, ? extends K2> pair : set) {
if (remove(pair.first, pair.second)) {
removed = true;
}
}
return removed;
}
public int size() {
return backingMap.size();
}
public Set<K1> firstKeySet() {
return backingMap.firstKeySet();
}
public Set<K2> secondKeySet(K1 k1) {
return backingMap.getMap(k1).keySet();
}
/**
* Iterate over the map using the iterator and entry inner classes.
*/
public Iterator<Pair<K1, K2>> iterator() {
return new TwoDimensionalSetIterator<>(this);
}
static class TwoDimensionalSetIterator<K1, K2> implements Iterator<Pair<K1, K2>> {
Iterator<TwoDimensionalMap.Entry<K1, K2, Boolean>> backingIterator;
TwoDimensionalSetIterator(TwoDimensionalSet<K1, K2> set) {
backingIterator = set.backingMap.iterator();
}
public boolean hasNext() {
return backingIterator.hasNext();
}
public Pair<K1, K2> next() {
TwoDimensionalMap.Entry<K1, K2, Boolean> entry = backingIterator.next();
return Pair.makePair(entry.getFirstKey(), entry.getSecondKey());
}
public void remove() {
backingIterator.remove();
}
}
}