Самый эффективный способ удаления элементов из списков массивов?

Я изучаю ООП и наткнулся на списки массивов. Я хотел бы знать, как на самом деле работает функция remove() и каков наиболее эффективный способ ее использования.


Первый способ удалить все "ББ"

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)

Это сбивает с толку, потому что счетчик был запущен для увеличения еще несколько раз в первом, но на самом деле он более эффективен, или «содержит ()» перебирает весь список массивов при каждой проверке оператора за сценой.

Как вы определили, какой фрагмент был более эффективным?

Eran 01.05.2019 10:30

На самом деле, я этого не делал, и это именно то, о чем я пытаюсь спросить.. @Eran

Rami 01.05.2019 13:52
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
3
116
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Если вы используете Java8, все, что вам нужно, это просто:

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

Или как короткий путь:

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

Если вы заметили, таким образом не нужно проверять, существует ли элемент в списке или нет.


в качестве хорошей практики:

  • не называйте переменные, где первая буква заглавная Alist, вместо этого используйте, например, aList
Ответ принят как подходящий

Вероятно, наиболее эффективный способ удаления из массива:

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

или

Alist.removeIf("BB"::equals)

Эти методы могут быть более эффективными, чем отдельные вызовы remove, поскольку фактическое удаление можно отложить до тех пор, пока не будут идентифицированы все элементы, равные "BB".

Это важно, потому что удаление элемента из ArrayList сдвигает все элементы с большим индексом «вниз на один». В худшем случае (когда все элементы списка равны тому, что вы хотите удалить), отдельные вызовы удаления списка будут квадратичными по количеству элементов списка; removeAll или removeIf будут линейными, потому что они могут сдвигать неудаленные элементы только один раз и вообще не беспокоиться о сдвиге элементов, подлежащих удалению.


Самая очевидная неэффективность первого метода заключается в том, что вы вызываете remove столько раз, сколько элементов списка, независимо от того, сколько раз элемент появляется в списке. В особенно патологическом примере у вас может быть 1 миллион элементов в списке, где ни один из них не равен "BB": вы все равно будете вызывать remove 1 миллион раз.

Самая очевидная неэффективность второго метода заключается в том, что вы вызываете contains, а затем remove. Вы ищете элемент дважды, делая это.

Более эффективным методом, но все же менее эффективным, чем два метода в начале этого ответа, было бы использование возвращаемое значение remove, которое является логическим значением, указывающим, действительно ли элемент был удален. Как только remove вернет false, нет смысла снова вызывать remove, потому что элемент не найден:

while (Alist.remove("BB")) {}
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);

Это отлично работает! Проверьте это.

Другие вопросы по теме