Inventory of those pits of the Java collection class List over the years

Some current high-level programming languages ​​will provide various out-of-the-box implementations of data structures. For example, the Java programming language's collection framework provides various implementations. Collection classes include Map and Collection. List is one of the collection classes that we often use. Many business codes cannot do without it. Today, let's take a look at some of the pits of List.

The first pit: The List returned by the Arrays.asList method does not support adding and deleting operations

For example, we execute the following code:

List<String> strings = Arrays.asList("m", "g");
strings.add("h");Copy code

Will throw java.lang.UnsupportedOperationException exception, what is your inner OS? Why can't the returned ArrayList add elements to it? Can we still add elements in the future? , And then decisively open Debug Dafa:

It is found that the returned ArrayList is not the commonly used java.util.ArrayList, but the internal class java.util.Arrays.ArrayList of Arrays. The source code of the entry method Arrays.asList is as follows:

public static <T> List<T> asList(T... a) {
    return new ArrayList<>(a);
}Copy code

The method returns the static internal class java.util.Arrays.ArrayList of Arrays. Although this class and java.util.ArrayList also inherit from the abstract class java.util.AbstractList, it is found through the source code of this class that it does not have an abstract parent The add method of the AbstractList class is to throw java.lang.UnsupportedOperationException by default.


The root cause of this pit is that the add method of the strings returned by our call is inherited from the add method of the abstract parent class, and the method of the abstract parent class throws java.lang.UnsupportedOperationException by default.

The second pit, the new List returned by the Arrays.asList method and the modification of the original parameter group of the method will affect each other

In addition to the above pit that does not support adding or deleting elements, the Arrays.asList method has another pit:


From the above code, we can find that the modification of the original array will affect the new List we obtained through the Arrays.asList method, and go deep into the source code of java.util.Arrays.ArrayList:

private static class ArrayList<E> extends AbstractList<E>
        implements RandomAccess, java.io.Serializable
    {
        private static final long serialVersionUID = -2764017481108945198L;
        private final E[] a;

        ArrayList(E[] array) {
            a = Objects.requireNonNull(array);
        }

        ...

     }   
Copy code

It can be found that the original array is used directly, so we must pay special attention to the List obtained by using the Arrays.asList method, because the array is shared, and some unexpected bugs may occur when mutual modification. One of the standard gestures is to use it as a parameter of the ArrayList construction method to renew a List (eg List stringList = new ArrayList<>(Arrays.asList(arrays))) or through Lists.newArrayList in the Guava library, The returned new List and the original array are decoupled, and they will no longer affect each other.

The third pit, traversing the List collection directly to delete elements will report an error

When directly traversing the collection elements, adding or deleting elements will report an error. For example, execute the following code:

List<String> stringList = Lists.newArrayList("m", "g", "h");
for (String s : stringList) {
    if (Arrays.asList("m", "h").contains(s)) {
        stringList.remove(s);
    }
}Copy code

The above code can be compiled and passed normally, but java.util.ConcurrentModificationException will be thrown when executed. Looking at the source code, you can find that the delete element method remove will modify the collection structure, that is, modCount (the number of actual modifications of the collection) will be modified. In the loop process, the actual number of modifications of the current List collection modCount is compared with the number of iterator modifications expectedModCount. ExpectedModCount is the modCount at initialization. If the two are not equal, ConcurrentModificationException will be reported. There are two main ways to solve the problem, 1. Use the iterator method of ArrayList to traverse, and then call the method. 2. In JDK 1.8+, you can use the removeIf method to delete.

Finally, I have a heart to ask: call the remove method of ArrayList to pass in the number of the basic type of int and the number of the packaging type of Integer. Is the execution result the same?

At last

Thank you all for seeing here, the article has deficiencies, and you are welcome to point out; if you think it is well written, please give me a thumbs up.

Guess you like

Origin blog.51cto.com/11436461/2547410