Несколько способов удаления элементов из Java Collection

Spring Boot

1. Введение

Коллекция операций представляет собойJavaТо, что программисты повторяют чуть ли не каждый день. Сегодня мы будем учиться сJava Collectionметод удаления элементов в . Я создал простую коллекцию в качестве примера для изучения.

  List<String> servers = new ArrayList<>();
        servers.add("Felordcn");
        servers.add("Tomcat");
        servers.add("Jetty");
        servers.add("Undertow");
        servers.add("Resin");

2. Цикл for не обязательно удаляет элементы из коллекции

Давайте воспользуемся традиционнымforeachудаление петлиFПоддельный сервер в начале, но вы обнаружите, что эта операция запускаетConcurrentModificationExceptionаномальный.

 // 错误的示范 千万不要使用
  for (String server : servers) {
    if (server.startsWith("F")) {
        servers.remove(server);
    }
 }

Не может ли цикл for удалить элементы? конечно, нет! Ничего страшного, если мы сможем определить индекс элемента, который нужно удалить.

 // 这种方式是可行
 for (int i = 0; i < servers.size(); i++) {
    if (servers.get(i).startsWith("F")) {
        servers.remove(i);
    }
}

Но таким образом я только продемонстрировалArrayList, другие типы строго не тестируются и оставляются на ваше усмотрение.

3. Итератор Итератор может удалять элементы в коллекции

Традиционно мы используемIteratorгарантированно удаляет элементы:

    Iterator<String> iterator = servers.iterator();

        while (iterator.hasNext()) {
            String next = iterator.next();
            if (next.startsWith("F")) {
                iterator.remove();
            }
        }

4. Недостатки обхода и удаления элементов

  • Нам нужно перебрать каждый элемент коллекции и утвердить их, даже если вы удалите элемент.
  • Хотя мы можем итеративно удалять определенные элементы, операция громоздка и имеет потенциал в зависимости от типа коллекции.ConcurrentModificationExceptionаномальный.
  • В зависимости от структуры данных временная сложность удаления элемента сильно различается. такие как структуры массиваArrayListНе так быстро, как структура связанного списка при удалении элементовLinkedList.

5. Операция удаления нового элемента коллекции

Java 8Предоставляет новые операции сбораAPIа такжеStreamчтобы помочь нам решить эту проблему. Я описал в предыдущих статьяхJava 8 Stream API, если вам интересно, то можете пойти и посмотреть.

5.1 Collection.removeIf()

новыйCollection Api removeIf(Predicate filter). ДолженApiобеспечивает более лаконичное использованиеPredicate(Утверждать) метод для удаления элемента, поэтому мы можем более кратко реализовать начальные требования:

 servers.removeIf(s-> s.startsWith("F"));

В то же время, согласно тесту,ArrayListа такжеLinkedListисполнение близко. Этот метод обычно рекомендуется для работы.

5.2 Потоковая реализация удаляет элементы

В отличие от всех вышеперечисленных операций по удалению, по сути, ни одна из операций не изменитStreamисточник, мы просто используемStream ApiРаботает с копией источника данных. последовал数据源 -> 中间操作 -> 归纳终止жизненный цикл. Давайте посмотрим на использованиеStreamКак достичь нашего намерения.

5.2.1 Реализуется утверждением фильтра

мы можем использоватьStreamизfilterутверждение.filterУтверждение объединит элементы потока, соответствующие утверждению, в новый поток, а затем суммирует его, поэтому мы можем написать:

// 跟以上不同的是 该方式中的断言是取反的操作。
List<String> newServers = servers.stream().filter(s -> !s.startsWith("F")).collect(Collectors.toList());

Это преимущество было упомянуто выше, не затрагивая исходные данные, и создается копия. Недостатком является то, что могут быть проблемы с использованием памяти.

5.2.2 Индукция через Collectors.partitioningBy

Хотя этого метода достаточно, я чувствую себя немного оппортунистическим.Collectors.partitioningBy()Метод предполагается дихотомическим. Этот метод суммирует элементы в потоке, которые соответствуют утверждению, и те, которые не соответствуют утверждению, в два элемента.keyсоответственноtrueа такжеfalseизMap, мы можем классифицировать набор совпадающих и не совпадающих элементов. Реализация выглядит следующим образом:

 Map<Boolean, List<String>> f = servers.stream().collect(Collectors.partitioningBy(s -> !s.startsWith("F")));
        
  List<String> trues = f.get(Boolean.TRUE);
  System.out.println("不以 F 开头的:  " + trues);

  List<String> falses = f.get(Boolean.FALSE);
  System.out.println("以 F 开头的:  " + falses);

Как правило, этот метод не рекомендуется для использования в этом сценарии и не соответствуетApiдизайнерский замысел.

6. Резюме

Сегодня мы изучили некоторыеCollectionsСпособы удаления элементов в , и их рассмотрение. Я не знаю, есть ли у вас какие-либо другие способы реализовать это, вы также можете передать общедоступную учетную запись:Felordcnскажите мне.

关注公众号:Felordcn获取更多资讯

Личный блог: https://felord.cn