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

时间:2019-05-01 08:26:57

标签: java performance oop arraylist

我正在研究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()”遍历整个数组列表场景。

3 个答案:

答案 0 :(得分:8)

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

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

Alist.removeIf("BB"::equals)

与单独调用remove相比,这些方法可能更有效,因为可以将实际删除操作推迟到所有等于"BB"的元素被确定为止。

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


第一种方法中最明显的低效率之处是,无论项目出现在列表中的次数是多少,您调用remove的次数与列表元素的次数相同。在一个特别的病理示例中,列表中可能有1M个元素,但它们都不等于"BB":您仍然会调用remove 1M次。

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

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

while (Alist.remove("BB")) {}

答案 1 :(得分:7)

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

//Preserves argument and class type
function genericCreatePage<T extends Page, A extends any[]>(ctor: new (...a: A)=> T, ...a:A){
    return new ctor(...a);
}

genericCreatePage(DerivedPage)
genericCreatePage(OtherPage, 0)
genericCreatePage(OtherPage, "0") //err

或者简而言之:

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

请注意,这种方式无需检查列表中元素是否存在。


作为一种好的做法:

  • 在第一个字母为大写字母aList.removeIf("B"::equals); 时不要命名变量,而应使用Alist例如

答案 2 :(得分:0)

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);

这很好!请检查一下。