【问题标题】:Any way to make an Iterator<E> emitted from ArrayList have remove() blocked WITHOUT creating two Iterators?有什么方法可以让从 ArrayList 发出的 Iterator<E> 阻止 remove() 而不创建两个迭代器?
【发布时间】:2012-02-17 21:58:48
【问题描述】:

ArrayList 的迭代器类 ArrayList.Itr 是私有的,所以我不能继承那个家伙。

ArrayList 中的 ArrayList.Itr 访问是私有的,所以我无法提供自己的实现。

我能看到如何做到这一点的唯一方法是继承 ArrayList、覆盖 iterator()、获取该迭代器并将其包装和委托到我自己的拒绝访问删除的 Iterator 对象。 (或者包装和委托 ArrayList 本身并做同样的事情)

Collections.unmodifiableList 基本上做同样的事情。

但这会导致每次调用 MyArrayList.iterator() 时都会创建两个对象,这在我的环境中是次优的。

想法?

编辑:

在这种环境中,对小对象进行 GC 是一个主要问题。这种环境在很短的时间内调用列表迭代器数亿次。我们需要尽可能少的 GC 抖动。这不是过早的优化。这是非常晚的优化。这不是一些玩具应用程序。这是一个在硬件绝对极限下运行的集群网络规模系统。

【问题讨论】:

  • 为什么需要停止 remove() 调用?你在写 API 吗?
  • 我希望列表是不可变的。 Collections.unmodifiableList 在调用 Iterator 时会创建两个对象。
  • 您是否通过坚持认为 2 个对象是不可接受的而过早优化?它不必复制整个列表,只需包装并委托给它(remove() 除外),因此内存不应该成为问题,并且构造包装器应该很快——实际上是免费的。
  • 您为什么要关心另外两个对象?这些只是包装器,创建和垃圾收集非常便宜。您是否测量过它引起了问题?还是你过早地轻视万恶之源?
  • 他们多年前构建并优化了Collections.unmodifiable()。你真的认为你能比平台的创造者和维护者做得更好吗?我告诉你一个秘密,它创建的对象比你想象的要多,你不会做得更好。

标签: java collections arraylist


【解决方案1】:

Collections.unmodifiable 列表,正如您所提到的,可能是最好的方法。我怀疑您是否确实对整个程序进行了概要分析,并发现迭代器的创建确实是执行过程中的瓶颈。

实际上,Java 创建了大量的临时对象。这看起来并不好,但正因为如此,它进行了非常优化,可以有效地做到这一点。

顺便说一句,您尝试访问 ArrayList 的私有成员的事实实际上有点臭。如果您确实不想在迭代列表时创建两个对象,为什么不创建基于 size()get(int index) 的迭代器?

【讨论】:

  • 我喜欢这种基于 get 和 size 创建迭代器的想法。太棒了。谢谢。
  • 这并不完美。如果您(或其他程序员)后来决定用 LinkedList 替换 ArrayList,会发生什么?这个 Iterator 实现不是通用的,它以一种微妙的方式绑定到特定的集合。我希望我能真正了解这个应用程序是如何工作的,并将这个(比方说“优化”的)解决方案与最明显、整洁和正确的解决方案(包装迭代器)的性能进行比较。
  • 如果您的应用程序瓶颈真的是大量的垃圾迭代器,我认为您应该避免使用迭代器和 Java 集合,并寻求真正的微优化解决方案(根据您的需求量身定制的数据结构)。 t 创建大量对象。如果瓶颈真的是这个,那么 get(int index) 事情就不会持续......
【解决方案2】:

您可以根据ArrayList 代码编写自己的AbstractList 子类。我最初认为这是一个可怕的想法,但如果这对您来说是一个关键问题,那么它不是一个大类。

【讨论】:

    【解决方案3】:

    不要对 Java 进行微优化。你的应用程序的瓶颈不会是这个迭代器的“加倍”,想当然

    您的解决方案很聪明而且很好,而是专注于其他(更相关的)问题。

    【讨论】:

    • 我明白你在说什么,但是在这个特殊的环境中,对小对象进行 GC 是一个主要问题。 100,000,000 个迭代器对象已经够糟糕了。 200M 让我们更痛快。
    • 如果您的应用程序中有 1 亿个迭代器,那么您的应用程序设计可能存在缺陷。
    • 不开玩笑,设计有缺陷。那不是我能改变的。我只是想从这只猪身上榨取更多的性能。
    猜你喜欢
    • 2014-03-14
    • 2018-09-11
    • 2011-04-08
    • 2013-09-30
    • 1970-01-01
    • 2021-07-05
    • 1970-01-01
    • 2022-06-15
    • 1970-01-01
    相关资源
    最近更新 更多