Esta es sólo una suposición, pero parte de la razón por la cual no se puede modificar una implementación no se proporcionó puede ser debido al hecho de que las interfaces NavigableSet/mapas exponen métodos mutantes que no están marcados como opcionales:
- NavigableSet.pollFirst
- NavigableSet.pollLast
- NavigableMap.pollFirstEntry
- NavigableMap.pollLastEntry
Dicho esto, parece razonable proporcionar una implementación no modificable para lanzar una UnsupportedOperationException. Eso es lo que se hace en estas implementaciones (que asumen que está utilizando Google Guava):
NavigableSet:
import static java.util.Collections.unmodifiableSortedSet;
import java.util.Collections;
import java.util.Iterator;
import java.util.NavigableSet;
import java.util.SortedSet;
import com.google.common.collect.ForwardingSortedSet;
/**
* {@link NavigableSet} equivalent of {@link Collections#unmodifiableSortedSet(SortedSet)}.
* This is unfortunately needed because {@link Collections} lacks "UnmodifiableNavigableSet"
* (see http://stackoverflow.com/questions/2577706/unmodifiable-navigableset-navigablemap-in-java
* and http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6907251).
*
* This is just a guess, but part of the reason why an unmodifiable implementation was not provided may be due to the fact that
* {@link NavigableSet} exposes mutating methods that aren't marked as optional:
* - {@link NavigableSet#pollFirst()}
* - {@link NavigableSet#pollLast()}
*
* In addition, one can't go the immutable route, as Google Guava doesn't provide an Immutable variant
* (see http://code.google.com/p/guava-libraries/issues/detail?id=664).
*
* @param <E> See {@link NavigableSet}
*/
public final class UnmodifiableNavigableSet<E> extends ForwardingSortedSet<E> implements NavigableSet<E> {
private final NavigableSet<E> delegate;
private final SortedSet<E> unmodifiableDelegate;
/**
* @param delegate See {@link ForwardingSortedSet#delegate()}.
*/
public UnmodifiableNavigableSet(NavigableSet<E> delegate) {
this.delegate = delegate;
unmodifiableDelegate = unmodifiableSortedSet(delegate);
}
/**
* @param delegate
* @return {@link #UnmodifiableNavigableSet(NavigableSet)}
* @see EffectiveJava#Static_factories_instead_of_constructors
*/
public static <E> UnmodifiableNavigableSet<E> newUnmodifiableNavigableSet(NavigableSet<E> delegate) {
return new UnmodifiableNavigableSet<E>(delegate);
}
@Override
protected SortedSet<E> delegate() {
return unmodifiableDelegate;
}
@Override
public E ceiling(E e) {
return delegate.ceiling(e);
}
@Override
public Iterator<E> descendingIterator() {
// NavigableSet.descendingIterator explicitly states this behavior.
// By doing this, we don't need to do anything extra to ensure the iterator is unmodifiable.
return descendingSet().iterator();
}
@Override
public NavigableSet<E> descendingSet() {
return newUnmodifiableNavigableSet(delegate.descendingSet());
}
@Override
public E floor(E e) {
return delegate.floor(e);
}
@Override
public NavigableSet<E> headSet(E toElement, boolean inclusive) {
return newUnmodifiableNavigableSet(delegate.headSet(toElement, inclusive));
}
@Override
public E higher(E e) {
return delegate.higher(e);
}
@Override
public E lower(E e) {
return delegate.lower(e);
}
@Override
public E pollFirst() {
throw new UnsupportedOperationException();
}
@Override
public E pollLast() {
throw new UnsupportedOperationException();
}
@Override
public NavigableSet<E> subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
return newUnmodifiableNavigableSet(delegate.subSet(fromElement, fromInclusive, toElement, toInclusive));
}
@Override
public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
return newUnmodifiableNavigableSet(delegate.tailSet(fromElement, inclusive));
}
}
NavigableMap:
import static UnmodifiableNavigableSet.newUnmodifiableNavigableSet;
import static java.util.Collections.unmodifiableSortedMap;
import java.util.AbstractMap;
import java.util.Map;
import java.util.NavigableMap;
import java.util.NavigableSet;
import java.util.SortedMap;
import com.google.common.collect.ForwardingSortedMap;
/**
* This class has the same rational as {@link UnmodifiableNavigableSet}.
* @param <K> See {@link NavigableMap}
* @param <V> See {@link NavigableMap}
*/
public final class UnmodifiableNavigableMap<K,V> extends ForwardingSortedMap<K,V> implements NavigableMap<K,V> {
private final NavigableMap<K,V> delegate;
private final SortedMap<K,V> unmodifiableDelegate;
/**
* @param delegate See {@link ForwardingSortedMap#delegate()}.
*/
public UnmodifiableNavigableMap(NavigableMap<K,V> delegate) {
this.delegate = delegate;
unmodifiableDelegate = unmodifiableSortedMap(delegate);
}
/**
* @param delegate
* @return {@link #UnmodifiableNavigableMap(NavigableMap)}
* @see EffectiveJava#Static_factories_instead_of_constructors
*/
public static <K,V> UnmodifiableNavigableMap<K,V> newUnmodifiableNavigableMap(NavigableMap<K,V> delegate) {
return new UnmodifiableNavigableMap<K,V>(delegate);
}
@Override
protected SortedMap<K,V> delegate() {
return unmodifiableDelegate;
}
private Map.Entry<K,V> newImmutableEntry(Map.Entry<K,V> entry) {
return entry == null ? null : new AbstractMap.SimpleImmutableEntry<K,V>(entry);
}
@Override
public Map.Entry<K,V> ceilingEntry(K key) {
return newImmutableEntry(delegate.ceilingEntry(key));
}
@Override
public K ceilingKey(K key) {
return delegate.ceilingKey(key);
}
@Override
public NavigableSet<K> descendingKeySet() {
return newUnmodifiableNavigableSet(delegate.descendingKeySet());
}
@Override
public NavigableMap<K,V> descendingMap() {
return newUnmodifiableNavigableMap(delegate.descendingMap());
}
@Override
public Map.Entry<K,V> firstEntry() {
return newImmutableEntry(delegate.firstEntry());
}
@Override
public Map.Entry<K,V> floorEntry(K key) {
return newImmutableEntry(delegate.floorEntry(key));
}
@Override
public K floorKey(K key) {
return delegate.floorKey(key);
}
@Override
public NavigableMap<K,V> headMap(K toKey, boolean inclusive) {
return newUnmodifiableNavigableMap(delegate.headMap(toKey, inclusive));
}
@Override
public Map.Entry<K,V> higherEntry(K key) {
return newImmutableEntry(delegate.higherEntry(key));
}
@Override
public K higherKey(K key) {
return delegate.higherKey(key);
}
@Override
public Map.Entry<K,V> lastEntry() {
return newImmutableEntry(delegate.lastEntry());
}
@Override
public Map.Entry<K,V> lowerEntry(K key) {
return newImmutableEntry(delegate.lowerEntry(key));
}
@Override
public K lowerKey(K key) {
return delegate.lowerKey(key);
}
@Override
public NavigableSet<K> navigableKeySet() {
return newUnmodifiableNavigableSet(delegate.navigableKeySet());
}
@Override
public Map.Entry<K,V> pollFirstEntry() {
throw new UnsupportedOperationException();
}
@Override
public Map.Entry<K,V> pollLastEntry() {
throw new UnsupportedOperationException();
}
@Override
public NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) {
return newUnmodifiableNavigableMap(delegate.subMap(fromKey, fromInclusive, toKey, toInclusive));
}
@Override
public NavigableMap<K,V> tailMap(K fromKey, boolean inclusive) {
return newUnmodifiableNavigableMap(delegate.tailMap(fromKey, inclusive));
}
}
Oops ... parece que se olvidó de hacer eso .... – skaffman
No hay tales métodos en el JDK, como se menciona en este informe de error: http://bugs.sun.com/bugdatabase/view_bug. Do? bug_id = 6907251 –