且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Java:高效的 ArrayList 过滤?

更新时间:2023-11-29 16:22:40

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

Efficiently removing a number of elements from an ArrayList requires some thought. The naive approach is something like this:

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

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

The problem is that each time you remove an element you copy (on average) half of the remaining elements. This is because removing an element from an ArrayList entails copying all elements after element removed one position to the left.

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

Your original solution involving the list of elements to be removed essentially does the same thing. Unfortunately, the properties of an ArrayList don't allow removeAll to do better than the above.

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

If you expect to remove a number of elements, the following is more efficient:

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 个元素,这应该会(平均)收支平衡.

We are copying (almost) the entire list twice, so this should break even (on average) if you remove as few as 4 elements.

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

It is interesting to note that functional programming languages / libraries typical support a filter method, and that can do this task in one pass through the list; i.e. a lot more efficiently. I think we can expect significant improvements if / when Java supports lambdas, and the collection APIs are enhanced to use them.

UPDATE 并且使用 Java 8 lambdas 和流,我们得到它们......对于这个用例.

UPDATE and with Java 8 lambdas and streams, we get them ... for this use-case.