【问题标题】:how to create an immutable iterator?如何创建一个不可变的迭代器?
【发布时间】:2019-02-21 02:29:04
【问题描述】:

如果我有一个 Map 或一个 List 并从中获取一个迭代器,例如:

var map = new HashMap();
var iterator = map.entrySet().iterator();

如果事后修改了该映射,它会影响迭代器还是迭代器一旦创建就基本上不可变?

如果不是不可变的,如何创建不可变的迭代器?

【问题讨论】:

  • 相关,但我的问题可能措辞更好,更切中要害
  • 为什么是-1?我认为这是一个有趣的问题?
  • 请阅读文档,即HashMap的javadoc:"这个类的所有“集合视图方法”返回的迭代器都是失败的-fast:如果在迭代器创建后的任何时候对映射进行结构修改,除了通过迭代器自己的remove方法之外的任何方式,迭代器都会抛出ConcurrentModificationException。”
  • 措辞上的问题并没有真正的意义,因为迭代器本质上必然是可变的;如果我理解正确,您想要一个迭代器,它是某个时刻底层集合的快照?

标签: java iterator


【解决方案1】:

迭代器的唯一有效操作是递增和取消引用(尽管 Java Iterator 在其 next() 方法中结合了这两者)。如果您有一个不可修改的迭代器,那么您只会取消引用。取消引用可以为您提供对象引用,或者取消引用无效,因为它没有引用集合中的有效位置。

但这些语义与Optional 相同:Optional 可以为空或具有有效的对象引用。因此,从 Iterator 创建一个 Optional 并将其用作“不可修改的迭代器”:

private Optional<T> unmodifiableNext(Iterator<T> i)
{
   if (i.hasNext()) {
      return Optional.ofNullable(i.next());
   } else {
      return Optional.empty();
   }
}

这还有一个额外的好处,那就是 Optional 不再与集合绑定,因此可以安全地更改集合,而无需更改 Optional 所指的对象。

【讨论】:

    【解决方案2】:

    迭代器实例本身通常不需要可变性/不变性的概念。但是,它正在迭代的集合可能是不可修改或不可变的。这是一种禁用迭代器更改集合的能力的方法。如果您返回此类的实例,则返回的迭代器的 remove() 方法将被禁用。该类通过返回 UnmodifiableIterator.create(yourIterator) 来使用。

    import java.util.Iterator;
    
    /**
     * UnmodifiableIterator, A wrapper around an iterator instance that
     * disables the remove method.
     */
    public final class UnmodifiableIterator<E> implements Iterator<E> {
    
        /**
         * iterator, The base iterator.
         */
        private final Iterator<? extends E> iterator;
    
        private UnmodifiableIterator(final Iterator<? extends E> iterator) {
            this.iterator = iterator;
        }
    
        public static <E> Iterator<E> create(final Iterator<? extends E> iterator) {
            if (iterator == null) {
                throw new NullPointerException("The iterator can not be null.");
            }
            return new UnmodifiableIterator<>(iterator);
        }
    
        @Override
        public boolean hasNext() {
            return iterator.hasNext();
        }
    
        @Override
        public E next() {
            return iterator.next();
        }
    
        @Override
        public void remove() {
            throw new UnsupportedOperationException("Iterator.remove() is disabled.");
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 2021-10-15
      • 2018-05-20
      • 2016-07-24
      • 2020-12-05
      • 2021-02-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-28
      相关资源
      最近更新 更多