12. Assembly
12.1 collective system
Sets are mainly two groups (single column Set and double column Set). The Collection interface has two important sub interfaces List and Set. Their implementation subclasses are single column sets, and the implementation subclass of the Map interface is double column sets, which store K-V
12.2 Collection interface
- Collection implementation subclass can store multiple elements, and each element can be an Object
- Some Collection implementation classes can store duplicate elements, and some cannot
- The Collection interface does not directly implement subclasses, but is implemented through its sub interfaces Set and List, where List is ordered and Set is not ordered.
12.2.1 common methods of collection interface:
Demonstration of implementing class with ArrayList:
List col = new ArrayList();
-
Add: add a single element
col.add("Xiao Wang"); col.add(999); System.out.println("col = " + col);//col = [Xiao Wang, 999]
-
remove: deletes the specified element
boolean bool = col.remove((Integer)999);//Delete element, delete 999, and the return value is boolean System.out.println(bool); System.out.println("col = " + col); //The result is: //true //col = [Xiao Wang, 0]
-
contains: find whether the element exists
//The return value is boolean System.out.println(col.contains("Xiao Wang"));//Result: true
-
size: get the number of elements
//The return value is int System.out.println(col.size());//Results: 2
-
isEmpty: judge whether it is empty
//The return value is boolean System.out.println(col.isEmpty());//Result: false
-
Clear: clear
//No return value col.clear(); System.out.println("col = " + col);//Result: col = []
-
addAll: add multiple elements
//The return value is boolean, 1: a parameter, Collection; List list = new ArrayList(); list.add("Zhang"); list.add("three"); list.add("Abundant"); boolean b = col.addAll(list); System.out.println(b); System.out.println(col); //result: //true //[Zhang, San, Feng]
-
containsAll: find whether multiple elements exist
//The parameter is collection and the return value is boolean System.out.println(col.containsAll(list));//The result is: true
-
removeAll: deletes multiple elements
//The parameter is Collection and the return value is boolean System.out.println(col.removeAll(list)); System.out.println(col); //The result is //true //[]
12.2.2 set traversal
-
Use iterator
-
The Iterator object is called an Iterator and is mainly used to traverse the elements in the Collection
-
All Collection classes that implement the Collection interface have an iterator() method to return an object that implements the Iterator interface, that is, an Iterator can be returned
-
Iterator structure:
-
Iterator is only used to traverse collections, and iterator itself does not store objects
Usage example:
ArrayList arrayList = new ArrayList(); arrayList.add(new Book("Romance of the Three Kingdoms",53.2)); arrayList.add(new Book("The Dream of Red Mansion",45.6)); arrayList.add(new Book("Water Margin",12.3)); arrayList.add(new Book("Journey to the West",34)); Iterator iterator = arrayList.iterator(); while (iterator.hasNext()) { Object book = iterator.next(); System.out.println(book); }
Details:
- The Collection subclass instance calls the iterator() method to get the iterator
- The iterator calls the hasNext() method to determine whether there is another element
- The iterator calls the next method, moves the pointer down, and returns the element at the position after the move down. The type is Object
- After traversal, next points to the last element. Calling again will throw an exception. To use it again, you need to reset the iterator first. Reset the iterator: iterator = arrayList.iterator();
-
-
Enhanced for
The enhanced for is a simplified version of the iterator. The underlying code is still an iterator and can only be used to traverse a set or array
ArrayList arrayList = new ArrayList(); arrayList.add(new Book("Romance of the Three Kingdoms",53.2)); arrayList.add(new Book("The Dream of Red Mansion",45.6)); arrayList.add(new Book("Water Margin",12.3)); arrayList.add(new Book("Journey to the West",34)); // Enhanced for // The underlying iterator is still used for (Object book : arrayList) { System.out.println(book); }
12.3 List interface
- The List interface is a sub interface of the Collection interface
- Each element in the List collection class is ordered (that is, the addition order is the same as the extraction order) and repeatable
- Each element in the List collection has its corresponding sequential index, that is, it supports index
- The elements in the List container correspond to an integer serial number, recording their position in the container. You can save the elements in the container according to the serial number
List common methods
-
add: inserts an element at the index position
arrayList.add(1,"test"); System.out.println(arrayList);
-
addAll: add all elements in the collection from the index position
arrayList.addAll(1,arrayList); System.out.println(arrayList);
-
get: gets the element at the specified index location
Object abc = arrayList.get(2);
-
indexOf: gets the index of the first occurrence of an element
int test = arrayList.indexOf("test");
-
lastIndexOf: gets the index of the last occurrence of the element
int test1 = arrayList.lastIndexOf("test");
-
remove: removes the specified index element
Object remove = arrayList.remove(5);
-
set: modify index elements
Object abc = arrayList.set(2, "abc");
-
subList: get the subset of [2,4]
arrayList.subList(2,4);
List three Traversals
-
Iterator iterator
Same as Collection
Iterator iterator = arrayList.iterator(); while (iterator.hasNext()) { Object next = iterator.next(); System.out.println(next); }
-
Enhanced for
for (Object obj : arrayList) { System.out.println(obj); }
-
Ordinary for
for (int i = 0;i < arrayList.size();i++){ System.out.println(arrayList.get(i)); }
12.4 ArrayList
ArrayList is an implementation class of the List interface
-
An array elementData of Object type is maintained in ArrayList
transient Object[] elementData;//rtansient indicates instantaneous and transient, indicating that the attribute will not be by serial number
-
When creating an ArrayList object, if a parameterless constructor is used, the initial elementData capacity is 0. If it is added for the first time, the expanded elementData is 10. If it needs to be expanded again, the expanded elementData is 1.5 times
-
If a constructor of the specified size is used, the initial elementData capacity is the specified size. If capacity expansion is required, the direct capacity expansion of elementData is 1.5 times
-
ArrayList can store null
-
ArrayList is basically equivalent to Vector, except that ArrayList is thread unsafe (high execution efficiency)
ArrayList add elements and expand capacity
Capacity expansion:
- Judge whether the ArrayList is empty. If it is empty, it is considered that at least 10 spaces need to be allocated; otherwise, it is considered that at least size+1 spaces need to be allocated
- Judge whether the current space is greater than the minimum required space. If the current space is greater than the minimum required space, it does not need to be allocated
- Compare the required space with 1.5 times of the current space, and take the larger one as the real space to be allocated
- Allocate space with the Arrays.copyOf() method
Add element:
elementData[size++] = e;
Source code:
//No parameters: ArrayList arrayList = new ArrayList(); arrayList.add("Xiao Wang"); //Enter source code public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; } private void ensureCapacityInternal(int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); } private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); } 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); }
12.5 Vector
Vector and ArrayList are basically the same, but vector is thread safe
12.6 LinkedList
- The underlying layer of LinkedList maintains a two-way linked list, which realizes the characteristics of two-way linked list and two end queue
- ListedList maintains two properties, first and last, which point to the first node and the last node respectively
- Each Node (Node object) maintains three attributes: prev, next and item. Prev points to the previous Node and next points to the next Node. Finally, a two-way linked list is realized
- The addition and deletion of ListedList elements are relatively efficient
- LinkedList can add any element (elements can be repeated), including null
- Thread is unsafe and synchronization is not implemented
Example of double linked list:
public class LinkedList01 { public static void main(String[] args) { Node tom = new Node("tom"); Node jack = new Node("jack"); Node ross = new Node("ross"); tom.next = jack; jack.next = ross; ross.pre = jack; jack.pre = tom; Node first = tom;//Let the first reference point to jack, the head node of the bidirectional linked list Node last = ross;//Let the last reference point to ross, the tail node of the two-way linked list while (true){ if(first == null){ break; } System.out.println(first); first = first.next; } } } class Node{ public Object item; public Node next; public Node pre; public Node(Object name){ this.item = name; } @Override public String toString() { return "Node name=" + item; } }
Common methods:
-
remove: deletes a node
linkedList.remove(); // Delete first node linkedList.remove(2); // Delete the node of index 3
-
set: modify node
linkedList.set(1,100); // Modify the second node to 100
-
Get: get node
linkedList.get(1); // Get 2nd node
LinkedList add element source code:
public boolean add(E e) { linkLast(e); return true; } void linkLast(E e) { // The prev of the new node points to the last node of the current linked list final Node<E> l = last; // Create a new node final Node<E> newNode = new Node<>(l, e, null); // last points to the new node last = newNode; // Determine whether the linked list is empty if (l == null) // The linked list is empty, and first also points to the new node first = newNode; else // The linked list is not empty. The next of the original last node points to the new node l.next = newNode; size++; modCount++; }
ArrayList and LinkedList comparison:
- If we have many operations to check and modify, select ArrayList
- If we add and delete many operations, select LinkedList
- Generally speaking, in the program, 80% ~ 90% are queries, so ArrayList will be selected in most cases
12.7 Set interface
The Set interface is a sub interface of the Collection interface
- The addition and extraction sequences are inconsistent, but the extraction sequence is fixed (that is, after the same object is extracted once, the extraction sequence is the same every time)
- Adding duplicate elements is not allowed, so it can contain at most one null
- Traversal cannot use indexes
- Common methods are consistent with Collection
give an example:
Set set = new HashSet(); set.add("jack"); set.add("tom"); set.add("jack"); set.add(null); set.add(null); System.out.println(set); //Result: [null, tom, jack]
12.8 HashSet
HashSet implements the Set interface. The bottom layer of HashSet is HashMap, and the bottom layer of HashMap is array + linked list + red black tree
public HashSet() { map = new HashMap<>(); }
There is a Node internal class in the HashMap as a Node; There are four variables in the Node class (hash, key, value, next); There is a Node array table in HashMap. Each element of table is a chain header Node, forming an array + linked list structure
Add element:
- When adding an element, get the hash value first (the calculation of hash value is related to the hashCode method of adding an element)
- Calculate the index value stored in the table according to the obtained hash value
- Check whether the element has been stored in the index position. If it is not directly added
- If yes, judge whether the added element and the current index element are the same element (judgment method: compare the hash in Node with the hash value of the element to be added, and the added element calls the equals method to compare with the key in Node)
- If it is the same element, the addition is discarded
- If it is not the same element, it is compared with the next node in the linked list
- Discard the addition until the same element is encountered
- If the traversal of the linked list is different, it will be added to the last element of the linked list
Add element source code:
public static void main(String[] args) { HashSet set = new HashSet();//Create a HashSet object String name = "jack";//Create String "jack" set.add(name);//Add element set.add("tom");//Add element set.add("null");//Add element int h = name.hashCode();//Get the hashCode of jack and assign it to h, System.out.println(h);//Output hashCode of jack System.out.println((15 & (h ^ (h >>> 16))));//Output the index value stored by name in the table in the set object. The calculation method is (the length of the current table - 1) & (the hashcode value of name ^ the hashcode value of name moves 16 bits to the right without sign) System.out.println(set);//Output set } Enter the source code: //1. enter the add method, e is the incoming parameter object, and PRESENT is a static shared property of HashSet, specifically: private static final Object PRESENT = new (); and then call the method. public boolean add(E e) { return map.put(e, PRESENT)==null; } //Entering the put method, key is the incoming object, value is the empty Object object, then the hash value of key is calculated, then putVal method is called. public V put(K key, V value) { return putVal(hash(key), key, value, false, true); } //Enter the hash method, judge whether the object is empty, and return 0 if it is empty. Otherwise, XOR the hashcode value of the object with its own unsigned right shifted value of 16 bits, and return the value static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); } //Enter the putVal method, //First, judge whether the table array of the current HashSet object is empty or whether the array length is zero. If it is true, call the resize method to initialize the table array. After initialization, the length of the table array is 16, //Then judge whether the index of the table array (the table array length - 1 and the hash value of the object are summed) is empty. If it is empty, it will be directly put into the node, //Otherwise, it means that the linked list of the index has nodes, //Then compare the hash value of the head node of the linked list with the hash value of the incoming object. If it is equal, and the address of the incoming object is equal to that of the object pointed to by the head node, or the incoming object is not empty and the value of the incoming object is the same as that of the head node, it is considered that the incoming object is equal to the head node and the element is not added, //Otherwise, if the table array is a red black tree, judge whether to add it, //Otherwise, it means that the table array is not a red black tree, and the object pointed to by the head node is different from the incoming object. Then enter the for loop and traverse the nodes after the head node. If it is found that the object pointed to by a node is the same as the incoming object, break and jump out of the loop; if it is found that no node points to the same object as the incoming object after the loop, insert the incoming object into the tail node Then, judge whether the index length of the table array exceeds the limit, z 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 ((p = tab[i = (n - 1) & hash]) == null) tab[i] = newNode(hash, key, value, null); else { Node<K,V> e; K k; if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) e = p; else if (p instanceof TreeNode) e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value); else { 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 treeifyBin(tab, hash); break; } if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) break; p = e; } } 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; }
Details:
- The table in the map in the new HashSet is empty
- The add method is the put method that calls the map
- The space for adding the element table for the first time is initialized to 16
- After adding elements, if the number of nodes in the table exceeds 0.75 times the table space or the length of the linked list exceeds 8, the capacity will be doubled
- If the number of elements in the linked list exceeds 8 and the table space is greater than or equal to 64, the linked list will be trealized (red black tree)
- The size method gets the number of nodes
12.9 LinkedHashSet
LinkedHashSet is a subclass of HashSet. The underlying layer of LinkedHashSet is a LinkedHashMap. LinkedHashMap is a subclass of HashMap. The underlying layer of LinkedHashMap maintains an array + two-way linked list
Add and remove in the same order: use a linked list to make elements appear to be saved in insertion order
LinkedHashMap has an Entry internal class as a Node, which inherits the internal class Node of HashMap; the Entry class adds (before, after) on the basis of the four variables (hash, key, value, next) of Node , respectively pointing to the previous and next nodes of the bidirectional linked list; LinkedHashMap still uses the Node array table of the inherited HashMap. Each element of the table is a chain header Node. Because entity inherits the Node, the Entry can be put into the table (polymorphic); LinkedHashMap also has member variables (head, tail) , respectively point to the head and tail of the two-way linked list; form an array + two-way linked list structure
The process of adding elements is basically the same as that of HashSet (LinkedHashSet does not override the put method, that is, the put method of the executed HashMap). However, LinkedHashMap overrides the method of adding new nodes, newNode. The actual added objects are changed to Entry objects, and the head and tail of the two-way linked list are modified, as well as the before and after of adding new nodes
12.10 TreeSet
TreeSet is internally a TreeMap. The essence of the add method is to call the put method of the internal TreeMap and put the elements to be added into the TreeMap key. See TreeMap below for the detailed addition method
The main difference from HashSet is that it can be sorted
1. When a TreeSet is created using a parameterless constructor, it is still unordered
public static void main(String[] args) { TreeSet treeSet = new TreeSet(); treeSet.add("Xu Song"); treeSet.add("Zhang Jie"); treeSet.add("Deng Ziqi"); treeSet.add("Lin Junjie"); treeSet.add("Jay Chou"); System.out.println(treeSet); } //Results: [Jay Chou, Zhang Jie, Lin Junjie, Xu Song, Deng Ziqi]
2. Using a constructor provided by TreeSet, you can pass in a comparator (anonymous inner class) and specify the sorting rules
Specific analysis:
When creating a TreeSet, pass in a comparator object: the anonymous internal class comparator, and then assign the comparator object to this. Comparator of the TreeMap attribute at the bottom of the TreeSet
Then call treeSet.add("Xu Song").
public static void main(String[] args) { TreeSet treeSet = new TreeSet(new Comparator() { @Override public int compare(Object o1, Object o2) { return ((String) o2).compareTo((String) o1); } }); treeSet.add("Xu Song"); treeSet.add("Zhang Jie"); treeSet.add("Deng Ziqi"); treeSet.add("Lin Junjie"); treeSet.add("Jay Chou"); System.out.println(treeSet); } //Results: [Deng Ziqi, Xu Song, Lin Junjie, Zhang Jie, Jay Chou] //Sort by character size
12.11 Map interface
- Map is a parallel existence with Collection. It is used to save data with mapping relationship: key value (double column element). Common implementation classes include HashMap, Hashtable and Properties
- The key and value in the Map can be data of any reference type and will be encapsulated in the HashMap$Node object
- The key in the Map cannot be repeated for the same reason as the HashSet. When there is the same key, the latter will replace the former
- The value in the Map can be repeated
- The key and value in the Map can be null, but only one key can be null, and multiple values can be null
- String class is often used as the key of Map
- There is a one-way one-to-one relationship between key and value, that is, the corresponding value can always be found through the specified key
- In the key value diagram of Map archived data, a team of k-v is placed in a Node. Because the Node implements the Emtry interface, it can also be said that a team of k-v is an Emtry
Common methods:
- put: add
- remove: deletes the mapping relationship based on the key
- Get: get value according to key
- size: get the number of elements
- isEmpty: judge whether the number is 0
- Clear: clear
- containsKey: check whether the key exists
Map interface traversal:
First create a Map:
Map map = new HashMap(); map.put("no1","Xu Song"); map.put("no2","Zhang Jie"); map.put("no3","Deng Ziqi"); map.put("no4","Lin Junjie"); map.put("no5","Jay Chou");
The first group: first take out the key of the map object, and then get the value through the get method
1. Use enhanced for loop
Set keySet = map.keySet(); for (Object key : keySet) { System.out.println(key + "-" + map.get(key)); }
2. Use iterators
Iterator iterator = keySet.iterator(); while (iterator.hasNext()) { Object next = iterator.next(); System.out.println(next + "-" + map.get(next)); }
The second group, get the value of the map directly, and then traverse
1. Use iterators
Collection values = map.values(); Iterator iterator = values.iterator(); while (iterator.hasNext()) { Object next = iterator.next(); System.out.println(next); }
2. Use enhanced for loop
for (Object value : values) { System.out.println(value); }
Group 3: get k-v through EntrySet
1. Enhance for loop
Set set = map.entrySet(); for (Object entry : set) { Map.Entry m = (Map.Entry) entry;//Downward transformation System.out.println(m.getKey() + "-" + m.getValue()); }
2. Iterator
Iterator iterator = set.iterator(); while (iterator.hasNext()){ Object entry = iterator.next(); Map.Entry m = (Map.Entry) entry; System.out.println(m.getKey() + "-" + m.getValue()); }
12.12 HashMap
- The key and value in the HashMap can be data of any reference type and will be encapsulated in the HashMap$Node object
- HashMap is the most frequently used implementation class of Map interface
- HashMap does not achieve synchronization, so it is thread unsafe
- The key in HashMap cannot be repeated, and the value in HashMap can be repeated
- HashMap does not guarantee the order of mapping
- The key and value of HashMap can be null, but only one key can be null
- String class is often used as the key of HashMap
- Putting elements with the same key will overwrite the original key value, which is equivalent to modifying
The bottom layer of HashMap is array + linked list + red black tree. (in jdk7.0, the bottom layer is array + linked list)
There is a Node static internal class in HashMap as a Node; There are four variables (hash, key, value, next) in the Node class, and the key value pairs are encapsulated in the Node; There is a Node array table in HashMap. Each element of table is a chain header Node, forming an array + linked list structure
Add element procedure:
- When adding a key value pair, get the hash value first (the calculation of the hash value is related to the hashCode method of the key)
- Judge whether the table is null. If it is null, initialize the table first (add it for the first time)
- Calculate the index value stored in the table according to the obtained hash value
- Check whether the element has been stored in the index position. If it is not directly added
- If yes, judge whether the key of the added element is the same as the key of the current index element (judgment method: compare the hash value of the Node with the hash value of the element to be added, and call the equals method to compare the key of the added key value pair with the key in the Node)
- If the keys are the same, replace the original key value pair
- If the keys are different, traverse the linked list corresponding to the index and compare the keys next to each other
- Until the same key is encountered, replace the original key value pair
- If the traversal of the linked list is different, it will be added to the end of the linked list
Details:
- The table in the new HashMap is null
- The space for adding the element table for the first time is initialized to 16
- After adding elements, if the number of nodes in the table exceeds 0.75 times the table space or the length of the linked list exceeds 8, the capacity will be doubled
- If the number of elements in the linked list exceeds 8 and the table space is greater than or equal to 64, the linked list will be trealized (red black tree)
12.13 LinkedHashMap
LinkedHashMap is a subclass of HashMap. The bottom layer maintains an array + two-way linked list
Refer to the LinkedHashSet above
12.14 Hashtable
- Hashtable is a subclass of Map interface and stores key value pairs
- The underlying maintenance of Hashtable is array + linked list
- The key and value of Hashtable cannot be null, otherwise a null pointer exception will be thrown
- The usage of Hashtable is basically the same as that of HashMap
- Hashtable is thread safe
The underlying maintenance of Hashtable is array + linked list. The array type is an internal class of a member in Hashtable - entry (which implements the Map.Entry interface). The entry has four attributes (hash, key, value, next). The key value pairs are encapsulated in the entry, which is similar to the array + linked list structure when the amount of HashMap data is small.
The process of adding elements is also similar to HashMap, but when forming a linked list, the newly added elements will be placed at the head of the linked list
Detailed discussion
- The table space in the new Hashtable is 11
- After adding elements, if the number of nodes in the table exceeds 0.75 times of the table space, the capacity will be expanded by double + 1
Compare HashMap
edition | Thread safety | efficiency | Allow null keys and null values | |
---|---|---|---|---|
HashMap | 1.2 | unsafe | high | sure |
Hashtable | 1.0 | security | Lower | may not |
12.15 Properties
- The Properties class inherits from the Hashtable class and implements the Map interface. It also uses a key value pair to save data
- The usage features are similar to Hashtable
- Properties can also be used to load data from the xxx.properties file into the properties class object, and read and modify it
- The xxx.properties file is usually used as a configuration file
- Neither key nor value can be empty
Common methods:
- Add: put
- Delete: remove
- Change: put
- Check: get
12.16 selection of set implementation classes
12.17 TreeMap
TreeMap implements the Map interface, and the bottom layer maintains a red black tree
The node of the red black tree is TreeMap$Entry, which implements the Map.Entry interface. The attributes of the node are (key, value, left, right, parent, color)
Add node
When adding a node, there are two situations: comparator and no comparator
// TreeMap without comparator TreeMap treeMap = new TreeMap(); // TreeMap with comparator TreeMap treeMap = new TreeMap(new Comparator() { @Override public int compare(Object o1, Object o2) { return ((String)o1).compareTo((String)o2); } });
- Judge whether the root node is null. If it is null, directly create a new node and put it into the root node (left, right and parent are empty)
- The root node is not empty. Judge whether there is a comparison method
- With comparator
- Use the compare method of the comparator to compare the size of the incoming key and the key of the root node
- If the result is less than 0, continue to compare with the key of the left child
- If the result is greater than 0, continue to compare with the key of the right child
- Until the left (right) child is null, put the new node here
- During the comparison, if the result is equal to 0, replace this node and end the comparison
- No comparator
- Strong conversion of key to Comparable type - k
- k calls the compareTo method with the key of the root node as the parameter
- If the result is less than 0, continue to compare with the key of the left child
- If the result is greater than 0, continue to compare with the key of the right child
- Until the left (right) child is null, put the new node here
- During the comparison, if the result is equal to 0, replace this node and end the comparison
Detailed discussion
- key cannot be null
- When the first element is added as the root node, the compare method of the comparator will also be called. If there is no comparator, the compareTo method will be called instead of the Comparable type
- If there is no comparator, the passed in key must implement the Comparable interface, or a type conversion exception ClassCastException will be thrown
12.18Collections
Collections is a tool class that operates on collections such as Set, List, and Map. Collections provides some column static methods to sort, query and modify collection elements
Common methods:
-
Reverse: reverse list
Collections.reverse(list);
-
shuffle: disorganize the list
Collections.shuffle(list);
-
Sort: sort the list (from small to large)
Collections.sort(list);
-
Sort: custom sort list
Collections.sort(list, new Comparator() { @Override public int compare(Object o1, Object o2) { return (int)o2 - (int)o1; } });
-
Swap: swap two element positions of list
Collections.swap(list, 0, 4);
-
max: the default comparison rule gets the maximum value in the Collecton collection
System.out.println(Collections.max(list));
-
max: Custom comparison rule to get the maximum value in the collection
System.out.println(Collections.max(list, new Comparator() { @Override public int compare(Object o1, Object o2) { return (int) o2 - (int) o1; } }));
-
min: min - Reference max
-
frequency: returns the number of occurrences of the specified element in the specified Collection
int frequency = Collections.frequency(list, 5); System.out.println(frequency);
-
copy: replace the first list.size() values in newList with list
List list = new ArrayList(); list.add(1); list.add(2); list.add(3); list.add(4); list.add(5); List newList = new ArrayList(); for (int i = 0; i < 8; i++) { newList.add(8); } Collections.copy(newList,list); System.out.println(newList); // [1, 2, 3, 4, 5, 8, 8, 8]
-
replaceAll: replace elements
Collections.replaceAll(list,"tom","Tom");//Replace to in the list set with Tom System.out.println(list);
common problem
1, Try to analyze how HashSet and TreeSet realize de duplication respectively
(1)HashSet's de duplication mechanism: hashCode() + equals(), the bottom layer first stores the object and obtains a hash value through operation, and then obtains the corresponding index through the hash value. If it is found that there is no data at the location of the table index, it will be stored directly. If there is data, it will be compared by equals [traversal comparison]. If the comparison is different, it will be added, otherwise it will not be added
(2)TreeSet's de duplication mechanism: if you pass in a Comparator anonymous object, use compare to de duplication. If the method returns 0, it is considered to be the same element / data and will not be added. If you do not pass in a Comparator anonymous object, use the compareTo de duplication of the comparable interface implemented by the object you add
2, Will the following code throw an exception?
TreeSet treeSet = new TreeSet(); treeSet.add(new Person()); class Person{}
An exception will be thrown because the Comparator object is not passed in. When adding data, the underlying layer will forcibly convert the incoming Person object to the compatible type, but the Person does not implement the compatible interface, and a type conversion exception ClassCastException will be thrown
3, What does the following code output?
// Known: the Person class overrides hashCode and equals methods 1 by id and name HashSet set = new HashSet();2 Person p1 = new Person(1001,"AA");3 Person p2 = new Person(1002,"BB");4 set.add(p1);5 set.add(p2);6 p1.name = "CC";7 set.remove(p1);8 System.out.println(set);9 set.add(new Person(1001,"CC"));10 System.out.println(set);11 set.add(new Person(1001,"AA"));12 System.out.println(set);13
Output results:
[Person{num=1002, name='BB'}, Person{num=1001, name='CC'}] [Person{num=1002, name='BB'}, Person{num=1001, name='CC'}, Person{num=1001, name='CC'}] [Person{num=1002, name='BB'}, Person{num=1001, name='CC'}, Person{num=1001, name='CC'}, Person{num=1001, name='AA'}]
Result analysis:
In line 7, change "1001-AA" in the set to "1001-CC"“
Line 8 attempts to delete p1, but p1 has been modified. The hash value obtained in the remove method will change, and the index value found is different from the index value originally added by p1. Deletion fails
Line 10 adds p1 according to the newly matched index position obtained from the new hash value
In line 12, because the id and name are the same as when p1 was added for the first time, you can find the same index, but now the p1 content has changed, so the new Person will be hung behind p1 to form a linked list