Collection of Java

Collection iterator

There are currently three iterators in Java: Iterator Iterable ListIterator.

  1. First look at the Iterator interface:

public interface Iterator { boolean hasNext(); E next(); void remove(); } The meaning of the provided API interface is as follows: hasNext(): Determine whether there is another object in the collection. next(): Returns the next object in the collection and moves the access pointer one bit. remove(): Delete the object returned by calling the next() method in the collection. In the early version of the JDK, there was only one way to traverse the collection, and that was to operate through the Iterator. The specific examples are as follows:








复制代码
List list = new ArrayList<>();
list.add(10);
list.add(20);
list.add(30);
Iterator iter = list.iterator();
while (iter.hasNext()) {
Integer next = iter.next();
System.out.println(next);
if (next == 20) {
iter.remove();
}
}
复制代码
2. Iterable接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public interface Iterable { Iterator iterator(); // since JDK 1.8 default void forEach(Consumer<? super T> action) { Objects.requireNonNull(action); for ( T t: this) { action.accept(t); } } // since JDK 1.8 default Spliterator spliterator() { return Spliterators.spliteratorUnknownSize(iterator(), 0); } }  Iterator() method is provided in the Iterable interface It returns an iterator, so a collection that implements the Iterable interface can still use iterators to traverse and manipulate objects in the collection. In JDK 1.8, a new method forEach() was added to the Iterable interface, which allows an enhanced for loop to traverse objects.













为什么要设计两个接口Iterable和Iterator?Iterator接口的保留可以让子类去实现自己的迭代器,而Iterable接口更加关注于for-each的增强语法。
  1. ListIterator

ListIterator inherits the Iterator interface and only exists in the List collection. It can return the iterator whose starting index is index by calling the method. There are several important methods in ListIterator, most of which have the same meaning as defined in Iterator. In addition, according to the returned iterator, bidirectional traversal can be achieved.

1
2
3
4
5
6
7
8
9
10
11
12
public interface ListIterator extends Iterator { boolean hasNext(); E next(); boolean hasPrevious(); E previous(); int nextIndex(); int previousIndex(); void remove (); // Replace the element of the current subscript, that is, the last element visited void set(E e); void add(E e); ) Three, Map and Collection interface











The Map interface and the Collection interface are two important schools in the Java collection framework. Collection stores the collection elements themselves, and Map stores <key, value> key-value pairs, but some Collection subclasses use Map to achieve. For example: the bottom layer of HashSet uses HashMap, the bottom layer of TreeSet uses TreeMap, and the bottom layer of LinkedHashSet uses LinkedHashMap.

The data structure of the Map interface is in the form of <key, value>. Key maps value. A key corresponds to a value. The key cannot be repeated, and the value can be repeated. The Map interface is subdivided into different categories:

SortedMap接口:该类映射可以对<key, value>按照自己的规则进行排序,具体实现有 TreeMap
AbsractMap抽象类:它为子类提供好一些通用的API实现,所有的具体Map如HashMap都会继承它

The Collection interface provides common methods for all collections (note that Map is not included here):
add method: add(E e) / addAll(Collection<? extends E> var1)/ addAll(int index, Collection<? extends E> var1)
Find method: contains(Object var1) / containsAll(Collection<?> var1)/
Query the information of the collection itself: size() / isEmpty()
Delete method: remove(O o)/removeAll(Collection<?> var1)/Find the intersection : RetainAll(Collection c)

... ...

The Collection interface subdivides collections into different categories:

Set接口:一个不允许存储重复元素的无序集合,具体实现有HashSet / TreeSet···
List接口:一个可存储重复元素的有序集合,具体实现有ArrayList / LinkedList···
Queue接口:一个可存储重复元素的队列,具体实现有PriorityQueue / ArrayDeque···
  1. Detailed explanation of Map interface The
    Map system is mainly divided into two types of collections: AbstractMap and SortedMap.
    AbstractMap is an extension of the Map interface. It defines the common methods of ordinary Map collections, which can avoid subclasses from writing a large amount of the same code. Subclasses can be repeated after inheriting AbstractMap. Write its method and implement additional logic to provide more external functions.
    The SortedMap interface defines the sorting behavior of Map. When subclasses implement it, all methods must be rewritten to provide sorting functions to the outside world.

1.1 HashMap
HashMap is a collection of the most common use of hash tables to store elements. When an element is added to the HashMap, the hash value of the key will be converted to the index subscript of the array to determine the storage location. When searching for the element, it is based on the hash of the key. The address is converted into the index subscript of the array to determine the search position.
The bottom layer of HashMap is implemented with three data structures: array + linked list + red-black tree, which is a non-thread-safe collection.

When adding elements have a hash conflict, HashMap will link the elements with the same address into a linked list. If the linked list length is greater than 8, and the array length is greater than 64, it will be converted into a red-black tree data structure.

A brief summary about HashMap:
1. It is the most commonly used Map collection type in the collection. The bottom layer is composed of array + linked list + red-black tree;
2. HashMap is not thread-safe;
3. When inserting an element, calculate the element hash value , Is converted into an array subscript through the hash mapping function; when looking for an element, the position of the array subscript positioning element is obtained through the hash mapping function.

1.2 LinkedHashMap
LinkedHashMap can be regarded as a combination of HashMap and LinkedList: it adds a doubly linked list on the basis of HashMap, and stores the insertion order of each element by default, but because of this doubly linked list, LinkedHashMap can implement the LRU cache elimination strategy. Because we can set this doubly linked list to be sorted according to the access order of the elements

1
2
3
4
// The head node
transient LinkedHashMap.Entry<K, V> head;
// The tail node
transient LinkedHashMap.Entry<K, V> tail;
LinkedHashMap can be used to implement the LRU cache elimination strategy, because it provides a method :

1
2
3
protected boolean removeEldestEntry(java.util.Map.Entry<K, V> eldest) { return false; } This method can remove the node closest to the head of the linked list, and the source code of the get(key) method is as follows , Its role is to move the position of the node:


1
2
3
4
5
6
7
8
public V get(Object key) { Node<K,V> e; if ((e = getNode(hash(key), key)) == null) return null; if (accessOrder) afterNodeAccess(e); return e.value; } As long as get(key) is called and accessOrder = true, the node will be updated to the end of the linked list. The specific logic is in afterNodeAccess(). The source code is as follows:







Copy code
void afterNodeAccess(Node<K,V> e) {// move node to last
  LinkedHashMap.Entry<K,V> last;
  if (accessOrder && (last = tail) != e) {     LinkedHashMap.Entry<K, V> p = (LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after;     p.after = null;     if (b == null) head = a;      else b.after = a;     if (a != null) a.before = b;     else last = b;     if (last == null) head = p;     else {       p.before = last;       last.after = p;     }     tail = p;     ++modCount;   } } Copy code Specify accessOrder = true, you can set the linked list to be arranged in the order of access, and accessOrder can be set through the provided constructor.
















public LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) { super(initialCapacity, loadFactor); this.accessOrder = accessOrder; } Rewrite the removeEldestEntry() method, internally defined logic, usually to determine whether the capacity reaches the upper limit, and if so, perform elimination .



Summarize two points about LinkedHashMap:
1. The bottom layer maintains a doubly linked list, inheriting HashMap, so it is not thread-safe
2. LinkedHashMap can implement the LRU cache elimination strategy, the principle is to define eliminated elements by setting accessOrder to true and rewriting the removeEldestEntry method The conditions to be met at the time.

1.3 TreeMap
TreeMap is a subclass of SortedMap, so it has a sorting function. It is implemented based on red-black tree data. Each key-value pair <key, value> is a node, which is naturally sorted by key by default. One is that it can be sorted by custom rules by passing in a custom Comparator.

// According to the key natural sorting, the natural sorting of Integer is ascending
TreeMap<Integer, Object> naturalSort = new TreeMap<>();
// Custom sorting, sorting in descending order of key
TreeMap<Integer, Object> customSort = new TreeMap<>( (o1, o2) -> Integer.compare(o2, o1));

Each node of the red-black tree in the figure is an Entry. The key and value are not marked here. These elements have been sorted according to the key, and the entire data structure is in an orderly state!
Regarding natural sorting and custom sorting:
natural sorting: the key must implement the Comparable interface.
Since the Integer class implements the Comparable interface, according to the natural sorting rule, the key is sorted from small to large.

TreeMap<Integer, String> treeMap = new TreeMap<>();
treeMap.put(2, "贰");
treeMap.put(1, "壹");
System.out.print(treeMap);
// {1 =一, 2=2}
Customized sorting: when initializing the TreeMap, pass in a new Comparator, and the key is not required to implement the Comparable interface

Copy the code
TreeMap<Integer, String> treeMap = new TreeMap<>((o1, o2) -> Integer.compare(o2, o1));
treeMap.put(1, "壹");
treeMap.put(2, "贰");
treeMap.put(4, "
"); treeMap.put(3, "三");
System.out.println(treeMap);
// {4=4, 3= , 2=2, 1=一}
Copy code
Three points about TreeMap are mainly introduced:
1. Its bottom layer is implemented by red-black trees, and the operation time complexity is O(logN);
2. TreeMap can sort keys naturally or by custom sorting , Comparator needs to be passed in for custom sorting, while natural sorting requires keys to implement the Comparable interface;
3. TreeMap is not thread-safe.

1.4 WeakHashMap
The data structure of the elements stored at the bottom of WeakHashMap is an array + a linked list, and there is no red-black tree. It is rarely used in daily development. It is implemented based on Map. The key in Entry will be cleared every garbage collection. It is suitable for elements that are accessed briefly or once, cached in WeakHashMap, and recycled as soon as possible.

public class WeakHashMap<K, V> extends AbstractMap<K, V> implements Map<K, V> { }   When Entry is GC, how does WeakHashMap perceive that an element is recycled?

    在 WeakHashMap 内部维护了一个引用队列queue:

private final ReferenceQueue queue = new ReferenceQueue<>(); The
queue contains all the keys dropped by GC. When the JVM turns on the GC, if the key in the WeakHashMap is recycled, the key will be placed in the queue, in expungeStaleEntries() Traverse the queue, take out all the keys in the queue, and delete them in the WeakHashMap to achieve synchronization.

The element marked by the dotted line in the figure will be deleted the next time WeakHashMap is accessed. WeakHashMap will do a series of adjustments internally, so the role of the queue is to mark the elements that have been GC removed.
There are three points to note about WeakHashMap:
1. Its key is a kind of weak key. When it is put into WeakHashMap, it will be recycled at any time, so there is no guarantee that certain access elements must exist;
2. It relies on ordinary Map for implementation. A non-thread-safe collection;
3. WeakHashMap is usually used as a cache, suitable for storing key-value pairs that only need to be accessed once or only need to be stored for a short time.

1.5 HashTable The
underlying storage structure of Hashtable is an array + linked list, which is a thread-safe collection. When the linked list is too long, the query efficiency is too low and the Hashtable will be locked for a long time. Therefore, in a concurrent environment, the performance is very poor. It is basically eliminated and rarely used. Thread safety, all its methods have been added the synchronized keyword. The default length of HashTable is 11, and the load factor is 0.75F, that is, when the number of elements reaches 75% of the array length, an expansion will be carried out, and each expansion will be twice the original array length.

  1. Detailed Explanation of
    Collection Collection System The top-level interface of Collection collection system is Collection, which specifies a series of methods under the collection.
    The collection can be divided into three types of collections: List, Set and Queue
    Set interfaces: duplicate elements cannot be stored, and any operation needs to be mapped to the internal positioning elements of the collection through a hash function, and the internal elements of the collection are out of order by default.
    List interface: can store repeated elements, and the elements in the collection are arranged in order according to the order in which the elements are inserted, and the elements can be accessed by index.
    Queue interface: The queue is used as the storage structure, and the elements in the collection are arranged in an orderly manner. Only the head node elements can be operated, and the elements in the middle of the queue cannot be accessed.
    The above three interfaces are the most common and abstract implementations, and within each collection interface, there will be more specific performance, deriving a variety of additional functions, so that developers can compare the advantages of each collection and use them based on the best.

2.1 Set interface The
Set interface inherits the Collection interface and is a collection that does not include repeated elements. To be more precise, any two elements in Set will not appear o1.equals(o2), and Set can only store at most one NULL value element .

In the Set collection system, we need to focus on two points: When
storing variable elements, we must be very careful, because any time the element state changes, it is impossible to make two equal elements appear in the Set, namely o1.equals( o2) = true, so generally do not change the elements stored in the Set, otherwise the function of equals() will be destroyed!
The biggest role of Set is to judge heavy, and the biggest role in the project is to judge heavy!

The
bottom layer of HashSet HashSet is implemented with HashMap, we can observe its multiple construction methods, which are essentially new and a HashMap

Copy the code
public class HashSet the Set the extends the AbstractSet the implements, the Cloneable, the Serializable { public HashSet () { this.map new new = the HashMap (); } public HashSet (int initialCapacity, a float loadFactor) { this.map new new = the HashMap (initialCapacity, loadFactor) ; } public HashSet(int initialCapacity) { this.map = new HashMap(initialCapacity); } } Copy code We can observe how the add() method and remove() method graft the operation of HashSet to HashMap.











Copy the code
Private the PRESENT static Final Object = new new Object ();
public Boolean the Add (E E) { return this.map.put (E, the PRESENT) == null; } public Boolean Remove (Object O) { return this.map. remove(o) == PRESENT; } Copy the value of the code HashMap. Developers using HashSet only need to pay attention to the key that needs to be inserted, shielding the value of HashMap






HashSet is implemented on the basis of HashMap, so many places can be linked to HashMap:
Underlying data structure: HashSet also uses array + linked list + red-black tree to achieve
thread safety: due to the implementation of HashMap, HashMap itself is not thread-safe and not in HashSet Add an additional synchronization strategy, so HashSet is also thread-unsafe to
store the state of the object in HashSet, it is best not to change, because it is possible that after the state is changed, two elements o1.equals(o2) appear in the set, destroying equals( ) Semantics.

LinkedHashSet
LinkedHashSet has a pitiful little code, as follows:

复制代码
public class LinkedHashSet
extends HashSet
implements Set, Cloneable, java.io.Serializable {

private static final long serialVersionUID = -2851667679971038690L;
public LinkedHashSet(int initialCapacity, float loadFactor) {
    super(initialCapacity, loadFactor, true);
}
public LinkedHashSet(int initialCapacity) {
    super(initialCapacity, .75f, true);
}
public LinkedHashSet() {
    super(16, .75f, true);
}
public LinkedHashSet(Collection<? extends E> c) {
    super(Math.max(2*c.size(), 11), .75f, true);
    addAll(c);
}
@Override
public Spliterator<E> spliterator() {
    return Spliterators.spliterator(this, Spliterator.DISTINCT | Spliterator.ORDERED);
}

}
Amazon evaluation www.yisuping.com

Guess you like

Origin blog.csdn.net/weixin_45032957/article/details/108576533