“This is the second day of my participation in the First Challenge 2022, for more details: First Challenge 2022”.


  • 🤟 blogger introduction: CSDN, Toutiao, Zhihu and other platforms quality bloggers, the whole network fans 2W +
  • 💬 If the article is helpful to you, welcome to follow, like, bookmark (click three links) and subscribe

Common set deletion problem: use a for loop to match an element, then delete it, and guess what the following code outputs?

List<String> list = new ArrayList<>(); List. The add (" taobao "); List. The add (" taobao "); List. The add (" nuggets "); For (String item: list) {if(" taobao ". Equals (item)) {list.remove(item); } } System.out.println(list);Copy the code

Answer: output, taobao, the nuggets 】 【 we want to delete the collection is intended as “taobao” elements, but because in a loop to the list using the remove method, so that once have element will be removed after the collection of the size becomes smaller, so that the original elements on the left will change, the final loop exit ahead of time, specific to see the following drawings resolution:

Solution:

Method 1: After the remove method is called, add: I –, so that the next coordinate goes back to the one before the deleted element (because this deletion will move all elements after the deleted element one bit to the left).

List.removeif (e -> “taobao”.equals(e)).

Second, use the enhanced for loop to delete elements. Guess what the following code outputs?

List<String> list = new ArrayList<>(); List. The add (" taobao "); List. The add (" taobao "); List. The add (" nuggets "); For (String item: list) {if(" taobao ". Equals (item)) {list.remove(item); } } System.out.println(list);Copy the code

Answer: throw ConcurrentModificationException, directly to the enhanced for loop is just a syntactic sugar actually, it’s convenient, developers use the virtual machine is the actual execution time is, through the way of the iterator cycle for the above code decompiled get the following code:

List<String> list = new ArrayList(); List. The add (" taobao "); List. The add (" taobao "); List. The add (" nuggets "); Iterator iterator = list.iterator() while(iterator .hasNext()) { String item = (String)iterator .next(); If (" taobao ". Equals (item)) {list.remove(item); } } System.out.println(list);Copy the code

Why does iterator looping throw this exception when an element is deleted during the loop? In fact, the iterator first executes checkForComodification() every time it calls the next() method. The purpose of this method is to check the list whether modCount and expectedModCount under the value of a variable consistent (can be understood as a version number), if not consistent, throw ConcurrentModificationException directly.

How does deletion work? In fact, the modCount variable represents the number of times the set is modified. Each time the set is added or removed, it is incremented by 1. When the remove method of the set is called, the value of the variable is incremented by 1, but the value of the expectedModCount does not change. When the next method is executed again, the values are not equal and an exception is thrown.

Solution: Use the iterator’s remove method to change the code removed above to: Iterator.remove (), the iterator’s remove method assigns the modCount value to the expectedModCount, so the next time the next method executes the same value, the exception will not be thrown.

A more elegant solution: use the removeIf method provided in java8, such as list.removeif (e -> “taobao”.equals(e)), which also uses iterators internally to delete.

Now that we know the solution, let’s dig into the purpose of throwing an exception.

In fact, it is a protection mechanism of the set, called “fast failure”, because the remove operation of the set is non-atomic. In the case of multi-threading, one thread may perform the deletion operation when traversing by another thread. When the elements of the set are deleted, the capacity of the set will be reduced. The coordinate of the element behind the deleted element will move one bit forward, so that some elements may be missed during the iteration of the cycle. Such data difference may not lead to abnormal conditions in the current scene, but will lead to abnormal conditions in some code links, which increases the difficulty of investigation.

When the “fast fail” mechanism is provided, if another thread removes the element during the traversal and the modCount and expectedModCount are inconsistent, an exception is thrown and the iteration is stopped so that we can quickly locate the cause and location of the exception.

Three: Integer type comparison, guess what result is returned below

public static void test3(){
    Integer a = 127;
    Integer b = 127;
    Integer c = 128;
    Integer d = 128;
    
    System.out.println(a == b);
    System.out.println(c == d);
    System.out.println(c.equals(d));
}
Copy the code

Answer: The answers are true, false, true, and you guessed it?

Because Integer caches values from -128 to 127, when the “==” comparison is used, it actually compares the addresses of two objects, because Integer caches values from -128 to 127. So the same two values in this range will return true using == or equals because they are directly fetched from the cache, but not in this range will return false.

Two identical values outside this range also return true when compared using the equals method, because Integer internally overrides the equals method, which compares the values in the two objects instead of the addresses.

Suggestion: When using wrapper classes to compare values, do not use “==”, instead use the equals method.


If the article is helpful, please pay attention to the author, like, favorites, comments, so that the blogger is motivated to create better quality articles.