【11】Common containers

table of Contents

一、hashMap,hashTable,ConcurrentHashMap,hashSet

1、HashTable

2、HashMap

3、ConcurrentHashMap

4、hashSet

Two, TreeMap and TreeSet comparison

Three, the difference between ArrayList LinkedList Vector

Fourth, when using the iterator to traverse the ArrayList, modify the List and report ConcurrentModificationException

一、hashMap,hashTable,ConcurrentHashMap,hashSet

Both HashMap and hashTable implement the three interfaces of Map, Cloneable, and Serializable. But HashMap inherits from the abstract class AbstractMap , and HashTable inherits from the abstract class Dictionary. Both HashMap and hashTable use hash tables for storage.

Each entry in the array is a hash bucket

1、HashTable

HashTable is thread-safe . Adding a lock to the entire table means that when multiple threads access at the same time, they are converted into serial operations. But when using compound operations, threading is not safe .

table.contants() is the same as table.contantsValue().

HashTable lookup key: first calculate the hash value, directly replace it with the hashCode of the key, then calculate the index value in the array, find the "Entry (hash bucket) corresponding to the key", and then find the "key value" and search in the linked list Elements whose keys are equal (using the equals method)

Find value: From the Entry array, traverse each linked list from back to front to find (using the equals method to compare).

If the value of key or value in hashTable is null, an exception will be thrown.

 

2、HashMap

HashMap is not thread-safe

HashMap search key: store the element with "key is null" in table[0] , if "key is not null", call hash() to calculate the hash value , in the "hash bucket corresponding to the hash value" (actually The function is called to calculate the index value) to find the element whose key value is equal to key (using the equals method).  

Find value: If the key value is null, call the containsNullValue() method to search, if "value is not null", then find whether there is a value node in the HashMap (from the Entry array, traverse each linked list from front to back, or Use equals method to compare)

When elements are added to the two collections, the hashCode may conflict, which is also called a collision. When the collision occurs, the calculated hash bucket number (bucketIndex) is also the same, and then it will be retrieved to the bucketIndex position that has been stored Elements are finally compared by equals. The equals method is the method that will be executed when the hash code collides. Therefore, HashMap rarely uses equals. HashMap finally determines whether K already exists through hashCode and equals. If it already exists, replace the old V value with the new V value and return the old V value. If it does not exist, store the new key-value pair <K, V> to The header position of the hash bucket.

In HashMap, null can be used as a key, and there is only one such key ; there can be one or more keys corresponding to null. When the get() method returns a null value, it may be that the key does not exist in the HashMap, or the value corresponding to the key may be null. Therefore, in HashMap, the get() method cannot be used to determine whether a key exists in the HashMap , but the containsKey() method should be used to determine.

The default initial size of the HashTable is 11, and each time it is expanded to the original 2n+1 (to make the result of simple modular hashing more uniform and the hash table more uniform). The default initial size of HashMap is 16, and it is expanded to twice the original size each time afterwards (the use of bit operations is more efficient and the location of the hash bucket is faster). If the initial size is given at the time of creation, then HashTable will directly use the size you give, and HashMap will expand it to a power of two size.

When hashMap calls the put() method, it will use the addEntry() method, and then determine whether it is necessary to call the resize() method for expansion. Value pairs are recalculated and written into a new array, and then table points to the newly generated array.).

When the number of entries in the hash table exceeds the product of the load factor and the current capacity (array length), the hash table must be resized (that is, capacity expansion). The load factor defaults to 0.75

When the length of the linked list in the hash bucket is greater than 8, it will be converted into a red-black tree in JDK 1.8    

3、ConcurrentHashMap

The default length of the segment array is 16, which is the same as the HashMap. When expanding, only the HashEntry in a certain segment is expanded.

The lock segmentation mechanism is used before jdk1.8, and the CAS algorithm is used after jdk1.8. Please refer to https://blog.csdn.net/u011328417/article/details/79284730

ConcurrentHashMap is as thread-safe as HashTable, it is also thread-safe for compound operations.

4、hashSet

1. The bottom layer of HashSet is implemented using HashMap. The implementation of HashSet is relatively simple. Most of the methods of HashSet are implemented by calling the method of HashMap. Therefore, the implementation of the two sets of HashSet and HashMap is essentially the same.

2. The key of the HashMap is the object placed in the HashSet, and the value is of the Object type.

3. When the add method of HashSet is called, a row (key-value pair) is actually added to the HashMap. The key of the row is the object added to the HashSet, and the value of the row is a constant of Object type.

When adding an element, the element is actually put into the HashMap as the key. 

Since the put() method of HashMap adds a key-value pair, when the key of the newly put HashMap entry is the same as the key of the original entry in the collection (hashCode() returns the same value -> then call hash() is equal -> again The calculation index is equal, and the equals comparison also returns true),

The value of the newly added Entry will overwrite the value of the original Entry, but the key will not change in any way.

Therefore, if you add an existing element to the HashSet, the newly added set element will not be placed in the HashMap.

The original elements will not be changed in any way, which also satisfies the feature of non-repetition of elements in Set. (Consistent with the implementation of HashMap)

If the hash value calculated by the key is the same as the key of the original Entry in the collection, but equals returns false, then the object is added to the entry linked list (the newly added element is at the head of the linked list, which is consistent with the implementation of HashMap)

HashSet is not thread-safe

Two, TreeMap and TreeSet comparison

Similar to HashMap and HashSet, the bottom layer of TreeSet is implemented by TreeMap (the bottom layer is a red-black tree)

Same point:

Both TreeMap and TreeSet are ordered collections, which means that the values ​​they store are all sorted.

Both TreeMap and TreeSet are non-synchronized collections, so they cannot be shared between multiple threads, but you can use the method Collections.synchroinzedMap() to achieve synchronization

The running speed is slower than the Hash set. The time complexity of their internal operations on the elements is O(logN), while the HashMap/HashSet is O(1).

difference:

The main difference is that TreeSet and TreeMap implement Set and Map interfaces respectively

TreeSet only stores one object, while TreeMap stores two objects Key and Value (only key objects are ordered)

There can be no duplicate objects in the TreeSet, and the key in the TreeMap cannot be duplicated, and the value can be duplicated

The bottom layer of TreeMap adopts the implementation of red and black trees to complete the orderly insertion and sorting of data.

Red-black tree concept:

Nature 1. The node is red or black.

Property 2. The root node is black.

Property 3 Each leaf node (NIL node, empty node) is black.

Property 4 The two child nodes of each red node are black. (There cannot be two consecutive red nodes on all paths from each leaf to the root)

Property 5. All paths from any node to each leaf contain the same number of black nodes.

Three, the difference between ArrayList LinkedList Vector

Reference: https://blog.csdn.net/Li_lingxiao/article/details/78299550

The three are the same:

① These three classes all implement the List interface ( List interface inherits Collection interface )

②The order of addition is consistent with the serial number (but it does not mean that the storage location is continuous )

③The elements can be taken out according to the serial number

The similarities between ArrayList and Vector:

① Both are ordered collections, that is, the positions of the elements stored in these two collections are spatially ordered, that is, continuous, which is equivalent to a dynamic array .

Simply put, the underlying data of ArrayList and Vector is the structure of an array

The three are different:

LinkList: The spatial position of the elements stored in the collection is not continuous, and the underlying data structure is a circular doubly linked list structure

Both ArrayList and Vector use arrays to store data. The number of elements in this array is greater than the actual data stored in order to add and insert elements. Both of them allow direct indexing of elements by sequence number. The query speed is fast, but inserting and deleting elements involves array element movement, etc. Memory operation, so indexing data is fast and inserting data is slow.

LinkedList uses a doubly linked list to achieve storage. Indexing data by sequence number requires forward or backward traversal, but when inserting data, only the preceding and following items of this item need to be recorded. Therefore, the insertion and deletion speed is faster, and the search speed is slower.

Vector is synchronous processing with low performance; ArrayList uses asynchronous processing with high performance.

Vector is thread-safe, ArrayList, LinkedList are not thread-safe.

 

ArrayList and Vector memory allocation and expansion:

1>Vector and ArrayList have an initial capacity size (10). When the number of elements stored in them exceeds the capacity, the storage space of ArrayList and Vector needs to be increased (the number of storage units added each time A certain balance must be achieved between memory space utilization and program efficiency);

2> .Vector default growth turned out twice , and ArrayList growth strategy is not clearly defined in the document (see the source code from the original growth of 1.5 times )

3>. Both ArrayList and Vector can set the initial space size, Vector can also set the growth space size, but ArrayList does not provide a method to set the growth space

Fourth, when using the iterator to traverse the ArrayList, modify the List and report ConcurrentModificationException

Reference: https://www.cnblogs.com/liuling/p/2013-8-21-04.html

Because when next is called, it will be judged whether the collection has been modified. If it is modified, ConcurrentModificationException will be thrown. This problem still occurs when using Collections.synchronized to wrap collections.

CopyOnWriteArrayList will not have this exception, because the ArrayList will be copied after each modification, and the operation is another ArrayList

Note: When adding a lot of operations, the efficiency is low, because each time it is added, it will be copied and the overhead is very large. You can choose when there are many concurrent iterative operations.

Guess you like

Origin blog.csdn.net/Jack_PJ/article/details/88018030