Java——List delete related operations

Table of contents

1. List loop to delete elements

2. List delete duplicate elements


1. List loop to delete elements

In daily business, sometimes we need to traverse the List list, judge and delete the elements in it.

(1) In the List list, if we want to delete elements in a loop, then we cannot directly traverse and then remove:

public class test {
    public static List<String> list = Arrays.asList("check 01","test 01","test 02","check 02","test 03");

    public static void main(String[] args) {
        List<String> nameList = new ArrayList<>(list);
        for (int i=0;i<nameList.size();i++){
            String str = nameList.get(i);
            if (str.startsWith("test")){
                nameList.remove(i);
            }
        }
        System.out.println(nameList);
    }
}

 

As above, when we loop through the deletion, an element is removed in the List, and the coordinates of the list will also be changed. That is, when we match the string test01 and delete it, the coordinates of test02 move forward one step and become 1 instead of 2. As the coordinates go backward, test02 will never be deleted.

In view of the above problems, if we want to delete elements using ordinary for loop traversal, then we need to delete in reverse order :

public class test {
    public static List<String> list = Arrays.asList("check 01","test 01","test 02","check 02","test 03");

    public static void main(String[] args) {
        List<String> nameList = new ArrayList<>(list);
        for (int i=nameList.size()-1;i>0;i--){
            String str = nameList.get(i);
            if (str.startsWith("test")){
                nameList.remove(i);
            }
        }
        System.out.println(nameList);
    }
}

 As above, successfully delete all characters starting with test in the List.

(2) Then, if the ordinary for loop cannot traverse normally, is it possible to use the enhanced for loop:

public class test {
    public static List<String> list = Arrays.asList("check 01","test 01","test 02","check 02","test 03");

    public static void main(String[] args) {
        List<String> nameList = new ArrayList<>(list);
        for (String name:nameList){
            if (name.startsWith("test")){
                nameList.remove(name);
            }
        }
        System.out.println(nameList);
    }
}

The above code will report a concurrent modification error:

 

 This is because in the list.remove method, the deletion of elements is mainly based on the fastremove method:

The modCount value is modified in the above method (this value refers to the number of operations on the list)

In the source code of arrayList, the value of modCount will be assigned to expectedModCount during initialization for synchronization:

 When performing enhanced for loop traversal, the next method will be called, which will determine whether there is a next element, including the following methods:

This method will judge expectedModCount and modCount. In the remove method, only the modCount is added, but the expectedModCount is not processed. The expectedModCount is only the value when the ArrayList is initialized (ie 0), so the two values ​​will not be equal after a deletion, and an exception will be thrown.

And because the bottom layer of list.forEach() is also implemented based on the enhanced for loop, the same problem will also exist.

(3) The enhanced for loop does not work, but we can operate it through iterators:

public class test {
    public static List<String> list = Arrays.asList("check 01","test 01","test 02","check 02","test 03");

    public static void main(String[] args) {
        List<String> nameList = new ArrayList<>(list);
        for (Iterator<String> iterator = nameList.iterator(); iterator.hasNext();){
            String name = iterator.next();
            if (name.startsWith("test")){
                iterator.remove();
            }
        }
        System.out.println(nameList);
    }
}

 This is because expectedModCount and modCount are synchronized in the remove method of the iterator, so no exception will be thrown in the next method:

 

2. List delete duplicate elements

(1) In daily business, sometimes we need to traverse the List list and delete duplicate elements in it. The most common method is double-loop judgment deduplication:

public class test {
    public static List<String> list = Arrays.asList("check 01","check 01","test 01","check 01","test 02");

    public static void main(String[] args) {
        List<String> nameList = new ArrayList<>(list);
        for (int i=0; i<nameList.size()-1; i++){
            for (int j=nameList.size()-1; j>i; j--){
                if (nameList.get(j).equals(list.get(i))){
                    nameList.remove(j);
                }
            }
        }
        System.out.println(nameList);
    }
}

(2) The simpler method is to use the characteristics of the Set collection (does not contain repeated elements) to deduplicate it:

public class test {
    public static List<String> list = Arrays.asList("check 01","check 01","test 01","check 01","test 01");

    public static void main(String[] args) {
        List<String> nameList = new ArrayList<>(list);
        List<String> resultList = new ArrayList<>(new LinkedHashSet<>(nameList));
        System.out.println(resultList);
    }
}

The reason why LinkedHashSet is used instead of HashSet is to maintain the order of the list.

 (3) Alternatively, we can deduplicate the new feature stream after java8:

public class test {
    public static List<String> list = Arrays.asList("check 01","check 01","test 01","check 01","test 01");

    public static void main(String[] args) {
        List<String> nameList = new ArrayList<>(list);
        nameList = nameList.stream().distinct().collect(Collectors.toList());
        System.out.println(nameList);
    }
}

Guess you like

Origin blog.csdn.net/tang_seven/article/details/129846609