从数组列表中删除元素的最有效方法? [关闭]

Posted

技术标签:

【中文标题】从数组列表中删除元素的最有效方法? [关闭]【英文标题】:Most Efficient Way To Delete Elements From Array Lists? [closed] 【发布时间】:2019-09-19 20:34:03 【问题描述】:

我正在学习 OOP,我遇到了数组列表。我想知道 remove() 函数实际上是如何工作的,以及最有效的使用方法是什么。


第一种删除所有“BB”的方法

public class ArrayListTest 
    public static void main(String args[])
        ArrayList<String> Alist = new ArrayList<String>();
        Alist.add("AA");
        Alist.add("BB");
        Alist.add("AA");
        Alist.add("AA");
        Alist.add("AA");
        Alist.add("BB");
        System.out.println("Original ArrayList : " + Alist);
        int n = 0 ;
        for (int i = 0; i < Alist.size(); i++)
            n++;
            Alist.remove("BB");
        
        System.out.println(n);
        System.out.println("Modified ArrayList : " + Alist);
    

输出

run:
Original ArrayList : [AA, BB, AA, AA, AA, BB]
4
Modified ArrayList : [AA, AA, AA, AA]
BUILD SUCCESSFUL (total time: 0 seconds)

第二种方法删除所有“BB”

public class ArrayListTest 
    public static void main(String args[])
        ArrayList<String> Alist = new ArrayList<String>();
        Alist.add("AA");
        Alist.add("BB");
        Alist.add("AA");
        Alist.add("AA");
        Alist.add("AA");
        Alist.add("BB");
        System.out.println("Original ArrayList : " + Alist);
        int n = 0 ;
        while(Alist.contains("BB"))
            n++;
            Alist.remove("BB");
        

        System.out.println(n);
        System.out.println("Modified ArrayList : " + Alist);
    

输出

run:
Original ArrayList : [AA, BB, AA, AA, AA, BB]
2
Modified ArrayList : [AA, AA, AA, AA]
BUILD SUCCESSFUL (total time: 0 seconds)

这令人困惑,因为在第一个中触发了计数器增加了几次,但它实际上更有效,还是“contains()”在每次检查后面的语句时循环整个数组列表场景。

【问题讨论】:

How do I write a correct micro-benchmark in Java? 你是如何确定哪个 sn-p 更有效的? 实际上,我没有,这正是我想要问的......@Eran 【参考方案1】:

从数组列表中删除的最有效方法可能是:

Alist.removeAll(Collections.singleton("BB"))

Alist.removeIf("BB"::equals)

这些方法比单独调用remove 更有效,因为实际删除可以推迟到所有等于"BB" 的元素都被识别出来。

这很重要,因为从ArrayList 中删除一个元素会将所有具有较大索引的元素“向下移动一个”。在最坏的情况下(当所有列表元素都等于您要删除的内容时),单个列表删除调用将是列表元素数量的二次方; removeAllremoveIf 将是线性的,因为它们可以只移动一次未删除的元素,而根本不需要移动要删除的元素。


第一种方法最明显的低效率是你调用remove的次数与列表元素的数量一样多,而不管该项目在列表中出现了多少次。在一个特别病态的例子中,您可能在列表中有 1M 元素,其中没有一个等于 "BB":您仍然会调用 remove 1M 次。

第二种方法最明显的低效率是调用contains,然后调用remove。通过执行此操作,您将查找该元素两次。

一个更有效的方法 - 但仍然比这个答案开头的两种方法效率低 - 是使用the return value of remove,它是一个布尔值,指示元素是否实际被删除。一旦remove 返回false,再次调用remove 就没有意义了,因为找不到该元素:

while (Alist.remove("BB")) 

【讨论】:

【参考方案2】:

如果您使用的是 Java8,您只需要:

aList.removeIf(s -> s.equals("BB"));

或者作为一种简短的方式:

aList.removeIf("B"::equals);

如果你注意了,这种方式不需要检查元素是否存在于列表中。


作为一种良好做法:

不要命名第一个字母为大写Alist的变量,例如使用aList

【讨论】:

【参考方案3】:
List<String> list1=new ArrayList(Arrays.asList("AA","BB","AA","AA","AA","BB"));
        List<String> list2=new ArrayList();

        list2=list1.stream().filter(a -> !a.equals("BB")).collect(Collectors.toList());
        System.out.println(list2);

这很好用!检查一下。

【讨论】:

以上是关于从数组列表中删除元素的最有效方法? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

Numpy - 从一维数组中删除最后一个元素的最佳方法?

如何通过索引从一个非常大的列表中有效地删除元素?

在 Go 中访问二维数组中的相邻元素的最有效方法是啥?

重命名列表数据框中元素的最有效方法

从嵌套在 std::map 中的 std::list 中删除元素的最佳方法

将对象列表从 c# 传递到糟糕的 c++ win32 本机 dll 的最有效方法是啥?