1. Do you really know how to use the remove method of List?

Let’s start with the following example:

public class ListRemoveDemo { public static void main(String[] args) { List<String> sourceList = new ArrayList<>(); sourceList.add("Rose"); sourceList.add("Jack"); sourceList.add("Cooper"); sourceList.add("Jay"); [Rose,Jack,Cooper,Jay] for (int I = 0; i < sourceList.size(); i++) { String curStr = sourceList.get(i); if (isNeedRemove(curStr)) { sourceList.remove(curStr); }} // Print the sourceList output:  [Rose,Cooper,Jay] } private static boolean isNeedRemove(String s) { if ("Jack".equalsIgnoreCase(s)) { return true; } return false; }}Copy the code

In the above example, isNeedRemove is used to determine which elements of the List should be removed. From the above output, the original List: [Rose,Jack,Cooper,Jay] [Rose,Cooper,Jay] At first glance, it’s perfect and it’s exactly what you want it to be.

Consider the following example:

public class ListRemoveDemo { public static void main(String[] args) { List<String> sourceList = new ArrayList<>(); sourceList.add("Rose"); sourceList.add("Jack"); sourceList.add("Jack"); sourceList.add("Jay"); // Print sourceList: [Rose,Jack,Jack,Jay] for (int I = 0; i < sourceList.size(); i++) { String curStr = sourceList.get(i); if (isNeedRemove(curStr)) { sourceList.remove(curStr); }} // Print the sourceList output:  [Rose,Jack,Jay] } private static boolean isNeedRemove(String s) { if ("Jack".equalsIgnoreCase(s)) { return true; } return false; }}Copy the code

In this example, the sourceList is [Rose,Jack,Jack,Jay], and the desired output is [Rose,Jack,Jay] for the element removed as Jack, while the actual output is [Rose,Jack,Jay]. Apparently, one Jack failed to be removed.

The example here simply simulates the pit of remove. Imagine that the isNeedRemove method is some business judgment that may return the need to remove from the List for different elements.

So what’s the problem?

Actually, the reason is simple, by looking at the ArrayList remove source code, can know the remove process is actually an array “translation”, find the need to delete the elements of the index, the [index + 1, the list. The size () – 1) to move forward.

// arraylist. Java // remove method finally calls fastRemove private void fastRemove(int index) {modCount++; int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // clear to let GC do its work }Copy the code

The System. Arraycopy method moves the index + 1 position and the element after it one bit forward, and finally sets the element at the end of the elementData to NULL and the size is reduced by one.

As you can see, each time you remove an element, the following node elements move forward by one, while the for loop increases I by one.

2. How to use the remove method of List correctly?

1) Reverse order deletion method

The wrong way to do this is to go from the end of the List to the head of the List

2) Create a List

Create a new List to store the elements you want to keep

3) Use iterators

public class ListRemoveDemo { public static void main(String[] args) { List<String> sourceList = new ArrayList<>(); sourceList.add("Rose"); sourceList.add("Jack"); sourceList.add("Cooper"); sourceList.add("Jay"); [Rose,Jack,Jack,Jay] Iterator<String> Iterator = sourcelist.iterator (); while (iterator.hasNext()) { String next = iterator.next(); If (isNeedRemove(next)) {// Note that this is iterator remove iterator.remove(); }} // Print the sourceList output:  [Rose,Jay] } private static boolean isNeedRemove(String s) { if ("Jack".equalsIgnoreCase(s)) { return true; } return false; }}Copy the code