【问题标题】:Java: Efficient ArrayList filtering?Java:高效的 ArrayList 过滤?
【发布时间】:2023-03-27 18:08:01
【问题描述】:

我需要过滤一个 ArrayList 并删除找到的元素。作为 Java 的新手,我想知道实现这一目标的最有效方法是什么(很重要,因为它在移动设备上运行)。目前我这样做:

// We display only top-level dealers (parentId=-10)
ArrayList<DealerProductCount> subDealers = new ArrayList<DealerProductCount>();
for (DealerProductCount dealer : wsResponse.Dealers) {
    if (dealer.ParentId != -10) subDealers.add(dealer);
}
wsResponse.Dealers.removeAll(subDealers);

可以在没有临时对象的情况下完成吗?也许通过直接操作(删除)被迭代列表的元素?

【问题讨论】:

  • 还有其他数据结构可以更有效地删除项目。从 LinkedList 中删除将具有 O(n) 性能。从 HashMap 中删除将具有恒定的时间性能。

标签: java android arraylist


【解决方案1】:

从ArrayList 中有效地删除一些元素需要一些思考。天真的方法是这样的:

Iterator<DealerProductCount> it = wsResponse.Dealers.iterator();
while (it.hasNext()) {
    if (it.next().ParentId != -10) { 
        it.remove(); 
    }
}

问题在于,每次删除一个元素时,都会复制(平均)剩余元素的一半。这是因为从ArrayList 中移除一个元素需要复制元素移除左侧一个位置之后的所有元素。

涉及要删除的元素列表的原始解决方案基本上做同样的事情。不幸的是,ArrayList 的属性不允许removeAll 比上面做得更好。

如果您希望删除多个元素,则以下方法更有效:

ArrayList<DealerProductCount> retain =
        new ArrayList<DealerProductCount>(wsResponse.Dealers.size());
for (DealerProductCount dealer : wsResponse.Dealers) {
    if (dealer.ParentId == -10) {
        retain.add(dealer);
    }
}
// either assign 'retain' to 'wsResponse.Dealers' or ...
wsResponse.Dealers.clear();
wsResponse.Dealers.addAll(retain);

我们将(几乎)整个列表复制了两次,因此如果您删除最少 4 个元素,这应该(平均而言)收支平衡。


有趣的是,函数式编程语言/库通常支持过滤器方法,并且可以通过列表一次性完成此任务;即更有效。我认为如果/当 Java 支持 lambda 并且集合 API 得到增强以使用它们时,我们可以期待显着的改进。

更新并使用 Java 8 lambdas 和流,我们得到它们......用于这个用例。

【讨论】:

  • 感谢斯蒂芬,您出色的深入解释!所以带回家的信息是填充一个新的 ArrayList 通常比从现有的元素中删除元素更好。很高兴知道!
【解决方案2】:

如果您使用迭代器,您可以在迭代时安全地移除元素。

【讨论】:

  • (如果迭代器提供了删除的实现——它可能会抛出一个UnsupportedOperationException——所以这只有在你了解你的迭代器时才有效)
【解决方案3】:

一种方法是使用迭代器而不是 for each:

Iterator<DealerProductCount> iter = wsResponse.Dealers.iterator()
while(iter.hasNext()) {
    if (iter.next().ParentId != -10) iter.remove();
}

【讨论】:

    猜你喜欢
    • 2011-01-09
    • 1970-01-01
    • 2018-09-18
    • 2011-06-19
    • 2010-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-27
    相关资源
    最近更新 更多