1, Overview of Java collection framework
1. Understanding
1) Collection and array are structures that store multiple data, which are referred to as Java containers for short. Note: storage at this time mainly refers to memory level storage, and does not involve persistent storage (. text,. jpg,. avi, in the database).
(2) Array features in storing multiple data:
① Advantages:
1. After the array is initialized, the length is determined.
2. The type of array declaration determines the type of element initialization. Such as String arr [], int arr1 [].
② Disadvantages:
1. After the array is initialized, the length is immutable and is not easy to expand.
2. There are few attributes and methods provided in the array, which is not convenient for adding, deleting, inserting and other operations, and the efficiency is not high. At the same time, the number of storage elements cannot be obtained directly.
3. The data stored in the array is ordered and repeatable. For disordered and unrepeatable requirements, they cannot be met. - --- > The characteristics of stored data are single.
2. API s involved in the collection framework
Java collections can be divided into Collection and Map systems.
(1) Collection interface: single column data, which defines the collection of methods to access a group of objects.
List interface: stores ordered and repeatable data. It is called a "dynamic" array. They mainly include Vector, ArrayList and LinkedList
Set interface: stores unordered and non repeatable data. A collection similar to high school mathematics. They mainly include: HashSet, LinkedHashSet and TreeSet
(2) Map interface: double column data, which stores a set with a mapping relationship "key value pair". Functions similar to high school mathematics, mainly include Hashtable, HashMap, Properties, LinkedHashMap and TreeMap
2, Methods in the Collection interface
(1) add(Object obj): Will element obj Add to current collection (2) addAll(Collection coll): take coll The elements in the collection are added to the current collection. (3)size(): Get the number of valid elements (4)clear(): Empty collection (5)isEmpty(): Is it an empty collection (6)contains(Object obj): adopt equals Method to determine whether the current collection contains obj. (7)containsAll(Collection coll1): Judge formal parameters coll1 Whether all elements in exist in the current collection. (8)remove(Object obj): Remove from current collection obj Element. (9)removeAll(Collection coll1): Remove from current collection coll1 All elements in the. (equivalent to taking the difference set of two sets) (10)retainAll(Collection coll1): Get current collection and coll1 The intersection of sets and returns it to the current set. (11)equals(Object obj): Judge whether the elements of the current set and the formal parameter set are the same. (12)hashCode(): Returns the hash value of the current object. (13)toArray(): Convert a collection to an array. (14)iterator(): Returns an iterator object for collection traversal.
demo
package com.atguigu.java; import org.junit.Test; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; /** * Collection Testing of methods declared in interfaces * * Conclusion: * When adding data obj to the object of the implementation class of the Collection interface, the class of obj is required to override equals() * */ public class CollectionTest { @Test public void test1(){ Collection coll = new ArrayList(); coll.add(123); coll.add(456); // Person p = new Person("Jerry",20); // coll.add(p); coll.add(new Person("Jerry",20)); coll.add(new String("Tom")); coll.add(false); //1.contains(Object obj): judge whether the current set contains obj //When judging, we will call equals() of the class where the obj object is located. boolean contains = coll.contains(123); System.out.println(contains); System.out.println(coll.contains(new String("Tom"))); // System.out.println(coll.contains(p));//true System.out.println(coll.contains(new Person("Jerry",20)));//false -->true //2.containsAll(Collection coll1): judge whether all elements in the formal parameter coll1 exist in the current collection. Collection coll1 = Arrays.asList(123,4567); System.out.println(coll.containsAll(coll1)); } @Test public void test2(){ //3.remove(Object obj): removes obj elements from the current collection. Collection coll = new ArrayList(); coll.add(123); coll.add(456); coll.add(new Person("Jerry",20)); coll.add(new String("Tom")); coll.add(false); coll.remove(1234); System.out.println(coll); coll.remove(new Person("Jerry",20)); System.out.println(coll); //4. removeAll(Collection coll1): subtraction: removes all elements in coll1 from the current collection. Collection coll1 = Arrays.asList(123,456); coll.removeAll(coll1); System.out.println(coll); } @Test public void test3(){ Collection coll = new ArrayList(); coll.add(123); coll.add(456); coll.add(new Person("Jerry",20)); coll.add(new String("Tom")); coll.add(false); //5. Retain all (collection coll1): intersection: get the intersection of the current set and coll1 set and return it to the current set // Collection coll1 = Arrays.asList(123,456,789); // coll.retainAll(coll1); // System.out.println(coll); //6.equals(Object obj): to return true, the elements of the current set and the parameter set must be the same. Collection coll1 = new ArrayList(); coll1.add(456); coll1.add(123); coll1.add(new Person("Jerry",20)); coll1.add(new String("Tom")); coll1.add(false); System.out.println(coll.equals(coll1)); } @Test public void test4(){ Collection coll = new ArrayList(); coll.add(123); coll.add(456); coll.add(new Person("Jerry",20)); coll.add(new String("Tom")); coll.add(false); //7.hashCode(): returns the hash value of the current object System.out.println(coll.hashCode()); //8. Set -- > array: toArray() Object[] arr = coll.toArray(); for(int i = 0;i < arr.length;i++){ System.out.println(arr[i]); } //Extension: array -- > collection: call the static method asList() of the Arrays class List<String> list = Arrays.asList(new String[]{"AA", "BB", "CC"}); System.out.println(list); List arr1 = Arrays.asList(new int[]{123, 456}); System.out.println(arr1.size());//1 List arr2 = Arrays.asList(new Integer[]{123, 456}); System.out.println(arr2.size());//2 //9.iterator(): returns an instance of the iterator interface for traversing collection elements. Put it in iteratortest Testing in Java } }
Array - > collection: call the static method asList() of the Arrays class
System.out.println("===array --->aggregate:call Arrays Class asList()==="); List<String> list = Arrays.asList(new String[]{"AA","bb","CC"}); System.out.println(list); List arr1 = Arrays.asList(new int[]{123, 456}); //If it is set to int, the basic data will be considered as a System.out.println(arr1.size());//1 List arr2 = Arrays.asList(new Integer[]{123, 456});//There are 2 wrapper classes System.out.println(arr2.size());//2
3, Iterator iterator interface
1. Understanding
(1) The Iterator object is called an Iterator (a kind of design pattern) and is mainly used to traverse the elements in the Collection.
(2) GOF defines the iterator pattern as providing a way to access each element in a container object without exposing the internal details of the object. The iterator pattern is born for containers. Similar to "conductor on the bus", "stewardess on the train" and "stewardess".
(3) Every time a collection object calls the iterator() method, it gets a new iterator object, and the default cursor is before the first element of the collection.
2. Main methods
(1) hasNext(): judge whether there is another element.
(2) next(): move the pointer down to return the elements at the collection position after moving down.
(3)remove():
Iterator can delete the elements of the collection, but it is the remove method of the iterator object during traversal, not the remove method of the collection object.
If next() has not been called or the remove method has been called since the next method was called last time, then calling remove will report IllegalStateException.
demo
public static void main(String[] args) { Collection c1 = new ArrayList(); c1.add(123); c1.add(456); Iterator iterator = c1.iterator(); // hasNext() determines whether there is a next element while (iterator.hasNext()) { // The next() pointer moves down and returns the elements at the collection position after moving down. Object next = iterator.next(); System.out.println(next); } }
When Iterator traverses, you can call the remove() method to remove this element:
public static void main(String[] args) { Collection c1 = new ArrayList(); c1.add("123"); c1.add("456"); Iterator iterator = c1.iterator(); // hasNext() determines whether there is a next element while (iterator.hasNext()) { // The next() pointer moves down and returns the elements at the collection position after moving down. Object obj = iterator.next(); //iterator.remove() // When Iterator traverses, you can call the remove() method to remove this element: if ("456".equals(obj)) { iterator.remove(); } } }
After calling it You must call it before the next () method Hasnext(). If it is not called and the next record is invalid, call it directly Next() will throw NoSuchElementException
Person class
package com.atguigu.java; import java.util.Objects; public class Person { private String name; private int age; public Person() { } public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } @Override public boolean equals(Object o) { System.out.println("Person equals()...."); if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; return age == person.age && Objects.equals(name, person.name); } @Override public int hashCode() { return Objects.hash(name, age); } }
package com.atguigu.java; import org.junit.Test; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; /** * The traversal operation of collection elements uses the Iterator iterator interface * 1.Internal methods: hasNext() and next() * 2.Every time the collection object calls the iterator() method, it gets a new iterator object, * The default cursors are before the first element of the collection. * 3.Remove () is defined internally, which can delete the elements in the collection during traversal. This method is different from the direct call to remove() from a collection * */ public class IteratorTest { @Test public void test1(){ Collection coll = new ArrayList(); coll.add(123); coll.add(456); coll.add(new Person("Jerry",20)); coll.add(new String("Tom")); coll.add(false); Iterator iterator = coll.iterator(); //Mode 1: // System.out.println(iterator.next()); // System.out.println(iterator.next()); // System.out.println(iterator.next()); // System.out.println(iterator.next()); // System.out.println(iterator.next()); // //Exception: NoSuchElementException // System.out.println(iterator.next()); //Method 2: not recommended // for(int i = 0;i < coll.size();i++){ // System.out.println(iterator.next()); // } //Method 3: recommendation hasNext():Determine if there is a next element while(iterator.hasNext()){ //next(): ① move the pointer down ② return the elements at the collection position after moving down System.out.println(iterator.next()); } } @Test public void test2(){ Collection coll = new ArrayList(); coll.add(123); coll.add(456); coll.add(new Person("Jerry",20)); coll.add(new String("Tom")); coll.add(false); //Error mode 1: // Iterator iterator = coll.iterator(); // while((iterator.next()) != null){ // System.out.println(iterator.next()); // } //Error mode 2: //Every time a collection object calls the iterator() method, it gets a new iterator object, and the default cursor is before the first element of the collection. while (coll.iterator().hasNext()){ System.out.println(coll.iterator().next()); } } //Test remove() in Iterator //If next() has not been called or the remove method has been called since the next method was last called, // Calling remove again will report IllegalStateException. @Test public void test3(){ Collection coll = new ArrayList(); coll.add(123); coll.add(456); coll.add(new Person("Jerry",20)); coll.add(new String("Tom")); coll.add(false); //Delete "Tom" in the collection Iterator iterator = coll.iterator(); while (iterator.hasNext()){ // iterator.remove(); Object obj = iterator.next(); if("Tom".equals(obj)){ iterator.remove(); // iterator.remove(); } } //Traversal set iterator = coll.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); } } }
3. for each
New method in JDK 5: used to traverse arrays and collections
The iterator is still called internally
for(Element type element temporary name: array\Collection name) { } for(Object obj : objs){//Using obj to call elements}
demo
public static void main(String[] args) { Collection c1 = new ArrayList(); c1.add("123"); c1.add("456"); // For (collection element type local variable: collection object) // The Iterator iterator is still called internally. for (Object obj : c1) { System.out.println(obj); } // Traversal array String[] strings = {"Zhang San", "Li Si"}; for (String str : strings) { System.out.println(str); } }
4, Collection sub interface 1: List interface
1. General
(1) In view of the limitation that arrays are used to store data in Java, we usually use List instead of arrays.
(2) The elements in the List collection class are ordered and repeatable, and each element in the collection has its corresponding sequential index.
(3) The elements in the List container correspond to an integer serial number, recording their position in the container. The elements in the container can be accessed according to the serial number.
(4) The implementation classes of List interface in JDK API are ArrayList, LinkedList and Vector.
2. Common implementation classes of list interface
(1) ArrayList: as the main implementation class of the List interface; the thread is unsafe and efficient; the underlying layer uses object [] elementdata storage;
(2) LinkedList: for frequent insert and delete operations, the efficiency of using this type is higher than that of ArrayList; the bottom layer uses two-way linked list storage;
LinkedList list = new LindedList(); Node first//First element Node last//Last element //When declared, the linked list has two properties with null values //Structure of saved data: [previous Node address + saved value + next Node address] private static class Node<E>{ E item; Node<E> next; Node<E> prev; Node(Node<E> prev,E element, Node<E> next){ this.item = element; this next = next; this.prev = prev; } } //add: encapsulate the data to the Node and create the Node object //For the first time, assign this Node to first and last //If you add it again, it will be added at the last Node
(3) Vector: as an ancient implementation class of the List interface; thread safe and inefficient; the underlying layer uses object [] elementdata storage;
Similarities and differences among ArrayList, LinkedList and Vector:
Same: the three classes implement the List interface, and the characteristics of storing data are the same: orderly and repeatable data.
Different:
3. Interface method
In addition to the methods inherited from the Collection collection, the List Collection adds some methods to operate the Collection elements according to the index.
① void add(int index, Object ele):stay index Position insertion ele Element. ② boolean addAll(int index, Collection eles):from index Position start will eles Add all elements in. ③ Object get(int index):Get specified index The element of the location. ④ int indexOf(Object obj):return obj The location of the first occurrence in the collection. ⑤ int lastIndexOf(Object obj):return obj The last occurrence in the current collection. ⑥ Object remove(int index):Remove assignment index And returns this element. ⑦ Object set(int index, Object ele):Setting assignment index The element of the location is ele. ⑧ List subList(int fromIndex, int toIndex):Return from fromIndex reach toIndex A subset of locations.
demo
package com.atguigu.java; import org.junit.Test; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; /** * 1. List Interface framework * * |----Collection Interface: a single column collection used to store objects one by one * |----List Interface: store ordered and repeatable data. -- > "Dynamic" array, replacing the original array * |----ArrayList: As the main implementation class of List interface; Unsafe thread and high efficiency; The underlying layer uses Object[] elementData storage * |----LinkedList: For frequent insert and delete operations, the efficiency of using this type is higher than that of ArrayList; The bottom layer uses two-way linked list storage * |----Vector: As an implementation class of the List interface; Thread safety and low efficiency; The underlying layer uses Object[] elementData storage * * * 2. ArrayList Source code analysis: * 2.1 jdk 7 Case * ArrayList list = new ArrayList();//The bottom layer creates an Object [] array elementData with a length of 10 * list.add(123);//elementData[0] = new Integer(123); * ... * list.add(11);//If the capacity of the underlying elementData array is insufficient due to this addition, the capacity will be expanded. * By default, the capacity expansion is 1.5 times of the original capacity, and the data in the original array needs to be copied to the new array. * * Conclusion: it is recommended to use a constructor with parameters in development: ArrayList = new ArrayList (int capacity) * * 2.2 jdk 8 Changes in ArrayList in: * ArrayList list = new ArrayList();//The underlying Object[] elementData is initialized to {} No array of length 10 was created * * list.add(123);//The first time add() is called, the underlying layer creates an array of length 10 and adds data 123 to elementData[0] * ... * The subsequent addition and expansion operations are the same as jdk 7. * 2.3 Summary: the creation of the ArrayList object in jdk7 is similar to the starving Han style of the singleton, while the ArrayList object in jdk8 * The creation of is similar to the lazy type of singleton, which delays the creation of array and saves memory. * * 3. LinkedList Source code analysis: * LinkedList list = new LinkedList(); The first and last attributes of Node type are declared internally, and the default value is null * list.add(123);//Encapsulate 123 into Node and create Node object. * * Node is defined as a two-way linked list that embodies LinkedList * private static class Node<E> { E item; Node<E> next; Node<E> prev; Node(Node<E> prev, E element, Node<E> next) { this.item = element; this.next = next; this.prev = prev; } } * * 4. Vector Source code analysis: when creating objects through the Vector() constructor in jdk7 and jdk8, the underlying layer creates an array with a length of 10. * In terms of capacity expansion, the default capacity expansion is twice the length of the original array. * * Interview question: what are the similarities and differences among ArrayList, LinkedList and Vector? * Same: the three classes implement the List interface, and the characteristics of storing data are the same: storing orderly and repeatable data * Difference: see above * * * * 5. List Common methods in interfaces * * @author shkstart * @create 2019 11:39 am */ public class ListTest { /* void add(int index, Object ele):Insert the ele element at the index position boolean addAll(int index, Collection eles):Add all elements in eles from the index position Object get(int index):Gets the element at the specified index location int indexOf(Object obj):Returns the position where obj first appears in the collection int lastIndexOf(Object obj):Returns the last occurrence of obj in the current collection Object remove(int index):Removes the element at the specified index location and returns this element Object set(int index, Object ele):Set the element at the specified index location to ele List subList(int fromIndex, int toIndex):Returns a subset from fromIndex to toIndex Summary: common methods Add: add(Object obj) Delete: remove(int index) / remove(Object obj) Change: set(int index, Object ele) Query: get(int index) Insert: add(int index, Object ele) Length: size() Traversal: ① Iterator iterator mode ② Enhanced for loop ③ Ordinary cycle */ @Test public void test3(){ ArrayList list = new ArrayList(); list.add(123); list.add(456); list.add("AA"); //Mode 1: Iterator iterator mode Iterator iterator = list.iterator(); while(iterator.hasNext()){ System.out.println(iterator.next()); } System.out.println("***************"); //Mode 2: enhanced for loop for(Object obj : list){ System.out.println(obj); } System.out.println("***************"); //Mode 3: normal for loop for(int i = 0;i < list.size();i++){ System.out.println(list.get(i)); } } @Test public void test2(){ ArrayList list = new ArrayList(); list.add(123); list.add(456); list.add("AA"); list.add(new Person("Tom",12)); list.add(456); //int indexOf(Object obj): returns the position where obj first appears in the collection. If it does not exist, - 1 int index = list.indexOf(4567); System.out.println(index); //int lastIndexOf(Object obj): returns the last occurrence of obj in the current collection. If it does not exist, - 1 System.out.println(list.lastIndexOf(456)); //Object remove(int index): removes the element at the specified index position and returns this element Object obj = list.remove(0); System.out.println(obj); System.out.println(list); //Object set(int index, Object ele): sets the element at the specified index position to ele list.set(1,"CC"); System.out.println(list); //List subList(int fromIndex, int toIndex): returns a subset of the left closed right open interval from fromIndex to toIndex List subList = list.subList(2, 4); System.out.println(subList); System.out.println(list); } @Test public void test1(){ ArrayList list = new ArrayList(); list.add(123); list.add(456); list.add("AA"); list.add(new Person("Tom",12)); list.add(456); System.out.println(list); //void add(int index, Object ele): inserts an ele element at the index position list.add(1,"BB"); System.out.println(list); //boolean addAll(int index, Collection eles): add all elements in eles from the index position List list1 = Arrays.asList(1, 2, 3); list.addAll(list1); // list.add(list1); System.out.println(list.size());//9 //Object get(int index): gets the element at the specified index position System.out.println(list.get(0)); } }
5, Collection sub interface 2: Set
1. General
(1) set interface is a sub interface of Collection. set interface does not provide additional methods (different from list).
(2) The Set set cannot contain the same elements. If you try to add two identical elements to the same Set set, the add operation fails.
(3) Set determines whether two objects are the same, not using the = = operator, but according to the equals() method.
(4) Set stores unordered and non repeatable data.
- ① Disorder does not represent randomness. The stored data is not added in the order of array index in the underlying array, but determined according to the hash value of the data.
- ② Non repeatability: ensure that when the added element is judged according to equals(), it cannot return true. That is, only one element can be added for the same element.
(5) The specific process of adding elements (taking HashSet as an example):
- When adding element a to the HashSet, first call the hashCode() method of the class where element a is located to calculate the hash value of element A. then, calculate the position stored in the underlying array of the HashSet through some method (determined by some hash function), and judge whether there are elements in this position of the array:
- 1) If there are no other elements in this position, element a is added successfully;
- 2) If there are other elements b (or multiple elements in the form of linked list) at this position, compare the hash values of a and b:
① If the hash values are different, element a is added successfully;
② If the hash values are the same, you need to call equals() of the class where element a is located
Method: equals() returns true, element a failed to be added; equals() returns false, element a was added successfully.
Note: in the case of successful addition, element a and the data already existing at the specified index position are stored in the form of linked list. jdk 7: put element a into the array and point to the original element; jdk 8: the original element is in the array and points to element a. (seven up and eight down)
(6) HashSet sets the criteria for judging the equality of two elements: the two objects are equal through hashCode() method, and the return values of the equals() method of the two objects are also equal.
(7) For objects stored in the set container, the corresponding classes must override the equals() and hashCode(Object obj) methods to implement the object equality rule. That is: "equal objects must have equal hash codes". Otherwise, the hashCode method in the object will be called to randomly obtain the hash value, which may cause two identical objects to obtain different hash values, resulting in duplicate objects in the set.
2. Common implementation classes of set interface
(1) HashSet: as the main implementation class of the Set interface; thread unsafe; null values can be stored. The bottom layer is array + linked list.
(2) LinkedHashSet: as a subclass of HashSet; when traversing its internal data, it can be traversed in the order of addition; while adding data, each data also maintains two references to record the data before and after this data. For frequent traversal operations, LinkedHashSet is more efficient than HashSet.
(3) TreeSet: you can sort according to the specified properties of the added object. The data added to TreeSet must be objects of the same class. There are two sorting methods:
① Natural sorting: TreeSet will call the compareTo(Object obj) method of collection elements to compare the size relationship between elements, and then arrange the collection elements in ascending order (by default). The criterion for comparing two objects is to return 0 for compareTo() instead of equals().
② Custom sorting: implemented through the Comparator interface. The criterion for comparing whether two objects are the same returns 0 for compare() instead of equals().
2.1. HashSet: the underlying layer uses the key of HashMap to store data
- a: HashSet is a typical implementation of the Set interface. Most users use this implementation class.
- b: HashSet stores the elements in the set according to the Hash algorithm, so it has good performance of access, search and deletion.
- c: HashSet features:
- 1.hashSet does not guarantee that elements are ordered. (determine the storage location according to the hash calculation).
- 2.HashSet is thread unsafe.
- 3.HashSet collection can store null values, but there can only be one null value.
- 4. There cannot be duplicate elements / objects. (what does it really mean) (for custom objects, you need to override equals and hashcode)
- d: HashSet set, the criteria for judging the equality of two elements:
The two objects are compared to be equal through the HashCode() method, and the return values of the equals() method of the two objects are also equal. - e: For objects stored in the Set container:
- The corresponding class must override the equals() and HashCode(Object obj) methods to implement the object equality principle.
- f: Basic principles for rewriting hashCode():
- 1. Rewrite the hashCode() and equals() methods to maintain consistency as much as possible. That is, equal objects must have equal hash codes and equal () values.
- 2. When the program is running, the same object calls the hashCode() method multiple times, and the return values are the same.
- 3. When the equals() method of two objects returns true, the return value of the hashCode() method of the two objects should also be equal. (but hashcodes are equal, and equals() is not necessarily equal)
- 4. The properties used for the equals method comparison in the object should be used to calculate the hashCode value.
- g: Hash Set capacity expansion mechanism and conversion to red black tree mechanism:
- 1. The bottom layer of HashSet is HashMap. When it is added for the first time, the table array is expanded to 16, and the critical value is 16 * 0.75 = 12. (both the elements in the table array and the elements in the linked list / red black tree are counted)
- 2. If the critical value 12 is used in the array, the capacity will be expanded to 16 * 2 = 32, and the new critical value is 32 * 0.75 = 24; and so on.
- 3. In Java 8, if the number of elements in a linked list reaches 8 and the size of the table > = 64, it will be trealized (converted into a red black tree). Otherwise, the array expansion mechanism is still used.
To add an element to a HashSet:
- When an element is stored in the HashSet set, the HashSet will call the hashCode() method of the object to get the hashCode value of the object, and then determine the storage location of the object in the underlying array of the HashSet through a hash function according to the hashCode value. (this hash function will calculate the subscript in the array with the length of the underlying array, and this hash function calculation also ensures that the elements can be stored evenly as much as possible. The more the hash distribution is, the better the hash function is designed.)
if the hashCode() values of the two elements are equal, the equals method will be called again. If the equals method results in
Is true, adding failed; If it is false, the element will be saved, but there are already elements in the position of the array,
Then the link will continue through the linked list.
if the equals() method of two elements returns true, but their hashCode() return values do not match
Etc., the hashSet will store them in different locations, but they can still be added successfully.
Basic principles for overriding hashCode() methods
when the program is running, the same object calls the hashCode() method multiple times and should return the same value.
when the equals() method of two objects returns true, the return value of the hashCode() method of the two objects should also be equal.
the fields in the object used for the equals() method comparison should be used to calculate the hashCode value.
Basic principles for overriding the equals() method
- Taking the custom Customer class as an example, when do I need to override equals()?
when a class has its own unique concept of "logical equality", when rewriting equals(), always rewrite hashCode(). According to the equals method of a class (after rewriting), two distinct instances may be logically equal, but according to the Object.hashCode() method, they are only two objects.
therefore, it violates "equal objects must have equal hash codes".
conclusion: when copying the equals method, it is generally necessary to copy the hashCode method at the same time. Generally, the properties of the objects involved in the calculation of hashCode should also be involved in the calculation of equals().
demo
package com.atguigu.java1; import org.junit.Test; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.Set; /** * 1. Set Interface framework: * * |----Collection Interface: a single column collection used to store objects one by one * |----Set Interface: store unordered and unrepeatable data -- > High School "set" * |----HashSet: As the main implementation class of Set interface; Thread unsafe; null values can be stored * |----LinkedHashSet: As a subclass of HashSet; When traversing its internal data, it can be traversed in the order of addition * For frequent traversal operations, LinkedHashSet is more efficient than HashSet * |----TreeSet: You can sort according to the specified attributes of the added object. * * * 1. Set There are no new methods defined in the interface, but all the methods declared in the Collection are used. * * 2. Requirement: the class of data added to set (mainly HashSet and LinkedHashSet) must override hashCode() and equals() * Requirement: the rewritten hashCode() and equals() should be consistent as much as possible: equal objects must have equal hash codes * Tip for rewriting two methods: the fields in the object used for the equals() method comparison should be used to calculate the hashCode value. * */ public class SetTest { /* 1, Set: stores unordered and non repeatable data Take HashSet as an example: 1. Disorder: not equal to randomness. The stored data is not added in the order of array index in the underlying array, but determined according to the hash value of the data. 2. Non repeatability: ensure that when the added element is judged according to equals(), it cannot return true That is, only one element can be added to the same element. 2, Process of adding elements: take HashSet as an example: We add element a to the HashSet. First, we call the hashCode() method of the class where element a is located to calculate the hash value of element a, This hash value then calculates the storage position (i.e. index position) in the underlying array of HashSet through some algorithm to judge Whether the array already has elements at this position: If there are no other elements at this location, element a is added successfully. ---- > Case 1 If there are other elements b (or multiple elements in the form of a linked list) at this position, compare the hash values of element a and element b: If the hash values are different, element a is added successfully. ---- > Case 2 If the hash values are the same, you need to call the equals() method of the class where element a is located: equals()Return true, element a addition failed equals()If false is returned, element a is added successfully. ---- > Case 2 For cases 2 and 3 where the addition is successful, element a and the data already existing at the specified index position are stored in a linked list. jdk 7 :Element a is placed in the array and points to the original element. jdk 8 :The original element is in the array and points to element a Conclusion: seven up and eight down HashSet Bottom layer: array + linked list structure. */ @Test public void test1(){ Set set = new HashSet(); set.add(456); set.add(123); set.add(123); set.add("AA"); set.add("CC"); set.add(new User("Tom",12)); set.add(new User("Tom",12)); set.add(129); Iterator iterator = set.iterator(); while(iterator.hasNext()){ System.out.println(iterator.next()); } } //Use of LinkedHashSet //LinkedHashSet is a subclass of HashSet. While adding data, each data also maintains two references, recording the previous one of this data //Data and the latter data. //Advantages: LinkedHashSet is more efficient than HashSet for frequent traversal operations @Test public void test2(){ Set set = new LinkedHashSet(); set.add(456); set.add(123); set.add(123); set.add("AA"); set.add("CC"); set.add(new User("Tom",12)); set.add(new User("Tom",12)); set.add(129); Iterator iterator = set.iterator(); while(iterator.hasNext()){ System.out.println(iterator.next()); } } }
2.2,LinkedHashSet
a: LinkedHashSet features:
- 1. It is a subclass of HashSet. The underlying layer uses LinkedHashMap to maintain an array + two-way linked list to store data.
- 2.LinkedHashSet determines the storage location according to the hashCode() value of the element. At the same time, use the linked list to maintain the order of elements, which makes the elements appear to be stored in insertion order.
- 3. Duplicate set elements are not allowed. For frequent traversal, the operation efficiency is high.
c: LinkedHashSet performance and benefits:
- The insertion performance is slightly lower than that of HashSet, because the head and tail points of this element in the linked list are maintained during insertion.
- However, LinkedHashSet has good performance when iteratively accessing all elements in the Set.
b: During add() operation:
- 1. LinkedHashSet is similar to hashMap storage. The storage location of an element is determined according to the hashCode value of the element.
- 2. However, while adding data, each data also maintains two references to record the previous data and the latter data,
- 3. That is to use a two-way linked list to maintain the storage order of elements, which makes elements appear to be protected in insertion order. It seems to be stored orderly.
d: LinkedHashSet storage structure display:
- Similar to hashSet storage, it only has a two-way linked list structure. To record the addition order.
demo
public void test2(){ Set set = new LinkedHashSet(); set.add(456); set.add(123); set.add(123); set.add("AA"); set.add("CC"); set.add(new User("Tom",12)); set.add(new User("Tom",12)); set.add(129); Iterator iterator = set.iterator(); while(iterator.hasNext()){ System.out.println(iterator.next()); } }
2.3,TreeSet
-
1: TreeSet is the implementation class of SortedSet interface. TreeSet can ensure that the internal elements of the collection are sorted according to the specified conditions.
-
2: Two objects have the same criteria:
- 1. If it is compareTo / compare, it returns 0 instead of equals(). The internal data structure is a red black tree. It is sorted by comparing the size of elements.
-
3: The underlying TreeSet uses a red black tree structure to store data.
- Features: sort the results according to the element comparison size, and select the storage location. The internal storage is orderly, and the query speed is faster than List.
- Features: sort the results according to the element comparison size, and select the storage location. The internal storage is orderly, and the query speed is faster than List.
4:TreeSet has two sorting methods: (the same standard for two objects is that compareTo / compare returns 0, which is no longer equal())
- 1. Natural sorting: (default)
- 2. Custom sorting: (specify the sorting order when creating TreeSet)
demo
User
package com.atguigu.java1; public class User implements Comparable{ private String name; private int age; public User() { } public User(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + '}'; } @Override public boolean equals(Object o) { System.out.println("User equals()...."); if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; User user = (User) o; if (age != user.age) return false; return name != null ? name.equals(user.name) : user.name == null; } @Override public int hashCode() { //return name.hashCode() + age; int result = name != null ? name.hashCode() : 0; result = 31 * result + age; return result; } //In descending order of name and age @Override public int compareTo(Object o) { if(o instanceof User){ User user = (User)o; // return -this.name.compareTo(user.name); int compare = -this.name.compareTo(user.name); if(compare != 0){ return compare; }else{ return Integer.compare(this.age,user.age); } }else{ throw new RuntimeException("The types entered do not match"); } } }
package com.atguigu.java1; import org.junit.Test; import java.util.Comparator; import java.util.Iterator; import java.util.TreeSet; public class TreeSetTest { /* 1.The data added to TreeSet must be objects of the same class. 2.There are two sorting methods: natural sorting (implementing Comparable interface) and custom sorting (Comparator) 3.In natural sorting, the criterion for comparing whether two objects are the same is: compareTo() returns 0 No longer equals() 4.In custom sorting, the criterion for comparing whether two objects are the same is: compare() returns 0 No longer equals() */ @Test public void test1(){ TreeSet set = new TreeSet(); //Failed: cannot add objects of different classes // set.add(123); // set.add(456); // set.add("AA"); // set.add(new User("Tom",12)); //Example 1: // set.add(34); // set.add(-34); // set.add(43); // set.add(11); // set.add(8); //Example 2: set.add(new User("Tom",12)); set.add(new User("Jerry",32)); set.add(new User("Jim",2)); set.add(new User("Mike",65)); set.add(new User("Jack",33)); set.add(new User("Jack",56)); Iterator iterator = set.iterator(); while(iterator.hasNext()){ System.out.println(iterator.next()); } } @Test public void test2(){ Comparator com = new Comparator() { //Arranged from small to large according to age @Override public int compare(Object o1, Object o2) { if(o1 instanceof User && o2 instanceof User){ User u1 = (User)o1; User u2 = (User)o2; return Integer.compare(u1.getAge(),u2.getAge()); }else{ throw new RuntimeException("The data types entered do not match"); } } }; TreeSet set = new TreeSet(com); set.add(new User("Tom",12)); set.add(new User("Jerry",32)); set.add(new User("Jim",2)); set.add(new User("Mike",65)); set.add(new User("Mary",33)); set.add(new User("Jack",33)); set.add(new User("Jack",56)); Iterator iterator = set.iterator(); while(iterator.hasNext()){ System.out.println(iterator.next()); } } }
2.4 what are the similarities and differences between HashSet, LinkedHashSet and TreeSet?
6, Map interface
1. General
(1) Map and Collection exist side by side. Used to save data with mapping relationship: key value. Similar to high school function: y=f(x) (Y → value, X → key)
(2) Understanding of Map structure:
- ① Keys in Map: unordered and non repeatable. Use Set to store all keys. (the class where the key is located should override equals () and
hashCode() method. (take HashMap as an example) - ② Value in Map: unordered and repeatable. Use Collection to store all values. (the class where value is located should be overridden
equals (). A key value pair: key value constitutes an Entry object. - ③ Entries in Map: unordered and non repeatable. Set is used to store all entries.
static class Node<K,V> implements Map.Entry<K,V> { final int hash; final K key; V value; Node<K,V> next; Node(int hash, K key, V value, Node<K,V> next) { this.hash = hash; this.key = key; this.value = value; this.next = next; }
2. Common implementation classes of map interface
1) HashMap: as the main implementation class of Map; Unsafe thread and high efficiency; Store null key and value.
bottom:
- Array + linked list (jdk 7 and before)
- Array + linked list + red black tree (jdk 8)
(2) LinkedHashMap: ensure that when traversing map elements, traversal can be realized in the order of addition. Reason: a pair of pointers are added on the basis of the original HashMap underlying structure to point to the previous and subsequent elements. For frequent traversal operations, this kind of execution efficiency is higher than that of HashMap.
(3) TreeMap: ensure to sort according to the added key value pairs to realize sorting traversal. At this time, consider the natural sorting or customized sorting of keys. The red black tree is used at the bottom.
(4) Hashtable: as an ancient implementation class, it is thread safe and inefficient. It cannot store null key s and value s.
(5) Properties: commonly used to handle configuration files. Both key and value are String types.
- 1.Properties class is HashTable
- 2. It is commonly used to process configuration files. Both key and value are String types.
- 3. Recommended usage: properties setProperty(“key”, “value”); And properties getProperty(“key”);
- 4. Read the Properties configuration file.
public static void main(String[] args) throws IOException { FileInputStream fis = null; try { Properties properties = new Properties(); fis = new FileInputStream(new File("/Users/zhangsan/workspace/renren_vue/mall-test/my_test_01/src/main/resources/application.properties")); properties.load(fis); Iterator<Map.Entry<Object, Object>> iterator = properties.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry<Object, Object> next = iterator.next(); System.out.println(next.getKey()); System.out.println(next.getValue()); } } catch (Exception e) { e.printStackTrace(); } finally { if (fis != null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } }
(6) Concurrent hashMap: a thread safe hashMap, but its efficiency is higher than that of hashTable. It uses the segmentation lock mechanism internally.
3. Underlying implementation principle of HashMap
Relevant meanings:
DEFAULT_INITIAL_CAPACITY: HashMap Default capacity of, 16; DEFAULT_LOAD_FACTOR: HashMap Default load factor for: 0.75; threshold: Critical value of capacity expansion,=capacity × Loading factor: 16 * 0.75=12; TREEIFY_THRESHOLD:Bucket If the length of the middle linked list is greater than the default value, it will be converted into a red black tree: 8; MIN_TREEIFY_CAPACITY: In the bucket Node Smallest when treelized hash Table capacity: 64
JDK 1.7: array + linked list:
JDK7 Specify capacity constructor creation HashMap,The actual capacity is not necessarily user specified( Capability (related) Load factor: 0.75-Capacity expansion trigger Critical value - capacity * Loading factor Actually created a one-dimensional array Entry[ ] put method →handle null,calculation k Hash value of (get the required value after processing) → (And operation) get the storage position of the element in the array → Take out the data at the position and judge whether it is empty →Traversal comparison hash value →Determine whether the reference points to the same key →call equals → Judge whether to trigger capacity expansion - it exceeds the critical value and the current storage location is not empty Trigger capacity expansion: re store the existing elements into the new array - the element position may change //Class to store data Static class Entry<k,v> implements Map.Entry<k,v>{ final k key; Entry<k,v> next; int hash; Entry(int h,k k ,Entry<k,v> n){ value = v; next = n; key = k; hash = h; } } //When creating a new Entry, place the original Entry on the Next pointer and add the new Entry to the array position (stored in reverse order)
HashMap map=new HashMap(); after instantiation, the bottom layer creates a one-dimensional array entry [] table with a length of 16
map.put(key1,value1): put key1 and value1 into the above array
① First, call hashCode () of the class where key1 is located to calculate the hash value of key1. After the hash value is calculated by some algorithm, the storage location in the Entry array is obtained:
② If the data in this location is empty, key1-value1 is added successfully; If the data in this location is not empty (which means that there are one or more data in this location (in the form of linked list)), compare the hash values of key1 and one or more existing data:
③ If the hash value of key1 is different from the hash value of existing data, key1-value1 is added successfully; If the hash value of key1 is the same as that of an existing data (key2-value2), continue the comparison:
④ Call equals() of the class where key1 is located: if equals() returns false, key1-value1 is added successfully; if equals() returns true, use value1 to replace value2.
Supplement: ① when the addition is successful, key1-value1 and the original data are stored in a linked list. ② In the process of continuous addition, the problem of capacity expansion will be involved. When the critical value of 12 is exceeded (and the location to be stored is not empty), the default capacity expansion method is to double the original capacity and copy the original data.
JDK1.8: Array + linked list + red black tree: (time complexity: linked list o(n); Red black tree o(logN)
JDK8 When declared, do not create an array and give it to the current Hashmap Load factor assignment //Node class for storing data static class Node<k,v> implement Map.Entry<k,v>{ final int hash; final k key; v value; Node<k,v> next; Node(int hash,k key,V value,Node<k,v> next){ this.hash = hash; this.key = key; this.value = value; this.next = next; } } //When put ting for the first time, create an array (capacity expansion mechanism 0 → 16) //Judge whether the index position where the data array is stored is null -- null -- added successfully → Not for null : judge hash Whether the value is equal to the existing element - there is no equality - added successfully → Hash Equal value : judge key Same - unequal - added successfully → Equal - replaces the of two key value pairs value value When the length of the linked list exceeds 8, the length of the array is less than 64 → Perform capacity expansion When the length of the linked list exceeds 8, the length of the array is greater than 64 → Convert linked list to tree //When adding, create a Node object and link it to an existing Node
jdk 8 is different from jdk 7 in terms of underlying implementation:
(1) new HashMap(): the underlying layer does not create an array with a length of 16.
(2) The array at the bottom of jdk 8 is Node [], not Entry [].
(3) When the put () method is called for the first time, the underlying layer creates an array with a length of 16.
(4) The underlying structure of jdk 7 is only array + linked list. The underlying structure of jdk 8 is array + linked list + red black tree. When the number of data in the form of linked list of elements at an index position of the array is > 8 and the length of the array is > 64, all data at this index position will be stored in red black tree instead.
4. Common methods
(1) Add, delete and modify:
Object put(Object key,Object value): Will specify key-value Add to(Or modify)current map Object void putAll(Map m):take m All in key-value Save to current map in Object remove(Object key): Remove assignment key of key-value Yes, and return value void clear(): Clear current map All data in
(2) Operation of element query:
Object get(Object key): Get specified key Corresponding value boolean containsKey(Object key): Include the specified key boolean containsValue(Object value): Include the specified value int size(): return map in key-value Number of pairs boolean isEmpty(): Judge current map Is it empty boolean equals(Object obj): Judge current map And parameter objects obj Are they equal
(3) Method of metaview operation:
Set keySet(): Return all key Constitutive Set aggregate Collection values(): Return all value Constitutive Collection aggregate Set entrySet(): Return all key-value To constitute Set aggregate
map does not have an iterator method. During traversal, you can use the above methods to get set or Collection, and then use their iterator method to realize traversal.
demo
import org.junit.jupiter.api.Test; import java.util.*; public class MapMethodTest { @Test public void test(){ Map map = new HashMap(); //put map.put(1, "AAA"); map.put(2, "BBB"); map.put(3, "CCC"); map.put(4, "DDD"); //Generally, all key types are the same; All values have the same type map.put("EEE", "DDD"); //When the added key value pairs have the same keys, the modification of the key value pair value is actually completed map.put(1, "EEE"); System.out.println(map); //putAll: Map map1 = new HashMap(); map1.put(9, "ZZZ"); map1.put(8, "XXX"); map1.put(7, "GGG"); map1.put(6, "HHH"); map .putAll(map1); System.out.println(map); //remove; Specify the key to remove the key value pair and return System.out.println(map.remove(9)); // //Clear: clear the elements in the map without affecting their size // map.clear(); // //Gets the number of key value pairs in the map // System.out.println(map.size()); // System.out.println(map); //Query: get returns the key value pair of the specified key System.out.println(map.get(9)); //containsKey: determine whether the key is included System.out.println(map.containsKey(4)); //containsValue: judge whether to include Value System.out.println(map.containsValue("DDD")); //isEmpty: judge whether the map is kong System.out.println(map.isEmpty()); //equals: determine whether the map s are the same System.out.println(map.equals(map1)); //Traversal operation: //set keySet() gets the set set composed of all keys Set set = map.keySet(); Iterator iterator = set.iterator(); while(iterator.hasNext()){ System.out.println(iterator.next()); } //Collection values() gets the collection collection composed of all values Collection list = map.values(); for(Object s:list){ System.out.println(s); } //Set entrySet() gets the set set composed of all key value pairs //All the elements in the obtained collection are entry class objects Set set1 = map.entrySet(); Iterator iterator1 = set1.iterator(); while(iterator1.hasNext()){ System.out.println(iterator1.next()); //After converting the type, get the key and value respectively System.out.println(((Map.Entry)(iterator.next())).getKey()); System.out.println(((Map.Entry)(iterator.next())).getValue()); } } }
7, Collections tool class
1. General
(1) Collections is a tool class that operates on collections such as Set, List, and Map.
(2) Collections provides a series of static methods to sort, query and modify collection elements. It also provides methods to set immutable collection objects and realize synchronous control over collection objects.
2. Common methods
1) Sorting operations: (all static methods)
reverse(List): reversal List Order of elements in shuffle(List): yes List Random sorting of collection elements sort(List): Assign to elements according to their natural order List The collection elements are sorted in ascending order sort(List,Comparator): According to the specified Comparator Generated sequence pair List Sort collection elements swap(List,int, int): Will specify list In the collection i At element and j Exchange elements at
(2) Find, replace
Object max(Collection): Returns the largest element in a given set according to the natural order of the elements Object max(Collection,Comparator): according to Comparator Returns the largest element in a given collection in the specified order Object min(Collection) Object min(Collection,Comparator) int frequency(Collection,Object): Returns the number of occurrences of the specified element in the specified collection void copy(List dest,List src): take src Copy content from to dest in boolean replaceAll(List list,Object oldVal,Object newVal): Replace with new value List All old values of the object
demo
import org.junit.jupiter.api.Test; import java.util.*; public class CollectionsTest { @Test public void test(){ List list = new ArrayList(); list.add(111); list.add(121); list.add(11); list.add(11); list.add(91); System.out.println(list); //reverse(List): reverses the order of elements in the List Collections.reverse(list);//Type must be an ordered List System.out.println(list); //shuffle(List): randomly sort the elements in the List Collections.shuffle(list); System.out.println(list); //sort(List): sort the elements in the List naturally (in ascending order) Collections.sort(list); System.out.println(list); //sort(List,Comparator): use the specified comparator to customize the sorting of all elements in the List Collections.shuffle(list); Collections.sort(list, new Comparator() { @Override public int compare(Object o1, Object o2) { if(o1 instanceof Integer && o2 instanceof Integer){ return (Integer)((Integer) o1).compareTo((Integer) o2);//The custom sorting here actually calls its natural sorting method }; throw new RuntimeException("type mismatch"); } }); System.out.println(list); //swap(List, int,int): the element exchange position of two index positions specified in the List Collections.swap(list,1,3); System.out.println(list); //Object max(Collection) and min(Collection): give the largest / smallest elements according to natural sorting System.out.println((Integer)Collections.max(list)); System.out.println((Integer)Collections.min(list)); //int frequency(Collection): returns the number of occurrences of the specified element System.out.println(Collections .frequency(list, 11)); // Void copy (list DeST, list SRC): copy the source collection elements to the target collection List list1 = new ArrayList(); // Collections.copy(list1, list);// The target collection capacity must be greater than the source collection Java lang.IndexOutOfBoundsException: Source does not fit in dest List list2 = Arrays.asList(new Object[list.size()]); System.out.println(list2); Collections.copy(list2, list); System.out.println(list2); //boolean replaceAll() replaces all specified values in the list Collections.replaceAll(list, 11, 56); } }
reference resources
1,https://blog.csdn.net/qq_43810938/article/details/118157638
2,https://blog.csdn.net/Hhuaahua/article/details/109038447