java - 为什么 Collections.UnmodifiableMap.UnmodifiableEntrySet 覆盖 stream() 方法?

标签 java oop collections java-stream overriding

在查看源代码时,我可以看到 stream()方法已在 Collections.UnmodifiableMap.UnmodifiableEntrySet 中被覆盖.但代码似乎与 Collection.stream() 相同除了 Collections.UnmodifiableMap.UnmodifiableEntrySet.stream() 中的返回类型更具体地说是Stream<Entry<K,V>>而不仅仅是 Stream<E>Collection.stream() .

spliterator()两个类的方法都不同,但即使 stream没有被覆盖我认为 UnmodifiableEntrySet.spliterator()将从 Collection.stream() 调用如果对象的类型是 UnmodifiableEntrySet .

那么,stream 有什么原因吗?方法被重写了?

Collection.java

@Override
default Spliterator<E> spliterator() {
    return Spliterators.spliterator(this, 0);
}
 
default Stream<E> stream() {
    return StreamSupport.stream(spliterator(), false);
}

Collections.UnmodifiableMap.UnmodifiableEntrySet.java

@SuppressWarnings("unchecked")
public Spliterator<Entry<K,V>> spliterator() {
    return new UnmodifiableEntrySetSpliterator<>(
        (Spliterator<Map.Entry<K, V>>) c.spliterator());
}

@Override
public Stream<Entry<K,V>> stream() {
    return StreamSupport.stream(spliterator(), false);
}

最佳答案

以下 Java 文档/程序来自openjdk 14 2020-03-17

覆盖spliterator的主要原因和 stream是为了保证UnmodifiableEntrySet的进入未修改。

来自 UnmodifiableEntrySet 的评论:

We need this class in addition to UnmodifiableSet as Map.Entries themselves permit modification of the backing Map via their setValue operation. This class is subtle: there are many possible attacks that must be thwarted.

开始,UnmodifiableEntrySet延伸UnmodifiableSet延伸 UnmodifiableCollection . 在 UnmodifiableCollection ,代理模式用于避免修改支持 Collection c,大多数方法只是调用支持 Collection方法,例如 spliteratorstream :

    @Override
    public Spliterator<E> spliterator() {
        return (Spliterator<E>)c.spliterator();
    }

    @SuppressWarnings("unchecked")
    @Override
    public Stream<E> stream() {
        return (Stream<E>)c.stream();
    }

所以如果UnmodifiableEntrySet不覆盖这些方法,行为将遵循 UnmodifiableCollection实现,支持条目将被公开并可以通过 Entry#setValue 进行修改.

因此 spliteratorstream方法被覆盖并且UnmodifiableEntrySetSpliterator引入是为了用 UnmodifiableEntry 包装对支持条目的所有访问, 确保条目不能被修改。

为什么 UnmodifiableCollection覆盖 stream

好像没必要重写streamUnmodifiableCollection ,因为我们可以在 Collection 中使用默认实现(只需通过 spliterator 创建流)。 但作者决定覆盖 stream使用背衬 Collection c stream方法,可能的原因之一是支持 Collection可以覆盖 stream出于性能原因的方法,例如Collections.CopiesList ,或者它是 spliterator方法不符合 Collection#stream 的要求

This method should be overridden when the spliterator() method cannot return a spliterator that is IMMUTABLE, CONCURRENT, or late-binding. (See spliterator() for details.)

关于java - 为什么 Collections.UnmodifiableMap.UnmodifiableEntrySet 覆盖 stream() 方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66197054/

相关文章:

java - Java 中的事件和监听器

类似 C++ 的 Moose 与 Perl 的 OOP 用法

java - 如何使用java驱动程序将mongo mapreduce结果存储在不同的数据库中

java - 将列表截断为给定数量的元素

java - Java 8 中的方法不明确,为什么?

java - 可以将配置文件放在 JAR 中吗?

java - 读取外部文本文件并存储到数组中

java - Apache 公共(public)日志配置

java - 如何在 Retrofit 调用中保存变量的值?

java - 按元素计算列表的大小