Java, java

Source: Internet
Author: User

[Switch] Java, java

A Data Structure is a collection of data in a certain form. It not only stores data, but also supports data access and processing operations. Java provides several data structures that can effectively organize and operate data. These data structures are generally called Java Collection frameworks. In normal learning and development, the flexible and skillful use of these collection frameworks can significantly improve our development efficiency. Of course, it is not enough to simply use them, understanding the design ideas and principles can improve our development level. The following is a summary of the Java Collection framework.

1. Overview 2. Collection interface 1. List 2.Set 3. Queue 3. Map interface 1. HashMap implementation principle 2. Other Map implementation classes 4. Other Collection classes 5. Summary
I. Overview

Before Java 2, Java did not have a complete set framework. It only has some simple container classes that can be expanded, such as Vector, Stack, and Hashtable. In the process of using these container classes, the efficiency problem has been criticized. Therefore, in Java 2, Java designers have made drastic changes and re-designed them, so they have the current collection framework. It should be noted that the previous container class libraries have not been discarded but are retained, mainly for the purpose of backward compatibility, but we should try to use them as little as possible during normal use.


Java Collection framework

From the preceding Collection frame diagram, we can see that the Java Collection framework mainly includes two types of containers: Collection, which stores one element set and Map ), store the key/value pair ing. The Collection interface has three seed types: List, Set, and Queue. The following are some abstract classes and the specific implementation classes, commonly used include ArrayList, sorted list, HashSet, sorted HashSet, HashMap, and LinkedHashMap.

Ii. Collection Interface

The Collection interface is the Root Interface for processing object sets. It defines many methods for operating elements. AbstractCollection is an abstract class that provides partial implementation of Collection. Shows all methods in the Collection interface.


Collection INTERFACE STRUCTURE

There are several common methods, such as adding () an element to the set, addAll () adds all elements in the specified set to the set, contains () the method checks whether the set contains the specified element. The toArray () method returns an array representing the set. The Collection interface has three subinterfaces, which are described in detail below.

1. List

The List interface extends the self-Collection, which can define an ordered set that can be repeated. From the method in the List interface, the List interface mainly adds location-oriented operations, the ListIterator allows you to operate on elements at a specified position and adds a new list iterator that can traverse linear tables in two directions. The AbstractList class provides partial implementation of the List interface. AbstractSequentialList is extended from AbstractList and mainly supports linked lists. The following describes two important implementation classes of the List interface, which are also the most commonly used classes, ArrayList and rule List.

ArrayList

By reading the source code of ArrayList, we can clearly see the logic in it. It uses an array to store elements. This array can be dynamically created. If the number of elements exceeds the size of the array, create a larger new array and copy all elements in the current array to the new array. Assume that there are no elements in the set for the first time. The following describes how to insert an element to the source code.

1. add (E e) to add the specified element to the set. Public boolean add (E e) {ensureCapacityInternal (size + 1); // Increments modCount !! ElementData [size ++] = e; return true ;}2. This method mainly determines the size of the array to be created. Private void ensureCapacityInternal (int minCapacity) {if (elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {minCapacity = Math. max (DEFAULT_CAPACITY, minCapacity);} ensureExplicitCapacity (minCapacity);} private void ensureExplicitCapacity (int minCapacity) {modCount ++; if (minCapacity-elementData. length> 0) grow (minCapacity);} 3. Create an array. You can see that the size of the added element is determined, and then the element is copied to the new array. Private void grow (int minCapacity) {// overflow-conscious code int oldCapacity = elementData. length; int newCapacity = oldCapacity + (oldCapacity> 1); if (newCapacity-minCapacity <0) newCapacity = minCapacity; if (newCapacity-MAX_ARRAY_SIZE> 0) newCapacity = hugeCapacity (minCapacity); // minCapacity is usually close to size, so this is a win: elementData = Arrays. copyOf (elementData, newCapacity );}

LinkedList

Similarly, when we open the source file of the listing list, it is not difficult to see that the listing list stores elements in a linked list.

When learning the data structure, we know that the biggest difference between linked lists and arrays is that they store different elements, which leads to different efficiency when performing different operations on data. Similarly, this is also true for ArrayList and rule list. In actual use, we need to select appropriate classes based on specific requirements. If you cannot insert or delete elements in other locations except the end, ArrayList is more efficient, if you need to insert or delete elements frequently, select the sequence list.

2. Set

The Set interface extends the self-Collection. The difference between the Set interface and the List is that the Set instance does not contain repeated elements. There must be no two equal elements in a rule set. AbstractSet is an abstract class that implements the Set interface. The Set interface has three specific implementation classes, namely, HashSet, javashashset, and TreeSet.

Hash set

A hash Set is a specific class used to implement the Set interface. You can use its non-parameter constructor to create an empty hash Set, you can also create a hash set from an existing set. In a hash, there are two terms to consider: initial capacity and seat rate. The passenger seat rate determines the full level of the rule set before the rule set is added. When the number of elements exceeds the product of the capacity and the passenger seat rate, the capacity will automatically double.

The following is an example of HashSet.

/** * @author JackalTsc */public class TestHashSet {    public static void main(String[] args) {        Set<String> set = new HashSet<>();        set.add("11111");        set.add("22222");        set.add("33333");        set.add("44444");        set.add("22222");        System.out.println(set.size());        for (String e : set) {            System.out.println(e);        }    }}

From the output results, we can see that the rule set has four elements at the end, and the elements are unordered during output.

Chain hash set

LinkedHashSet is implemented using a linked list to extend the HashSet class. It supports sorting of elements in the rule set. Elements in a HashSet are not sorted, while elements in a HashSet can be extracted in the order they are inserted into the rule set.

TreeSet

TreeSet extends from AbstractSet, implements NavigableSet, and AbstractSet extends from AbstractCollection. The tree Set is an ordered Set with a tree at the bottom, in this way, an ordered sequence can be extracted from the Set. When instantiating a TreeSet, we can specify a Comparator for the TreeSet to specify the element sequence in the tree. Tree sets provide many convenient methods.

The following is an example of TreeSet.

/*** @ Author JackalTsc */public class TestSet {public static void main (String [] args) {TreeSet <Integer> set = new TreeSet <> (); set. add (1111); set. add (2222); set. add (3333); set. add (4444); set. add (5555); System. out. println (set. first (); // output the first element System. out. println (set. lower (3333); // The largest element less than 3333 System. out. println (set. higher (2222); // The largest element greater than 2222 System. out. println (set. floor (3333); // The maximum element System. out. println (set. ceiling (3333); // The maximum element System. out. println (set. pollFirst (); // Delete the first element System. out. println (set. pollLast (); // Delete the last element System. out. println (set );}}
3. Queue

A queue is a first-in-first-out data structure. An element is added to the end of the queue and deleted from the queue header. The Queue interface extends the self-Collection and provides operations such as insertion, extraction, and validation.


Queue INTERFACE STRUCTURE

The offer method adds an element to the queue. Both the poll () and remove () Methods remove the element from the queue header. The difference between the two is that if the queue is empty, then poll () the return value is null, while remove () throws an exception. Methods element () and peek () are used to obtain the Header element without deleting it.

The Deque interface is a dual-end Queue extended from Queue. It supports element insertion and deletion at both ends. Because the destlist class implements the Deque interface, we can usually use the shortlist to create a Queue. The PriorityQueue class implements a priority queue. Elements in the priority queue are given a priority. elements with a high priority are deleted first.

/** * @author JackalTsc */public class TestQueue {    public static void main(String[] args) {        Queue<String> queue = new LinkedList<>();        queue.offer("aaaa");        queue.offer("bbbb");        queue.offer("cccc");        queue.offer("dddd");        while (queue.size() > 0) {            System.out.println(queue.remove() + "");        }    }}
Iii. Map Interface

A Map or graph is a container class that stores the ing of key-value pairs. In a Map, the key can be any type of object, but there cannot be duplicate keys. Each key corresponds to a value, the entries actually stored in the graph are composed of key values. The following is the class structure of the interface Map.


Interface Map Structure

From the figure above, we can see that interface Map provides many methods for querying, updating, and obtaining stored key-value pairs. updates include methods clear (), put (), and putAll () and remove (). The query methods include containsKey and containsValue. The Map interface is commonly used in three implementation classes: HashMap, LinkedHashMap, and TreeMap.

1. HashMap

HashMap is a non-synchronous Implementation of the Map interface based on the hash table. It inherits from AbstractMap, and AbstractMap is an abstract class that partially implements the Map interface. During normal development, HashMap is used a lot. We know that ArrayList mainly uses arrays to store elements. The ArrayList uses a linked list to store elements. What is the implementation principle of HashMap? First look at the figure below:


Hashmap .jpg

In earlier versions, HashMap uses arrays and linked lists to handle conflicts. linked lists with the same hash value are stored in one linked list. However, when there are many elements in the linked list, that is, there are many elements with the same hash value, the efficiency of searching by key values in turn is low. In JDK1.8, HashMap uses arrays + linked lists + red and black trees. When the length of a linked list exceeds the threshold (8), it converts the linked list to a red and black tree, greatly reducing the search time.

The following describes how it works through the source code.

Array of elements stored in HashMap

  transient Node<K,V>[] table;

The element types of the array are Node <K, V>, and Node <K, V> inherited from Map. Entry <K, V>, which indicates key-Value Pair ing.

Static class Node <K, V> implements Map. entry <K, V> {final int hash; final K key; V value; Node <K, V> next; // Constructor (Hash value key value next Node) node (int hash, K key, V value, Node <K, V> next) {this. hash = hash; this. key = key; this. value = value; this. next = next;} public final K getKey () {return key;} public final V getValue () {return value;} public final String toString () {return key + "=" + value;} publ Ic final int hashCode () {return Objects. hashCode (key) ^ Objects. hashCode (value);} public final V setValue (V newValue) {V oldValue = value; value = newValue; return oldValue;} public final boolean equals (Object o) {if (o = this) return true; if (o instanceof Map. entry) {Map. entry <?,?> E = (Map. Entry <?,?>) O; if (Objects. equals (key, e. getKey () & Objects. equals (value, e. getValue () return true;} return false ;}}

Next, let's take a look at the put Operation of HashMap.

Final V putVal (int hash, K key, V value, boolean onlyIfAbsent, boolean evict) {Node <K, V> [] tab; Node <K, V> p; int n, I; if (tab = table) = null | (n = tab. length) = 0) n = (tab = resize ()). length; // if not initialized, initialize table if (p = tab [I = (n-1) & hash]) = null) // here (n-1) & hash indicates the position (subscript) tab [I] = newNode (hash, key, value, null) of the element in the Array Based on the hash value ); // if no element exists in the position of the array, put the element directly to this position in the array else {Node <K, V> e; K k; // The hash value of the first node is the same, and the key value is the same as the inserted key if (p. hash = hash & (k = p. key) = key | (key! = Null & key. equals (k) e = p; else if (p instanceof TreeNode) // belongs to the red/black tree processing conflict e = (TreeNode <K, V>) p ). putTreeVal (this, tab, hash, key, value); else {/linked list processing conflict for (int binCount = 0; ++ binCount) {if (e = p. next) = null) {p. next = newNode (hash, key, value, null); if (binCount> = TREEIFY_THRESHOLD-1) //-1 for 1st // after adding a node, if the number of nodes reaches the threshold, the linked list is converted to treeifyBin (tab, hash); break;} if (e. hash = hash && (K = e. key) = key | (key! = Null & key. equals (k) break; p = e ;}// update the node Value with the same hash Value and key Value if (e! = Null) {// existing mapping for key V oldValue = e. value; if (! OnlyIfAbsent | oldValue = null) e. value = value; afterNodeAccess (e); return oldValue ;}++ modCount; if (++ size> threshold) resize (); afterNodeInsertion (evict); return null ;}

Next, let's take a look at the get operation of HashMap.

Final Node <K, V> getNode (int hash, Object key) {Node <K, V> [] tab; Node <K, V> first, e; int n; K k; if (tab = table )! = Null & (n = tab. length)> 0 & (first = tab [(n-1) & hash])! = Null) {if (first. hash = hash & // always check first node (k = first. key) = key | (key! = Null & key. equals (k) return first; if (e = first. next )! = Null) {// if the first node is TreeNode, the array + red/black tree structure is used to handle conflicts. // traverse the red/black tree to obtain the node value if (first instanceof TreeNode) return (TreeNode <K, V>) first ). getTreeNode (hash, key); do {if (e. hash = hash & (k = e. key) = key | (key! = Null & key. equals (k) return e;} while (e = e. next )! = Null) ;}} return null ;}

Here, the general implementation principle of HashMap should be very clear, and there are several important points to pay attention: the way HashMap stores elements and determines the location of the ing in the Array Based on the Hash value, as well as the Red/black tree added after JDK 1.8.

To locate an element in HashMap, You need to obtain the position in the corresponding Array Based on the hash value of the key. For any given object, as long as its hashCode () returns the same value, the hash code value calculated by the Program Calling the hash (int h) method is always the same. The first thing we think of is the modulo operation of the hash value on the array length. In this way, the element distribution is relatively even. However, the consumption of "modulo" operations is still relatively large. In HashMap,(N-1) & hashUsed to calculate the index of the table array where the object is stored. The underlying array length of HashMap is always the n power of 2. When the array length is the n power of 2,(N-1) & hashThe probability of the same index is small, and the data distribution on the array is relatively uniform, that is, the probability of collision is small, relative, you do not need to traverse the linked list at a certain position during query, in this way, the query efficiency is high.

2. LinkedHashMap

LinkedHashMap inherits from HashMap. It is mainly implemented by using a linked list to expand the HashMap class. Entries in HashMap are not ordered, but elements in LinkedHashMap can be sorted in the order they are inserted into graphs, you can also sort them in the order they were last accessed.

3. TreeMap

TreeMap is implemented based on the data structure of the red and black trees. Key values can be sorted using the Comparable or Comparator interfaces. TreeMap inherits from AbstractMap and implements the interface NavigableMap, while the interface NavigableMap inherits from SortedMap. SortedMap is a sub-interface of Map. It ensures that entries in the graph are sorted in order.

In actual use, if you do not need to keep the order of the elements in the graph when updating the graph, use HashMap. If you need to keep the insertion sequence or access sequence of the elements in the graph, use LinkedHashMap, if you want to sort the graph by key value, use TreeMap.

4. Other collection classes

The above section describes the Java Collection framework in detail, including the Collection and Map interfaces, their abstract classes, and common implementation classes. The following describes several other special Collection classes, vector, Stack, HashTable, ConcurrentHashMap, and CopyOnWriteArrayList.

1. Vector

As we have mentioned above, Java designers have retained some data structures when re-designing the previous container classes, including Vector. In terms of usage, the Vector and ArrayList are basically the same. The difference is that the Vector uses the keyword synchronized to synchronize the methods for accessing and modifying the Vector. Therefore, for applications that do not need to be synchronized, arrayList is more efficient than Vector.

2. Stack

Stack and Stack class, introduced before Java2, inherit from class Vector.

3. HashTable

HashTable is similar to the previously introduced HashMap. It is also a hash and stores key-Value Pair ing. The difference is that HashTable inherits from Dictionary, all functions in HashTable are synchronized, which means it is thread safe. In addition, keys and values in HashTable cannot be considered null.

The above three collection classes are all the container classes launched before Java2. We can see that although the efficiency is relatively low in use, they are all thread-safe. The following describes two special collection classes.

4. ConcurrentHashMap

Concurrent, concurrency. It can be seen from the name that ConcurrentHashMap is the thread security version of HashMap. Compared with HashMap, ConcurrentHashMap not only guarantees the security of the access thread, but also greatly improves the efficiency compared with HashTable. For the design of ConcurrentHashMap, I will introduce it in the next blog on concurrent programming. Stay tuned.

5. CopyOnWriteArrayList

CopyOnWriteArrayList is the implementation of a thread-safe List interface. It uses the ReentrantLock to ensure high-performance concurrent reading in the case of concurrency.

V. Summary

At this point, the summary of the Java Collection framework is over, and many collection classes are not mentioned here. More need to be checked and used by yourself. By reading the source code and reading materials, you have gained a lot.

  • Java Collection framework mainly includes Collection and Map types. Collection has three seed types: List, Set, and Queue. Map stores key-Value Pair ing.

  • The rule Set stores non-repeated elements. The linear table stores repeated elements. The Queue describes the first-in-first-out data structure. The Queue list can be used to implement queues.

  • In terms of efficiency, the rule set is more efficient than the linear table.

  • ArrayList mainly uses arrays to store elements, while list mainly uses linked lists to store elements. The underlying implementation of HashMap is mainly achieved through arrays, linked lists, and red/black trees.

  • Vector, HashTable, and other collection classes are less efficient, but all of them are thread-safe. The java. util. concurrent package contains a large number of collection classes for thread security, greatly improving the efficiency.



Author: Shiyu fanxin
Link: http://www.jianshu.com/p/63e76826e852
Source: Simplified book
Copyright belongs to the author. For commercial reprint, please contact the author for authorization. For non-commercial reprint, please indicate the source.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.