You could even grow your own:
public class FilteredMap<K, V> extends AbstractMap<K, V> implements Map<K, V> {
// The map I wrap.
private final Map<K, V> map;
// The filter.
private final Set<K> filter;
public FilteredMap(Map<K, V> map, Set<K> filter) {
this.map = map;
this.filter = filter;
}
@Override
public Set<Entry<K, V>> entrySet() {
// Make a new one to break the bond with the underlying map.
Set<Entry<K, V>> entries = new HashSet<>(map.entrySet());
Set<Entry<K, V>> remove = new HashSet<>();
for (Entry<K, V> entry : entries) {
if (!filter.contains(entry.getKey())) {
remove.add(entry);
}
}
entries.removeAll(remove);
return entries;
}
}
public void test() {
Map<String, String> map = new HashMap<>();
map.put("1", "One");
map.put("2", "Two");
map.put("3", "Three");
Set<String> filter = new HashSet<>();
filter.add("1");
filter.add("2");
Map<String, String> filtered = new FilteredMap<>(map, filter);
System.out.println(filtered);
}
If you're concerned about all of the copying you could also grow a filtered Set
and a filterd Iterator
instead.
public interface Filter<T> {
public boolean accept(T t);
}
public class FilteredIterator<T> implements Iterator<T> {
// The Iterator
private final Iterator<T> i;
// The filter.
private final Filter<T> filter;
// The next.
private T next = null;
public FilteredIterator(Iterator<T> i, Filter<T> filter) {
this.i = i;
this.filter = filter;
}
@Override
public boolean hasNext() {
while (next == null && i.hasNext()) {
T n = i.next();
if (filter.accept(n)) {
next = n;
}
}
return next != null;
}
@Override
public T next() {
T n = next;
next = null;
return n;
}
}
public class FilteredSet<K> extends AbstractSet<K> implements Set<K> {
// The Set
private final Set<K> set;
// The filter.
private final Filter<K> filter;
public FilteredSet(Set<K> set, Filter<K> filter) {
this.set = set;
this.filter = filter;
}
@Override
public Iterator<K> iterator() {
return new FilteredIterator(set.iterator(), filter);
}
@Override
public int size() {
int n = 0;
Iterator<K> i = iterator();
while (i.hasNext()) {
i.next();
n += 1;
}
return n;
}
}
public class FilteredMap<K, V> extends AbstractMap<K, V> implements Map<K, V> {
// The map I wrap.
private final Map<K, V> map;
// The filter.
private final Filter<K> filter;
public FilteredMap(Map<K, V> map, Filter<K> filter) {
this.map = map;
this.filter = filter;
}
@Override
public Set<Entry<K, V>> entrySet() {
return new FilteredSet<>(map.entrySet(), new Filter<Entry<K, V>>() {
@Override
public boolean accept(Entry<K, V> t) {
return filter.accept(t.getKey());
}
});
}
}
public void test() {
Map<String, String> map = new HashMap<>();
map.put("1", "One");
map.put("2", "Two");
map.put("3", "Three");
Set<String> filter = new HashSet<>();
filter.add("1");
filter.add("2");
Map<String, String> filtered = new FilteredMap<>(map, new Filter<String>() {
@Override
public boolean accept(String t) {
return filter.contains(t);
}
});
System.out.println(filtered);
}