Several ways of removing elements from Java Collection

1. Preface

Operation set is a thing that Java programmers repeat almost every day. Today, let's study the method of deleting elements from Java Collection. I built a simple collection, and we used it as an example to explore.

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

2. The for loop does not necessarily remove elements from the set

Let's use the traditional foreach loop to remove the fake server starting with F, but you will find that this operation raises the ConcurrentModificationException exception.

 // Never use a wrong demonstration
  for (String server : servers) {
    if (server.startsWith("F")) {
        servers.remove(server);
    }
 }

Can't a for loop remove elements? Of course not! If we can determine the index of the element to be removed, it is OK.

 // This approach is feasible
 for (int i = 0; i < servers.size(); i  ) {
    if (servers.get(i).startsWith("F")) {
        servers.remove(i);
    }
}

However, I have only demonstrated ArrayList in this way, and other types are not strictly tested, which is left to you to explore.

3. Iterator iterator can delete elements in the collection

In the traditional way, we use Iterator to ensure the deletion of elements:

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

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

4. Disadvantages of traversing and deleting elements

  • We need to traverse each element of the collection and assert them, even if you delete one element.
  • Although we can delete specific elements iteratively, the operation is cumbersome, and there are potential ConcurrentModificationException exceptions according to different collection types.
  • According to different data structures, the time complexity of deleting elements is also greatly different. For example, ArrayList of array structure is not as fast as LinkedList of linked list structure in deleting elements.

5. Delete new collection elements

Java 8 provides a new collection operation API and Stream to help us solve this problem.

5.1 Collection.removeIf()

New collection Api removeif (predict <? Super E > filter). The Api provides a more concise method to delete elements using Predicate, so we can more concisely implement the initial requirements:

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

At the same time, according to the test, the performance of ArrayList and LinkedList is close. This method is generally recommended.

5.2 Stream implementation remove elements

Different from all the above removal operations, in fact, any operation will not change the Stream source. We just use Stream Api to operate the copy of the data source. It follows the life cycle of data source - > intermediate operation - > inductive termination. Let's see how to use Stream to achieve our intention.

5.2.1 implementation through filter assertion

We can use the filter assertion of Stream. The filter assertion will integrate the Stream elements that meet the assertion into a new Stream, and then sum them up. Therefore, we can write as follows:

// The difference from the above is that the assertions in this method are negated.
List<String> newServers = servers.stream().filter(s -> !s.startsWith("F")).collect(Collectors.toList());

This advantage has been mentioned above. It will not affect the original data. It generates a copy. The disadvantage is that there may be memory consumption problems.

5.2.2 through collectors Partitioningby induction

Although this method can meet the needs, I feel a little opportunistic. Collectors. The partitioningby () method is intended to do secondary classification. This method will summarize the elements that meet and do not meet the assertion in the flow into two maps with true and false key s respectively. We can classify the set of elements that meet and do not meet the assertion. The implementation is as follows:

 Map<Boolean, List<String>> f = servers.stream().collect(Collectors.partitioningBy(s -> !s.startsWith("F")));

  List<String> trues = f.get(Boolean.TRUE);
  System.out.println("Not to F Beginning:  "   trues);

  List<String> falses = f.get(Boolean.FALSE);
  System.out.println("with F Beginning:  "   falses);

Generally, this method is not recommended for use in this scenario, which is not in line with the design intent of the Api.

6. Summary

Today, we looked at some methods and considerations for deleting elements from Collections.

Here I recommend a framework learning exchange circle. Exchange and study wechat: 539413949 (there are a large number of interview questions and answers) will share some videos recorded by senior architects: Spring, MyBatis, Netty source code analysis, the principle of high concurrency, high performance, distributed and micro service architecture, JVM performance optimization, distributed architecture, etc. These have become the necessary knowledge system for architects. You can also receive free learning resources, which has benefited a lot at present

Tags: Java Spring Programmer Struts

Posted by adam119 on Fri, 15 Apr 2022 19:25:14 +0930