look out! These hidden "bug s" from "array" to "collection"

First, let's popularize science to unfamiliar brothers:

Array. The aslist () method is used to convert an array to a collection

For friends who often do data processing

It should be no stranger

But then again

This method has several hidden "pits"

A fraternity may be recruited

Let's find out next

It's said that the sharing effect is better!!

Pit 1: arrays of basic data types cannot be directly converted

Error case:

//Defines an array of int classes of the basic data type
int[] arr = {1, 2, 3};
//Using array The aslist () method is converted to a collection
List list = Arrays.asList(arr);
//Output the converted set information
log.info("list:{} size:{}", list, list.size());

Expected output:

list:[1, 2, 3] size:3

Console actual output:

list:[[I@1c53fd30] size:1

Obviously, the hidden "pit" appeared,

An array with three elements has only one element after conversion, and there is a problem with the data type.

Cause analysis:

Although int can be boxed into wrapper class integer, int array cannot be boxed into integer array as a whole.

Pit removal scheme:

1. Arrays. Net is provided above Java 8 Stream method cast

int[] arr1 = {1, 2, 3};
List list1 = Arrays.stream(arr1).boxed().collect(Collectors.toList());
log.info("list:{} size:{}", list1, list1.size());

2. Define arrays directly using the wrapper class integer

Integer[] arr2 = {1, 2, 3};
List list2 = Arrays.asList(arr2);
log.info("list:{} size:{}", list2, list2.size());

Modified console output:

list:[1, 2, 3] size:3

We got the result we expected, and we succeeded in getting rid of the first pit!

Brother, don't be stingy with your praise! It is the power that I continue to output, and we continue to get out of the pit:

Pit 2: the converted set cannot add or delete elements

Error case:

//This time we use the reference class String array
String[] arr = {"1", "2", "3"};
List list = new ArrayList(Arrays.asList(arr));
try {
//Try to append an element to the converted list
list.add("5");
} catch (Exception ex) {
ex.printStackTrace();
}
//After conversion, modify the value of the original array
arr[1] = "4";
//Output original array and converted set
log.info("arr:{} list:{}", Arrays.toString(arr), list);

Expected output:

arr:[1, 4, 3] list:[1, 2, 3, 5]

Console actual output:

//The first is the exception of the list append element
java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:148)
at java.util.AbstractList.add(AbstractList.java:108)
at org.geekbang.time.commonmistakes.collection.aslist.AsListApplication.wrong2(AsListApplication.java:41)
at org.geekbang.time.commonmistakes.collection.aslist.AsListApplication.main(AsListApplication.java:15)
//Element output
arr:[1, 4, 3] list:[1, 4, 3]

According to the console output,

Not only did we fail to append elements to the list,

Our modifications to the elements in the original array also affect the set list,

This is the third pit:

Pit 3: the modification of the original array will affect the List after conversion

Cause analysis:

Actually, Arrays The List returned by the aslist method is not the Java util. ArrayList, but the internal class ArrayList of Arrays.

The difference between the two is that the ArrayList inner class inherits from the AbstractList class and does not override the add method of the parent class, so the above exception is generated.

As for the third pit, because ArrayList directly uses the original array, it will have the effect of sharing arrays with each other.

If we pass through arrays The List obtained by aslist is handled by other methods. It is easy to modify each other because the array is shared, resulting in implicit "bug s".

It is difficult to find the cause of this problem, so we should be very careful.

Pit removal scheme:

The method is not hard to guess,

We just need to use a real Java util. ArrayList to store the converted list

String[] arr = {"1", "2", "3"};
//Use Java util. ArrayList receives the converted list
List list = new ArrayList(Arrays.asList(arr));
arr[1] = "4";
try {
list.add("5");
} catch (Exception ex) {
ex.printStackTrace();
}
log.info("arr:{} list:{}", Arrays.toString(arr), list);

Modified console output:

arr:[1, 4, 3] list:[1, 2, 3, 5]

The output meets our expectations.

Our new ArrayList can not only do the add operation, but also separate from the previous array.

This is a good solution to the problem!

end

Added by fresh on Sun, 26 Dec 2021 12:20:12 +0200