Source reading notes

1 some pits of assembly

  1. When a collection element is a custom class, the custom class enforces the equals and hashCode methods, both of which must be implemented.

In the collection, except that TreeMap and TreeSet compare element sizes through comparators, the other collection classes will use the equals and hashCode methods when judging the index position and equality. This was mentioned in the previous source code analysis, so when the collection elements are custom classes, we strongly recommend overriding the equals and hashCode Method, we can directly use IDEA tool to override these two methods, which is very convenient;

  1. When deleting all collection classes in the for loop, if you directly use the remove method of the collection class to delete, it will fail quickly and report the error of ConcurrentModificationException. Therefore, in any loop deletion scenario, it is recommended to use an iterator to delete;

  2. When we convert an array to a collection, we often use Arrays.asList(array). This method has two pits. The code demonstration pit is:

public void testArrayToList(){
  Integer[] array = new Integer[]{1,2,3,4,5,6};
  List<Integer> list = Arrays.asList(array);

  //Pit 1: modifying the value of the array will directly affect the original list"before the array is modified, the first element of the collection is: {}", list.get(0));
  array[0] = 10;"before the array is modified, the first element of the collection is: {}", list.get(0));

  //Pit 2: when using add, remove and other methods to operate list,
  //Unsupported operation exception will be reported
Pit 1: after the array is modified, it will directly affect the value of the new List.
Pit 2: add, remove and other operations cannot be performed on the new List. Otherwise, an unsupported operationexception error will be reported at runtime.

When we look at the source implementation of Arrays.asList, we can see the problem. The source is as follows:

From the above figure, we can see that the List returned by the Arrays.asList method is not a java.util.ArrayList, but a static class within itself. This static class directly holds array references and does not implement the add, remove and other methods. These are the reasons for pits 1 and 2.

  1. The set List is converted into an array. We usually use the toArray method, which is very dangerous. If we don't pay attention to it, we step into a big hole. Our example code is as follows:
  public void testListToArray(){
    List<Integer> list = new ArrayList<Integer>(){{

    // The commented code in the following line can't be converted into an array. The parameterless toArray returns Object [],
    // Unable to convert down to list < integer >, compilation failed
    // List<Integer> list2 = list.toArray();

    // Demonstrate the method of parameter toArray. When the array size is not enough, get the situation that the array is null
    Integer[] array0 = new Integer[2];
    list.toArray(array0);"toArray Insufficient array size, array0 array[0] The value is{},array[1] The value is{},",array0[0],array0[1]);
    // Demonstrate that the initialization size of an array is just right, just convert it to an array
    Integer[] array1 = new Integer[list.size()];
    list.toArray(array1);"toArray The array size is just right, array1 array[3] The value is{}",array1[3]);

    // Demonstrate that the initialization size of an array is larger than the actual required size, or it can be converted into an array
    Integer[] array2 = new Integer[list.size()+2];
    list.toArray(array2);"toArray There is a lot of array size, array2 array[3] The value is{},array[4] The value is{}",array2[3],array2[4]);
19:33:07.687 [main] INFO - toArray Insufficient array size, array0 array[0] The value is null,array[1] The value is null,
19:33:07.697 [main] INFO - toArray The array size is just right, array1 array[3] The value is4
19:33:07.697 [main] INFO - toArray There is a lot of array size, array2 array[3] The value is4,array[4] The value is null

The parameterless method of toArray cannot be converted to specific type. When compiling, there will be a reminder. Generally, we will use the toArray method with parameters. At this time, there will be a pit. If the size of parameter array is not enough, the returned array value is empty. The return value of array0 in the above code reflects this point, but let's look at toArray Source code: it is found that the data returned in the source code is the data of four size values, which is not empty. The source code is as follows:

// List to array
public <T> T[] toArray(T[] a) {
  // If the length of the array is not enough, copy it according to the size of the List. When returning, all the returned arrays are correct
  if (a.length < size)
    // Make a new array of a's runtime type, but my contents:
    return (T[]) Arrays.copyOf(elementData, size, a.getClass());
  System.arraycopy(elementData, 0, a, 0, size);
  // If the array length is greater than the List size, the value is null
  if (a.length > size)
    a[size] = null;
  return a;

From the source code, we can't see why the element value of array0 is null at all. Finally, we look at the annotation of the method and find that it is described in this way:

If the list fits in the specified array, it is returned therein.  Otherwise, a new array is
 allocated with the runtime type of the specified array and the size of this list. 

If the returned array size is the same as the declared array size, it will return normally. Otherwise, a new array will be allocated and returned.

So when we use the parameter toArray method, the declared array size must be greater than or equal to the List size. If it is smaller than, you will get an empty array.

Keywords: Programming Java

Added by Jumba on Wed, 12 Feb 2020 10:22:55 +0200