The subList of List in the Android pit avoidance series should be used with caution

1. Scene

We know that the String class has the function of splitting strings (subString function), and of course it also provides the function of splitting collections (subList function) in the List collection.

However, the division method of List has pitfalls, such as the following code:

1. Normal use:

ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("a");
arrayList.add("b");
arrayList.add("c");
arrayList.add("d");
List<String> list = arrayList.subList(0, 2);
System.out.println(list);

output:

 2. The use of pits:

List<String> arrayList = new ArrayList<String>();
arrayList.add("a");
arrayList.add("b");
arrayList.add("c");
List<String> arrayList_subList = arrayList.subList(0, 2);
arrayList.remove(0);
arrayList.add("d");
System.out.println(arrayList_subList.size());

output:

 The last line reports an error. According to normal code logic thinking, arrayList_subList creates a new object List to save the split data. Subsequent changes to the parent List should not affect the child List, but it does not.

Second, the reason analysis:

See the official documentation for this function:

/**
 * Returns a view of the portion of this list between the specified
 * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive.  (If
 * {@code fromIndex} and {@code toIndex} are equal, the returned list is
 * empty.)  The returned list is backed by this list, so non-structural
 * changes in the returned list are reflected in this list, and vice-versa.
 * The returned list supports all of the optional list operations supported
 * by this list.<p>
 *
 * This method eliminates the need for explicit range operations (of
 * the sort that commonly exist for arrays).  Any operation that expects
 * a list can be used as a range operation by passing a subList view
 * instead of a whole list.  For example, the following idiom
 * removes a range of elements from a list:
 * <pre>{@code
 *      list.subList(from, to).clear();
 * }</pre>
 * Similar idioms may be constructed for {@code indexOf} and
 * {@code lastIndexOf}, and all of the algorithms in the
 * {@code Collections} class can be applied to a subList.<p>
 *
 * The semantics of the list returned by this method become undefined if
 * the backing list (i.e., this list) is <i>structurally modified</i> in
 * any way other than via the returned list.  (Structural modifications are
 * those that change the size of this list, or otherwise perturb it in such
 * a fashion that iterations in progress may yield incorrect results.)
 *
 * @param fromIndex low endpoint (inclusive) of the subList
 * @param toIndex high endpoint (exclusive) of the subList
 * @return a view of the specified range within this list
 * @throws IndexOutOfBoundsException for an illegal endpoint index value
 *         ({@code fromIndex < 0 || toIndex > size ||
 *         fromIndex > toIndex})
 */

 According to the notes:

1. This method returns a view of the parent list, from fromIndex (included) to toIndex (excluded). fromIndex=toIndex indicates that the sublist is empty

2. The non-structural changes (non-structural changes) made by the parent-child list will affect each other: the so-called "non-structural changes" refer to changes that do not involve changes in the size of the list. In contrast, structural modifications refer to modifications that change the size of the list.

3. For structural modifications, all operations on the child list will be reflected on the parent list. But the modification of the parent list will invalidate the returned child list .

4. Tips: How to delete a certain piece of data in the list:

list.subList(from, to).clear();

The following piece of code verifies the third point:

List<String> list = new ArrayList<String>();  
list.add("a");  
  
// 使用构造器创建一个包含list的列表list1  
List<String> list1 = new ArrayList<String>(list);  
// 使用subList生成与list相同的列表list2  
List<String> list2 = list.subList(0, list.size());  
list2.add("b");  
  
System.out.println(list.equals(list1));  
System.out.println(list.equals(list2));

output:

 3. Summary

         See more source code.

Guess you like

Origin blog.csdn.net/sunbinkang/article/details/121100556