Java 中不可修改的 NavigableSet/NavigableMap?

发布于 2024-08-27 07:59:38 字数 550 浏览 5 评论 0原文

java.util.Collections 有几个不可修改的方法,它们通过将集合包装在禁止突变操作的装饰器中来提供不可修改的集合视图。

Java 6 添加了对 java.util.NavigableSet 和 java.util.NavigableMap 的支持。

我希望能够拥有不可修改的 NavigableSetNavigableMap ,但是 java.util.Collections#unmodifyingSortedSet(SortedSet) 和 < code>java.util.Collections#unmodifyingSortedMap(SortedMap) 是不够的,因为它们不支持 NavigableSetNavigableMap 特有的操作。

unmodifyingNavigableSetunmodifyingNavigableMap 是否有事实上的实现?

java.util.Collections has several unmodifiable methods that provide unmodifiable collection views by wrapping collections in decorators that prohibit mutation operations.

Java 6 added support for java.util.NavigableSet and java.util.NavigableMap.

I'd like to be able to have unmodifiable NavigableSets and NavigableMaps, but java.util.Collections#unmodifiableSortedSet(SortedSet) and java.util.Collections#unmodifiableSortedMap(SortedMap) are not sufficient because they do not support the operations that are particular to NavigableSet and NavigableMap.

Are there de-facto implementations for unmodifiableNavigableSet and unmodifiableNavigableMap?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

只怪假的太真实 2024-09-03 07:59:38

Guava 现在提供(自 12.0 版本起,2012 年 4 月 30 日发布)Maps.unmodifyingNavigableMapSets.unmodifyingNavigableSet

Guava now provides (since version 12.0, released April 30, 2012) Maps.unmodifiableNavigableMap and Sets.unmodifiableNavigableSet.

夏夜暖风 2024-09-03 07:59:38

Java SE 8 包含这两种方法。

请参阅 Javadoc< /a>.

Java SE 8 included these two methods.

See the Javadoc.

耳根太软 2024-09-03 07:59:38

这只是一个猜测,但未提供不可修改的实现的部分原因可能是由于 NavigableSet/Map 接口公开了未标记为可选的变异方法:

  • NavigableSet.pollFirst
  • NavigableSet.pollLast
  • NavigableMap.pollFirstEntry
  • NavigableMap.pollLastEntry

也就是说,在提供不可修改的实现时仅抛出 UnsupportedOperationException 似乎是合理的。这就是这些实现中所做的事情(假设您使用的是 GoogleGuava):

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));
    }
}

导航地图:

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));
    }
}

This is just a guess, but part of the reason why an unmodifiable implementation was not provided may be due to the fact that the NavigableSet/Map interfaces expose mutating methods that aren't marked as optional:

  • NavigableSet.pollFirst
  • NavigableSet.pollLast
  • NavigableMap.pollFirstEntry
  • NavigableMap.pollLastEntry

That said, it seems reasonable when providing an unmodifiable implementation to just throw an UnsupportedOperationException. That is what is done in these implementations (which assume you're using GoogleGuava):

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));
    }
}
只是我以为 2024-09-03 07:59:38

来自 Christian Semrau(在问题评论中):

JDK 中没有这样的方法,如 此错误报告

From Christian Semrau (in the question comments):

There are no such methods within the JDK, as mentioned in this bug report.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文