[Java] collection

Table of contents

1. Sets and Arrays

1. Overview of collection and array storage data:

2. Features of array storage:

3. Disadvantages of array storage:

4. Advantages of collective storage:

5. Classification of collections

6. The framework structure of the collection

2. Collection interface

1. Single-column collection frame structure

2. Common methods of the Collection interface:

3. Conversion between Collection collection and array

3. Iterator interface and foreach loop

1. Two ways to traverse Collection:

2. The iterator interface defined under the java.utils package: Iterator

3. New features of JDK 5.0 - enhanced for loop: (foreach loop)

4. Collection sub-interface: List interface

1. Stored data characteristics:

2. Common methods:

3. Common implementation classes:

4. Source code analysis (difficulty)

5. Requirements for stored elements:

6. Interview questions

5. Collection sub-interface: Overview of Set interface

1. Stored data characteristics:

2. Element addition process: (take HashSet as an example)

3. Common methods

4. Common implementation classes:

5. Requirements for the class of the storage object:

6. Use of TreeSet

6. Map interface

1. Common implementation class structure

2. Understanding of storage structure:

3. Common methods

4. Memory structure description: (difficult point)

5. Use of TreeMap

6. Use Properties to read the configuration file

7. Interview questions

Seven, the use of Collection tools

1. Function:

2. Common methods:

8. Brief description of data structure

1. Data structure overview

2. Understanding of data structures and algorithms

3. Research object of data structure

4. Mind map:


1. Sets and Arrays

1. Overview of collection and array storage data:

Collections and arrays are structures that store and operate multiple data, referred to as Java containers. Note: The storage at this time mainly refers to the storage at the memory level, and does not involve persistent storage (.txt, .jpg, .avi, in the database)

2. Features of array storage:

Once initialized, its length is determined. Once an array is defined, the type of its elements is determined. We can only operate on specified types of data.

For example: String[] arr, int[] arr1,Object[] arr2

3. Disadvantages of array storage:

  1. Once initialized, its length cannot be modified.
  2. The methods provided in the array are very limited, and it is very inconvenient and inefficient for operations such as adding, deleting, and inserting data.
  3. The need to obtain the actual number of elements in the array, the array has no ready-made properties or methods available
  4. The characteristics of array storage data: orderly and repeatable. For disorderly and non-repeatable requirements, it cannot be satisfied.

4. Advantages of collective storage:

Solve the disadvantages of array storage data.

5. Classification of collections

Java collections can be divided into two systems: Collection and Map

  • Collection interface: a single column of data that defines a collection of methods for accessing a set of objects
    • List: an ordered, repeatable collection of elements
    • Set: an unordered, non-repeatable set of elements
  • Map interface: double-column data, saving a collection of "key-value pairs" with a mapping relationship

6. The framework structure of the collection

|----Collection接口:单列集合,用来存储一个一个的对象
     |----List接口:存储有序的、可重复的数据。  -->“动态”数组
           |----ArrayList:作为List接口的主要实现类,线程不安全的,效率高;底层采用Object[] elementData数组存储
           |----LinkedList:对于频繁的插入删除操作,使用此类效率比ArrayList效率高底层采用双向链表存储
           |----Vector:作为List的古老实现类,线程安全的,效率低;底层采用Object[]数组存储
           
     |----Set接口:存储无序的、不可重复的数据   -->数学概念上的“集合”
           |----HashSet:作为Set接口主要实现类;线程不安全;可以存null值
           		|----LinkedHashSet:作为HashSet的子类;遍历其内部数据时,可以按照添加顺序遍历;对于频繁的遍历操作,LinkedHashSet效率高于HashSet.
           |----TreeSet:可以按照添加对象的指定属性,进行排序。


|----Map:双列数据,存储key-value对的数据   ---类似于高中的函数:y = f(x)
     |----HashMap:作为Map的主要实现类;线程不安全的,效率高;存储null的key和value
          |----LinkedHashMap:保证在遍历map元素时,可以照添加的顺序实现遍历。
                    原因:在原的HashMap底层结构基础上,添加了一对指针,指向前一个和后一个元素。
                    对于频繁的遍历操作,此类执行效率高于HashMap。
     |----TreeMap:保证照添加的key-value对进行排序,实现排序遍历。此时考虑key的自然排序或定制排序
                      底层使用红黑树
     |----Hashtable:作为古老的实现类;线程安全的,效率低;不能存储null的key和value
          |----Properties:常用来处理配置文件。key和value都是String类型


复制代码

2. Collection interface

  • The Collection interface is the parent interface of the List, Set, and Queue interfaces. The methods defined in this interface can be used to operate both the Set collection and the List and Queue collections.
  • JDK does not provide any direct implementation of this interface, but provides more specific subinterfaces (such as: Set and List) implementation.
  • Before JDK 5.0, Java collections would lose the data types of all objects in the container and treat all objects as Object types; since JDK 5.0 added generics, Java collections can remember the data types of objects in the container.

1. Single-column collection frame structure

|----Collection接口:单列集合,用来存储一个一个的对象
     |----List接口:存储有序的、可重复的数据。  -->“动态”数组
           |----ArrayList:作为List接口的主要实现类,线程不安全的,效率高;底层采用Object[] elementData数组存储
           |----LinkedList:对于频繁的插入删除操作,使用此类效率比ArrayList效率高底层采用双向链表存储
           |----Vector:作为List的古老实现类,线程安全的,效率低;底层采用Object[]数组存储
           
     |----Set接口:存储无序的、不可重复的数据   -->数学概念上的“集合”
           |----HashSet:作为Set接口主要实现类;线程不安全;可以存null值
           		|----LinkedHashSet:作为HashSet的子类;遍历其内部数据时,可以按照添加顺序遍历;对于频繁的遍历操作,LinkedHashSet效率高于HashSet.
           |----TreeSet:可以按照添加对象的指定属性,进行排序。


复制代码

Graphic:

2. Common methods of the Collection interface:

  1. Add to
    • add(Object obj)
    • addAll(Collection coll)
  2. Get the number of valid elements
    • int size()
  3. empty collection
    • void clear()
  4. Is it an empty collection
    • boolean isEmpty()
  5. Does it contain an element
    • boolean contains(Object obj): It is to judge whether it is the same object through the equals method of the element
    • boolean containsAll(Collection c): It is also compared by calling the equals method of the element. Compare elements of two collections one by one
  6. delete
    • boolean remove(Object obj): Determine whether it is the element to be deleted by the equals method of the element. Only the first element found will be removed
    • boolean removeAll(Collection coll): Take the difference of the current set
  7. Take the intersection of two sets
    • boolean retainAll(Collection c): Store the intersection result in the current collection without affecting c
  8. Are the sets equal
    • boolean equals(Object obj)
  9. Convert to an array of objects
    • Object [] toArray()
  10. Get the hash value of the collection object
-   `hashCode()`

复制代码
  1. traverse
-   `iterator()`:返回迭代器对象,用于集合遍历

复制代码

Code example:

@Test
public void test1() {
    Collection collection = new ArrayList();
    //1.add(Object e):将元素添加到集合中
    collection.add("ZZ");
    collection.add("AA");
    collection.add("BB");
    collection.add(123);
    collection.add(new Date());
    //2.size():获取添加元素的个数
    System.out.println(collection.size());//5
    //3.addAll(Collection coll1):将coll1集合中的元素添加到当前集合中
    Collection collection1 = new ArrayList();
    collection1.add("CC");
    collection1.add(213);
    collection.addAll(collection1);
    System.out.println(collection.size());//9
    //调用collection1中的toString()方法输出
    System.out.println(collection);//[ZZ, AA, BB, 123, Tue Apr 28 09:22:34 CST 2020, 213, 213]
    //4.clear():清空集合元素
    collection1.clear();
    System.out.println(collection1.size());//0
    System.out.println(collection1);//[]
    //5.isEmpty():判断当前集合是否为空
    System.out.println(collection1.isEmpty());//true
}

@Test
public void test2() {
    Collection coll = new ArrayList();
    coll.add(123);
    coll.add(456);
    coll.add(new Person("Tom", 23));
    coll.add(new Person("Jarry", 34));
    coll.add(false);
    //6.contains(Object obj):判断当前集合中是否包含obj
    //判断时需要调用obj对象所在类的equals()方法
    System.out.println(coll.contains(123));//true
    System.out.println(coll.contains(new Person("Tom", 23)));//true
    System.out.println(coll.contains(new Person("Jarry", 23)));//false
    //7.containsAll(Collection coll1):判断形参coll1中的元素是否都存在当前集合中
    Collection coll1 = Arrays.asList(123, 4566);
    System.out.println(coll.containsAll(coll1));//flase
    //8.remove(Object obj):从当前集合中移除obj元素
    coll.remove(123);
    System.out.println(coll);//[456, Person{name='Tom', age=23}, Person{name='Jarry', age=34}, false]
    //9.removeAll(Collection coll1):差集:从当前集合中和coll1中所有的元素
    Collection coll2 = Arrays.asList(123, 456, false);
    coll.removeAll(coll2);
    System.out.println(coll);//[Person{name='Tom', age=23}, Person{name='Jarry', age=34}]
}

@Test
public void test3() {
    Collection coll = new ArrayList();
    coll.add(123);
    coll.add(456);
    coll.add(new Person("Tom", 23));
    coll.add(new Person("Jarry", 34));
    coll.add(false);
    //10.retainAll(Collection coll1):交集:获取当前集合和coll1集合的交集,并返回给当前集合
    Collection coll1 = Arrays.asList(123, 345, 456);
    boolean b = coll.retainAll(coll1);
    System.out.println(b);//true
    System.out.println(coll);//[123, 456]
    //11.equals(Object obj):返回true需要当前集合和形参集合的元素相同
    Collection coll2 = new ArrayList();
    coll2.add(123);
    coll2.add(456);
    System.out.println(coll.equals(coll2));//true
    //12.hashCode():返回当前对象的哈希值
    System.out.println(coll.hashCode());//5230
    //13.集合--->数组:toArray()
    Object[] array = coll.toArray();
    for (Object obj : array) {
        System.out.println(obj);
    }
    //14.数组--->集合:调用Arrays类的静态方法asList()
    List<int[]> ints = Arrays.asList(new int[]{123, 345});
    System.out.println(ints.size());//1
    List<String> strings = Arrays.asList("AA", "BB", "CC");
    System.out.println(strings);//[AA, BB, CC]
    //15.iteratoriterator():返回Iterator接口的实例,用于遍历集合元素。
}


复制代码

3. Conversion between Collection collection and array

//集合 --->数组:toArray()
Object[] arr = coll.toArray();
for(int i = 0;i < arr.length;i++){
    System.out.println(arr[i]);
}

//拓展:数组 --->集合:调用Arrays类的静态方法asList(T ... t)
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


复制代码

To use Collection to store objects, the class to which the object belongs is required to meet:

When adding data obj to the object of the implementation class of the Collection interface, the class where obj is required to be rewritten  equals().

3. Iterator interface and foreach loop

1. Two ways to traverse Collection:

① Use iterator Iterator

② foreach loop (or enhanced for loop)

2. The iterator interface defined under the java.utils package: Iterator

2.1 Description:

The Iterator object is called an iterator (a type of design pattern), and it is mainly used to traverse the elements in the Collection collection. GOF defines the iterator pattern as: providing a method to access each element in a container object without exposing the internal details of the object. The iterator pattern is born for containers.

2.2 Function:

Traverse collection Collectiton elements

2.3 How to get an instance:

coll.iterator() returns an iterator instance

2.4 Code implementation of traversal:

Iterator iterator = coll.iterator();
//hasNext():判断是否还下一个元素
while(iterator.hasNext()){
    //next():①指针下移 ②将下移以后集合位置上的元素返回
    System.out.println(iterator.next());
}


复制代码

2.5 Illustrations:

2.6 Use of remove() method in iterator:

  • Test the Iterator in remove()
  • If the method has not been called  or the method  has been called after  next() the last method call   , it will report if you call remove again  .next()remove()IllegalStateException
  • Internally defined  remove(), elements in the collection can be deleted during traversal. This method is different from the collection calling directlyremove()

Code example:

@Test
public void test3(){
    Collection coll = new ArrayList();
    coll.add(123);
    coll.add(456);
    coll.add(new Person("Jerry",20));
    coll.add("Tom"
            );
    coll.add(false);

    //删除集合中"Tom"
    Iterator iterator = coll.iterator();
    while (iterator.hasNext()){
        //            iterator.remove();
        Object obj = iterator.next();
        if("Tom".equals(obj)){
            iterator.remove();
            //                iterator.remove();
        }

    }
    //将指针重新放到头部,遍历集合
    iterator = coll.iterator();
    while (iterator.hasNext()){
        System.out.println(iterator.next());
    }
}


复制代码

3. New features of JDK 5.0 - enhanced for loop: (foreach loop)

3.1 Example of traversing collections:

@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);

    //for(集合元素的类型 局部变量 : 集合对象)
    
    for(Object obj : coll){
        System.out.println(obj);
    }
}


复制代码

Explanation: The iterator is still called internally.

3.2. Example of traversing an array:

@Test
public void test2(){
    int[] arr = new int[]{1,2,3,4,5,6};
    //for(数组元素的类型 局部变量 : 数组对象)
    for(int i : arr){
        System.out.println(i);
    }
}


复制代码

4. Collection sub-interface: List interface

1. Stored data characteristics:

Store sequential, repeatable data.

  • In view of the limitations of arrays used to store data in Java, we usually use List instead of arrays
  • The elements in the List collection class are ordered and repeatable, and each element in the collection has its corresponding sequential index.
  • The elements in the List container correspond to an integer serial number to record its position in the container, and the elements in the container can be accessed according to the serial number.
  • Common implementation classes of List interface in JDK AP are: ArrayList, LinkedList and Vector.

2. Common methods:

In addition to the methods inherited from the Collection collection, the List collection adds some methods for manipulating the elements of the collection based on the index.

  • 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): Get the element at the specified index position
  • 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): Remove the element at the specified index position and return this element
  • Object set(int index, Object ele): Set the element at the specified index position to ele
  • List subList(int fromIndex, int toIndex): Returns the sub-collection from fromIndex to toIndex

Summarize:

  • increase:add(Object obj)
  • delete: remove(int index) / remove(Object obj)
  • change:set(int index, Object ele)
  • check:get(int index)
  • Insert:add(int index, Object ele)
  • length:size()
  • Traversal: ① Iterator iterator method ② foreach (enhanced for loop) ③ Ordinary loop

Code example:

@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):返回obj在集合中首次出现的位置。如果不存在,返回-1.
    int index = list.indexOf(4567);
    System.out.println(index);

    //int lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置。如果不存在,返回-1.
    System.out.println(list.lastIndexOf(456));

    //Object remove(int index):移除指定index位置的元素,并返回此元素
    Object obj = list.remove(0);
    System.out.println(obj);
    System.out.println(list);

    //Object set(int index, Object ele):设置指定index位置的元素为ele
    list.set(1,"CC");
    System.out.println(list);

    //List subList(int fromIndex, int toIndex):返回从fromIndex到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):在index位置插入ele元素
    list.add(1,"BB");
    System.out.println(list);

    //boolean addAll(int index, Collection eles):从index位置开始将eles中的所有元素添加进来
    List list1 = Arrays.asList(1, 2, 3);
    list.addAll(list1);
    //        list.add(list1);
    System.out.println(list.size());//9

    //Object get(int index):获取指定index位置的元素
    System.out.println(list.get(0));

}


复制代码

3. Common implementation classes:

3. 常用实现类:
|----Collection接口:单列集合,用来存储一个一个的对象
  |----List接口:存储序的、可重复的数据。  -->“动态”数组,替换原的数组
      |----ArrayList:作为List接口的主要实现类;线程不安全的,效率高;底层使用Object[] elementData存储
      |----LinkedList:对于频繁的插入、删除操作,使用此类效率比ArrayList高;底层使用双向链表存储
      |----Vector:作为List接口的古老实现类;线程安全的,效率低;底层使用Object[] elementData存储


复制代码

3.1 ArrayList

  • ArrayList is a typical implementation class of the List interface, the main implementation class
  • Essentially, ArrayList is a "variable length" array of object references
  • What is the difference between the implementation of Array Listi before and after JDK 1.8?
    • JDK 1.7: ArrayList is like a hungry man, directly creating an array with an initial capacity of 10
    • JDK 1.8: ArrayList is like a lazy man, creating an array with a length of 0 at the beginning, and creating an array with an initial capacity of 10 when adding the first element
  • Arrays.asList(...)The List collection returned by the method is neither an ArrayList instance nor a Vector instance. Arrays.asList(...)The return value is a fixed-length List collection

Code example:

@Test
public void test1() {
    Collection coll = new ArrayList();
    coll.add(123);
    coll.add(345);
    coll.add(new User("Tom", 34));
    coll.add(new User("Tom"));
    coll.add(false);
    //iterator()遍历ArrayList集合
    Iterator iterator = coll.iterator();
    while (iterator.hasNext()) {
        System.out.println(iterator.next());
    }
}


复制代码

3.2 linkedList

  • For frequent insertion and deletion of elements, it is recommended to use the LinkedList class, which is more efficient

  • New method:

    • void addFirst(Object obj)
    • void addLast(Object obj)
    • Object getFirst()
    • Object getlast)()
    • Object removeFirst()
    • Object removeLast()
  • Linkedlist: A doubly linked list. Instead of declaring an array inside, it defines frst and last of the Node type to record the first and last elements. At the same time, define the internal class Node as the basic structure for saving data in Linkedlist. In addition to saving data, Node also defines two variables:

    • prev: The variable records the position of the previous element
    • next: The variable records the position of the next element

Code example:

@Test
public void test3(){
    LinkedList linkedList = new LinkedList();
    linkedList.add(123);
    linkedList.add(345);
    linkedList.add(2342);
    linkedList.add("DDD");
    linkedList.add("AAA");
    
    Iterator iterator = linkedList.iterator();
    while (iterator.hasNext()){
        System.out.println(iterator.next());
    }
}


复制代码

4. Source code analysis (difficulty)

4.1 Source code analysis of ArrayList:

4.1.1 In the case of JDK 7.0

ArrayList list = new ArrayList();//底层创建了长度是10的Object[]数组elementData
list.add(123);//elementData[0] = new Integer(123);
...
list.add(11);//如果此次的添加导致底层elementData数组容量不够,则扩容。


复制代码
  • By default, the expansion is 1.5 times the original capacity, and the data in the original array needs to be copied to the new array.

  • Conclusion: It is recommended to use constructors with parameters in development:ArrayList list = new ArrayList(int capacity)

4.1.2 Changes of ArrayList in JDK 8.0:

ArrayList list = new ArrayList();//底层Object[] elementData初始化为{}.并没创建长度为10的数组
list.add(123);//第一次调用add()时,底层才创建了长度10的数组,并将数据123添加到elementData[0]
...


复制代码

Subsequent addition and expansion operations are no different from JDK 7.0.

4.1.3 Summary:

The creation of ArrayList objects in JDK 7.0 is similar to the hungry style of singletons, while the creation of ArrayList objects in JDK 8.0 is similar to the lazy style of singletons, which delays the creation of arrays and saves memory.

4.2 Source code analysis of LinkedList:

LinkedList list = new LinkedList(); //内部声明了Node类型的first和last属性,默认值为null
list.add(123);//将123封装到Node中,创建了Node对象。

//其中,Node定义为:体现了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.3 Source code analysis of Vector:

  • Vector is an ancient collection, JDK 1.0 will have. Most operations are the same as ArrayList, the difference is that Vector is thread-safe
  • Among various lists, it is best to use ArrayList as the default choice. When insertion and deletion are frequent, use LinkedList; Vector is always slower than ArrayList, so try to avoid using it.
  • When creating an object through the Vector() constructor in JDK 7.0 and JDK 8.0, an array with a length of 10 is created at the bottom layer.
  • In terms of expansion, the default expansion is twice the length of the original array.

5. Requirements for stored elements:

The added object, the class where it is located must override the equals() method

6. Interview questions

May I ask the similarities and differences of ArrayList/LinkedList/Vector? Talk about your understanding? What is the bottom layer of ArrayList? Expansion mechanism? The biggest difference between Vector and ArrayList?

  • The similarities and differences between ArrayList and Linkedlist:

    Both are thread-unsafe. Compared with thread-safe Vector, ArrayList has higher execution efficiency. In addition, ArrayList implements a data structure based on a dynamic array, and Linkedlist is based on a linked list data structure. For random access get and set, ArrayList is better than Linkedlist, because Linkedlist needs to move the pointer. For adding and deleting operations add (specifically insert) and remove, Linkedlist has an advantage because ArrayList needs to move data.

  • The difference between ArrayList and Vector:

    Vector and ArrayList are almost identical, the only difference is that Vector is a synchronized class (synchronized), which belongs to the strong synchronization class. Therefore, the overhead is larger than that of ArrayList, and the access is slower. Under normal circumstances, most Java programmers use ArrayList instead of Vector, because synchronization can be completely controlled by the programmer. Vector requests 2 times its size each time it expands, while ArrayList requires 1.5 times. Vector also has a subclass Stack.

5. Collection sub-interface: Overview of Set interface

  • The Set interface is a subinterface of Collection, and the set interface does not provide additional methods
  • The Set collection is not allowed to contain the same elements. If you try to add two identical elements to the same Set collection, the addition operation will fail. (It is mostly used for filtering operations and removing duplicate data)
  • Set determines whether two objects are the same not using the == operator, but according to the equals() method

1. Stored data characteristics:

Used to store unordered, non-repeatable elements

Take HashSet as an example:

  1. Disorder: Not equal to randomness. The stored data is not added in the order of the array index in the underlying array, but is determined according to the hash value of the data.
  2. Non-repeatability: Ensure that the added element cannot return true when judged by equals(). That is: only one of the same element can be added.

2. Element addition process: (take HashSet as an example)

We add element a to HashSet, first call the hashCode() method of the class where element a belongs to calculate the hash value of element a, and then calculate the storage location in the underlying array of HashSet through a certain algorithm for this hash value (that is, : index position), judging

Whether the array already has an element at this position:

  • If there is no other element at this position, element a is added successfully. ---> Case 1
  • If there is another element b (or multiple elements in the form of a linked list) at this position, then compare the hash values ​​of element a and element b:
    • If the hash values ​​are not the same, element a is successfully added. ---> Case 2
    • If the hash values ​​are the same, then you need to call the equals() method of the class where element a is located:
      • equals() returns true, element a failed to add
      • equals() returns false, then element a is added successfully. ---> Case 3

For cases 2 and 3 where the addition is successful: the element a and the data already existing at the specified index position are stored in the form of a linked list.

JDK 7.0: Element a is placed in the array and points to the original element.

JDK 8.0: The original element is in the array, pointing to element a

Summary: ups and downs

The bottom layer of HashSet: the structure of array + linked list. (before JDK 7.0)

3. Common methods

There are no additional new methods defined in the Set interface, and all methods declared in Collection are used.

3.1 The basic method of rewriting hashCode()

  • When the program is running, calling  hashCode() the method multiple times on the same object should return the same value.

  • When the method comparison of two objects  returns true,  the return values ​​of the methods equals() of these two objects  should also be equal.hashCode()

  • The Field used for method comparison in the object  equals() should be used to calculate the hashCode value.

3.2  equals() Basic principles of overriding methods

  • Taking the custom Customer class as an example, when does it need to be rewritten  equals()?

  • When a class has its own unique concept of "logical equality", when rewriting equals(), it must always be rewritten.  hash Code()According to the equals method of a class (after rewriting), two completely different instances may be logically equal , but, according to  Object.hashCode() method, they are just two objects.

  • Therefore, objects that violate equality must have equal hash codes .

  • Conclusion: When rewriting the equals method, it is generally necessary to rewrite the hashCode method at the same time. Usually the properties of the object involved in the calculation of hashCode should also be involved in  equals() the calculation.

3.3 hashCode() rewriting in Eclipse/IDEA tools

Taking Eclipse/DEA as an example, tools can be called to automatically rewrite  equals() and hashCode()

Question: Why is there a number of 31 when rewriting the hash Code method with Eclipse/IDEA?

  • When selecting the coefficient, choose the coefficient as large as possible. Because if the calculated hash address is larger, the so-called "conflicts" will be less, and the search efficiency will be improved. (less conflict)

  • And 31 only occupies 5 bits, the probability of data overflow caused by multiplication is small.

  • 31 can be represented by i*31==(<<5)-1, and now many virtual machines have related optimizations. (improve algorithm efficiency)

  • 31 is a prime number. The function of a prime number is that if I multiply this prime number by a number, the final result can only be divisible by the prime number itself, the multiplicand and 1! (less conflict)

Code example:

@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;
}


复制代码

4. Common implementation classes:

 |----Collection接口:单列集合,用来存储一个一个的对象
      |----Set接口:存储无序的、不可重复的数据   -->高中讲的“集合”
           |----HashSet:作为Set接口的主要实现类;线程不安全的;可以存储null值
                |----LinkedHashSet:作为HashSet的子类;遍历其内部数据时,可以按照添加的顺序遍历,对于频繁的遍历操作,LinkedHashSet效率高于HashSet.
           |----TreeSet:可以按照添加对象的指定属性,进行排序。


复制代码

4.1 HashSet

  • Hashset is a typical implementation of the Set interface, and this implementation class is used most of the time when using the Set collection.
  • HashSet stores the elements in the collection according to the Hash algorithm, so it has good access, search, and deletion performance.
  • HashSet has the following characteristics:
    • The order of the elements is not guaranteed
    • HashSet is not thread safe
    • Collection elements can be nul
  • HashSet sets the criteria for judging the equality of two elements: two objects are compared equal by the hashCode() method, and the return values ​​of the equals() method of the two objects are also equal.
  • For the objects stored in the Set container, the corresponding class must rewrite the equals() and hashCode(Object obj) methods to implement the object equality rule. That is: "Equal objects must have equal hash codes"

Code example:

@Test
//HashSet使用
public void test1(){
    Set set = new HashSet();
    set.add(454);
    set.add(213);
    set.add(111);
    set.add(123);
    set.add(23);
    set.add("AAA");
    set.add("EEE");
    set.add(new User("Tom",34));
    set.add(new User("Jarry",74));

    Iterator iterator = set.iterator();
    while (iterator.hasNext()){
        System.out.println(iterator.next());
    }
}


复制代码

4.2 LinkedHashSet

  • LinkedhashSet is a subclass of HashSet

  • LinkedhashSet determines the storage location of the element according to the hashCode value of the element, but it also uses a doubly linked list to maintain the order of the elements, which makes the elements appear to be stored in the order of insertion.

  • The insertion performance of LinkedhashSet is slightly lower than that of HashSet, but it has good performance when iterating through all elements in Set.

  • LinkedhashSet does not allow duplicate collection elements.

Graphic:

Code example:

@Test
//LinkedHashSet使用
public void test2(){
    Set set = new LinkedHashSet();
    set.add(454);
    set.add(213);
    set.add(111);
    set.add(123);
    set.add(23);
    set.add("AAA");
    set.add("EEE");
    set.add(new User("Tom",34));
    set.add(new User("Jarry",74));

    Iterator iterator = set.iterator();
    while (iterator.hasNext()){
        System.out.println(iterator.next());
    }
}


复制代码

4.3 TreeSet

  • Treeset is an implementation class of the SortedSet interface, and TreeSet can ensure that the collection elements are in a sorted state.

  • The bottom layer of TreeSet uses red-black tree structure to store data

  • The newly added method is as follows: (understand)

    • Comparator comparator()

    • Object first()

    • Object last()

    • Object lower(object e)

    • Object higher(object e)

    • SortedSet subSet(fromElement, toElement)

    • SortedSet headSet(toElement)

    • SortedSet tailSet(fromElement)

  • TreeSet has two sorting methods: natural sorting and custom sorting. By default, TreeSet adopts natural ordering.

Red-black tree diagram:

The characteristics of red-black tree: orderly, query efficiency is faster than List

Detailed introduction: www.cnblogs.com/LiaHon/p/11…

Code example:

@Test
public void test1(){
    Set treeSet = new TreeSet();
    treeSet.add(new User("Tom",34));
    treeSet.add(new User("Jarry",23));
    treeSet.add(new User("mars",38));
    treeSet.add(new User("Jane",56));
    treeSet.add(new User("Jane",60));
    treeSet.add(new User("Bruce",58));

    Iterator iterator = treeSet.iterator();
    while (iterator.hasNext()){
        System.out.println(iterator.next());
    }
}


复制代码

5. Requirements for the class of the storage object:

5.1HashSet/LinkedHashSet:

  • Requirements: For the data added to Set (mainly refers to: HashSet, LinkedHashSet), its class must rewrite hashCode() and equals()
  • Requirements: The rewritten hashCode() and equals() are as consistent as possible: equal objects must have equal hash codes

Tips for overriding the two methods: the Field used in the object for comparison by the equals() method should be used to calculate the hashCode value.

5.2 TreeSet:

  1. In natural sorting, the standard for comparing whether two objects are the same is: compareTo() return 0. No longer equals()

  2. In custom sorting, the standard for comparing whether two objects are the same is: compare() return 0. No longer equals()

6. Use of TreeSet

6.1 Instructions for use:

  1. The data added to the TreeSet is required to be objects of the same class.

  2. Two sorting methods: natural sorting (implementing the Comparable interface and custom sorting (Comparator)

6.2 Commonly used sorting methods:

Method 1: Natural sorting

  • Natural sorting: TreeSet will call  compareTo(object obj) the method of collection elements to compare the size relationship between elements, and then arrange the collection elements in ascending order (by default)

  • If you try to add an object to the Treeset, the object's class must implement the Comparable interface.

    • The class that implements Comparable must implement  compareTo(Object obj) the method, and the two objects are compareTo(Object obj) compared by the return value of the method
  • A typical implementation of Comparable:

    • BigDecimal, BigInteger, and all the wrapper classes corresponding to numeric types: compare according to their corresponding numerical sizes

    • Character: unic by character! ode value to compare

    • Boolean: the wrapper class instance corresponding to true is greater than the wrapper class instance corresponding to false

    • String: Compare by the unicode value of the characters in the string

    • Date, Time: the later time and date are larger than the previous time and date

  • When adding elements to the TreeSet, only the first element does not need the comparison  compareTo() method, and all elements added later will call  compareTo() the method for comparison.

  • Because only two instances of the same class will compare in size, objects of the same class should be added to the TreeSet. For the TreeSet collection, the only criterion for judging whether two objects are equal is:  compareTo(Object obj) the return value of the two objects through method comparison.

  • When you need to put an object into the TreeSet and rewrite the equals() method corresponding to the object, you should ensure that the method  compareTo(Object obj) has the same result as the method: if two objects return true through the comparison of the equals() method, then use  compareTo(object ob) the method comparison Should return 0. Otherwise, it is hard to understand.

@Test
public void test1(){
    TreeSet set = new TreeSet();

    //失败:不能添加不同类的对象
    //        set.add(123);
    //        set.add(456);
    //        set.add("AA");
    //        set.add(new User("Tom",12));

    //举例一:
    //        set.add(34);
    //        set.add(-34);
    //        set.add(43);
    //        set.add(11);
    //        set.add(8);

    //举例二:
    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());
    }

}


复制代码

Method 2: Custom sorting

  • The natural sorting of TreeSet requires that the class to which the element belongs implements the Comparable interface. If the class to which the element belongs does not implement the Comparable interface, or if you do not want to arrange the elements in ascending order (by default) or want to sort by other attribute sizes, consider using custom sorting . Custom sorting is implemented through the Comparator interface. The compare(T o1, T o2) method needs to be rewritten.

  • Use  int compare(T o1,T o2) the method to compare the size of o1 and o2: if the method returns a positive integer, it means that o1 is greater than o2; if it returns 0, it means they are equal; if it returns a negative integer, it means that o1 is smaller than o2.

  • To implement custom sorting, an instance that implements the Comparator interface needs to be passed as a formal parameter to the TreeSet constructor.

  • At this point, only objects of the same type can still be added to the Treeset. Otherwise  ClassCastException an exception occurs

  • The standard for judging the equality of two elements using custom sorting is: comparing two elements through the Comparator returns 0

@Test
public void test2(){
    Comparator com = new Comparator() {
        //照年龄从小到大排列
        @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("输入的数据类型不匹配");
            }
        }
    };

    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());
    }
}


复制代码

6. Map interface

  • Map and Collection exist side by side. Used to save data with a mapping relationship: key-value
  • Both key and value in Map can be data of any reference type
  • The key in the Map is stored in a set, and duplication is not allowed, that is, the class corresponding to the same Map object must rewrite  hashCode() and  equals() method
  • The String class is often used as the "key" of the Map
  • There is a one-way one-to-one relationship between key and value, that is, a unique and definite value can always be found through the specified key
  • Common implementation classes of the Map interface: HashMap, TreeMap, LinkedHashMap and Properties. Among them, HashMap is the most frequently used implementation class of the Map interface.

1. Common implementation class structure

|----Map:双列数据,存储key-value对的数据   ---类似于高中的函数:y = f(x)
     |----HashMap:作为Map的主要实现类;线程不安全的,效率高;存储null的key和value
          |----LinkedHashMap:保证在遍历map元素时,可以照添加的顺序实现遍历。
                    原因:在原的HashMap底层结构基础上,添加了一对指针,指向前一个和后一个元素。
                    对于频繁的遍历操作,此类执行效率高于HashMap。
     |----TreeMap:保证照添加的key-value对进行排序,实现排序遍历。此时考虑key的自然排序或定制排序
                      底层使用红黑树
     |----Hashtable:作为古老的实现类;线程安全的,效率低;不能存储null的key和value
          |----Properties:常用来处理配置文件。key和value都是String类型


HashMap的底层: 数组+链表  (JDK 7.0及之前)
               数组+链表+红黑树 (JDK 8.0以后)


复制代码

1.1 HashMap

  • HashMap is the most frequently used implementation class of the Map interface.

  • Null keys and null values ​​are allowed, and like HashSet, the order of the mapping is not guaranteed.

  • The collection of all keys is a set: unordered and non-repeatable. Therefore, the class where the key is located should rewrite equals() and hashCode()

  • The collection of all values ​​is Collection: unordered and repeatable. Therefore, the class where the value is located should be rewritten: equals()

  • A key-value constitutes an entry

  • The set of all entries is Set: unordered and non-repeatable

  • The standard for HashMap to judge that two keys are equal is: the two keys  equals() return true through the method, and the hashCode values ​​are also equal.

  • The standard for HashMap to judge that two values ​​are equal is: the two values  equals() ​​return true through the method.

Code example:

@Test
public void test1(){
    Map map = new HashMap();

    map.put(null,123);

}


复制代码

1.2 LinkedHashMap

  • The underlying structure of LinkedHashMap is the same as that of HashMap, because LinkedHashMap inherits from HashMap.
  • The difference is that LinkedHashMap provides Entry inside, replacing Node in HashMap.
  • Similar to Linkedhash Set, LinkedHashMap can maintain the iteration order of Map: the iteration order is consistent with the insertion order of Key-value pairs

Code example:

@Test
public void test2(){
    Map map = new LinkedHashMap();
    map.put(123,"AA");
    map.put(345,"BB");
    map.put(12,"CC");

    System.out.println(map);
} 


复制代码

1.3 TreeMap

  • When TreeMap stores Key-Value pairs, it needs to be sorted according to the key-value pairs. TreeMap can guarantee that all Key-Value pairs are in an ordered state.

  • The bottom layer of TreeSet uses red-black tree structure to store data

  • The sorting of the Key of the TreeMap:

    • Natural sorting: All Keys of the TreeMap must implement the Comparable interface, and all Keys should be objects of the same class, otherwise ClassCastException() will be thrown
    • Custom sorting: When creating a TreeMap, pass in a Comparator object, which is responsible for sorting all the keys in the TreeMap. At this time, there is no need for the Key of the Map to implement the Comparable interface.
  • TreeMap judges the criteria for two keys to be equal: two keys return 0 through the compareTo() method or compare() method.

1.4 Hashtable

  • Hashtable is an ancient Map implementation class, which is provided by JDK1.0. Unlike HashMap, Hashtable is thread-safe.

  • The implementation principle of Hashtable is the same as that of HashMap, and the functions are the same. The bottom layer uses a hash table structure, the query speed is fast, and it can be used interchangeably in many cases

  • Unlike HashMap, Hashtable does not allow null as key and value.

  • Like HashMap, Hashtable cannot guarantee the order of Key-value pairs in it.

  • Hashtable judges that two keys are equal and two values ​​are equal, which is consistent with HashMap.

1.5 Properties

  • The Properties class is a subclass of Hashtable, which is used to process property files

  • Since the key and value in the property file are all string types, the key and value in Properties are all string types

  • When accessing data, it is recommended to use  setProperty(String key,String value) methods and  getProperty(String key) methods

Code example:

//Properties:常用来处理配置文件。key和value都是String类型
public static void main(String[] args)  {
    FileInputStream fis = null;
    try {
        Properties pros = new Properties();

        fis = new FileInputStream("jdbc.properties");
        pros.load(fis);//加载流对应的文件

        String name = pros.getProperty("name");
        String password = pros.getProperty("password");

        System.out.println("name = " + name + ", password = " + password);
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if(fis != null){
            try {
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

}


复制代码

2. Understanding of storage structure:

  • Key in Map: unordered, non-repeatable, use the key stored in Set ---> the class where the key is located should rewrite equals() and hashCode() (take HashMap as an example)
  • Value in Map: Unordered, repeatable, use Collection to store the value ---> the class where the value is located must rewrite equals()
  • A key-value pair: key-value constitutes an Entry object.
  • Entry in Map: unordered, non-repeatable, use Set to store the entry

3. Common methods

3.1 Add, delete, modify operations:

  • Object put(Object key,Object value): Add (or modify) the specified key-value to the current map object
  • void putAll(Map m): Store all key-value pairs in m into the current map
  • Object remove(Object key): Remove the key-value pair of the specified key and return the value
  • void clear(): Clear all data in the current map

Code example:

@Test
public void test1() {
    Map map = new HashMap();
    //Object put(Object key,Object value):将指定key-value添加到(或修改)当前map对象中
    map.put("AA",123);
    map.put("ZZ",251);
    map.put("CC",110);
    map.put("RR",124);
    map.put("FF",662);
    System.out.println(map);//{AA=123, ZZ=251, CC=110, RR=124, FF=662}

    //Object put(Object key,Object value):将指定key-value添加到(或修改)当前map对象中
    map.put("ZZ",261);
    System.out.println(map);//{AA=123, ZZ=261, CC=110, RR=124, FF=662}

    //void putAll(Map m):将m中的所有key-value对存放到当前map中
    HashMap map1 = new HashMap();
    map1.put("GG",435);
    map1.put("DD",156);
    map.putAll(map1);
    System.out.println(map);//{AA=123, ZZ=261, CC=110, RR=124, FF=662, GG=435, DD=156}

    //Object remove(Object key):移除指定key的key-value对,并返回value
    Object value = map.remove("GG");
    System.out.println(value);//435
    System.out.println(map);//{AA=123, ZZ=261, CC=110, RR=124, FF=662, DD=156}

    //void clear():清空当前map中的所有数据
    map.clear();
    System.out.println(map.size());//0  与map = null操作不同
    System.out.println(map);//{}
}


复制代码

3.2 Operation of element query:

  • Object get(Object key): Get the value corresponding to the specified key
  • boolean containsKey(Object key): Whether to contain the specified key
  • boolean containsValue(Object value): Whether to contain the specified value
  • int size(): Returns the number of key-value pairs in the map
  • boolean isEmpty(): Determine whether the current map is empty
  • boolean equals(Object obj): Determine whether the current map and the parameter object obj are equal

Code example:

@Test
public void test2() {
    Map map = new HashMap();
    map.put("AA", 123);
    map.put("ZZ", 251);
    map.put("CC", 110);
    map.put("RR", 124);
    map.put("FF", 662);
    System.out.println(map);//{AA=123, ZZ=251, CC=110, RR=124, FF=662}
    //Object get(Object key):获取指定key对应的value
    System.out.println(map.get("AA"));//123

    //boolean containsKey(Object key):是否包含指定的key
    System.out.println(map.containsKey("ZZ"));//true

    //boolean containsValue(Object value):是否包含指定的value
    System.out.println(map.containsValue(123));//true

    //int size():返回map中key-value对的个数
    System.out.println(map.size());//5

    //boolean isEmpty():判断当前map是否为空
    System.out.println(map.isEmpty());//false

    //boolean equals(Object obj):判断当前map和参数对象obj是否相等
    Map map1 = new HashMap();
    map1.put("AA", 123);
    map1.put("ZZ", 251);
    map1.put("CC", 110);
    map1.put("RR", 124);
    map1.put("FF", 662);
    System.out.println(map.equals(map1));//true
}


复制代码

3.3 Method of meta view operation:

  • Set keySet(): Returns the Set collection composed of all keys
  • Collection values(): Returns the Collection set composed of all values
  • Set entrySet(): Returns the Set collection composed of all key-value pairs

Code example:

@Test
public void test3() {
    Map map = new HashMap();
    map.put("AA", 123);
    map.put("ZZ", 251);
    map.put("CC", 110);
    map.put("RR", 124);
    map.put("FF", 662);
    System.out.println(map);//{AA=123, ZZ=251, CC=110, RR=124, FF=662}
    //遍历所有的key集:Set keySet():返回所有key构成的Set集合
    Set set = map.keySet();
    Iterator iterator = set.iterator();
    while (iterator.hasNext()) {
        System.out.println(iterator.next());
    }
    System.out.println("--------------");
    //遍历所有的value集:Collection values():返回所有value构成的Collection集合
    Collection values = map.values();
    for (Object obj :
         values) {
        System.out.println(obj);
    }
    System.out.println("---------------");
    //Set entrySet():返回所有key-value对构成的Set集合
    Set entrySet = map.entrySet();
    Iterator iterator1 = entrySet.iterator();
    //方式一:
    while (iterator1.hasNext()) {
        Object obj = iterator1.next();
        //entrySet集合中的元素都是entry
        Map.Entry entry = (Map.Entry) obj;
        System.out.println(entry.getKey() + "-->" + entry.getValue());
    }
    System.out.println("--------------");

    //方式二:
    Set keySet = map.keySet();
    Iterator iterator2 = keySet.iterator();
    while (iterator2.hasNext()) {
        Object key = iterator2.next();
        Object value = map.get(key);
        System.out.println(key + "==" + value);
    }
}


复制代码

Summary: Common methods:

  • Add to:put(Object key,Object value)
  • delete:remove(Object key)
  • Revise:put(Object key,Object value)
  • Inquire:get(Object key)
  • length:size()
  • traverse  :  keySet() // values()entrySet()

4. Memory structure description: (difficult point)

4.1 HashMap implementation principle in JDK 7.0:

4.1.1 Storage structure of HashMap:

JDK 7.0 and previous versions: HashMap is an array + linked list structure (address linked list method)

After JDK 8.0 version: HashMap is an array + linked list + red-black tree implementation

4.1.2 Object creation and addition process:

HashMap map = new HashMap():

After instantiation, the underlying creates a one-dimensional array of length 16  Entry[] table.

​ ...may have executed multiple puts...

map.put(key1,value1):

  • First, call  hashCode() the calculation key1 hash value of the class where key1 belongs to. After the hash value is calculated by a certain algorithm, the storage location in the Entry array is obtained.
  • If the data at this position is empty, key1-value1 is added successfully at this time. ---- Situation 1
  • If the data at this location is not empty, (meaning that there is one or more data (in the form of a linked list) at this location), compare key1 with the hash value of one or more existing data:
    • If the hash value of key1 is different from the hash value of the existing data, then key1-value1 is added successfully. ---- Situation 2
    • If the hash value of key1 is the same as the hash value of an existing data (key2-value2), continue to compare: call the equals(key2) method of the class where key1 is located, and compare:
      • If  equals() it returns false: key1-value1 is added successfully at this time. ---- Situation 3
      • If  equals() true: replace value2 with value1.

Supplement: Regarding case 2 and case 3: At this time, key1-value1 and the original data are stored in the form of a linked list.

In the process of continuous addition, the problem of capacity expansion will be involved. When the critical value is exceeded (and the location to be stored is not empty), the capacity will be expanded. The default expansion method: expand the capacity to twice the original capacity, and copy the original data over.

4.1.3 Expansion of HashMap

When there are more and more elements in the HashMap, the probability of hash conflicts becomes higher and higher, because the length of the array is fixed. Therefore, in order to improve the query efficiency, it is necessary to expand the HashMap array, and after the HashMap array is expanded, the data in the original array must recalculate its position in the new array and put it in. This is resize.

4.1.4 HashMap Expansion Timing

When the number of elements in the HashMap exceeds the size of the array (the total length of the array, not the number in the array) * loadFactor, the array will be expanded. The default value of loadFactor ( ) is 0.75, which is a compromise value DEFAULT_LOAD_ FACTOR. That is to say, by default, the array size ( DEFAULT INITIAL CAPACITY) is 16, then when the number of elements in the HashMap exceeds 16 * 0.75=12 (this value is the threshold value in the code, also called the critical value), the array The size is expanded to 2 * 16 = 32, that is, doubled, and then recalculates the position of each element in the array, and this is a very performance-consuming operation, so if we have already predicted the number of elements in the HashMap, then pre- Setting the number of elements can effectively improve the performance of HashMap.

4.2 The underlying implementation principle of HashMap in JDK 8.0:

4.2.1 Storage structure of HashMap:

The internal storage structure of HashMap is actually a combination of array + linked list + red-black tree.

4.2.2 The process of adding elements to HashMap:

When instantiating a HashMap, initialCapacity and loadFactor will be initialized. When putting the first pair of mapping relationships, the system will create a Node array with a length of initialCapacity. This length is called capacity in the hash table. In this The location where elements can be stored in the array is called a "bucket". Each bucket has its own index, and the system can quickly find elements in the bucket based on the index.

Each bucket stores an element, that is, a Node object, but each Noe object can carry a reference variable next to point to the next element. Therefore, in a bucket, it is possible to generate a Node chain. It may also be a TreeNode object, each Tree node object can have two leaf nodes left and right, therefore, in a bucket, it is possible to generate a TreeNode tree. The newly added element is used as the last of the linked list, or the leaf node of the tree.

4.2.3 The expansion mechanism of HashMap:

  • When the number of objects in one of the chains in HashMapl does not reach 8, it is the same as the expansion method before JDK 7.0.
  • When the number of objects in one of the chains in HashMapl reaches 8, if the capacity does not reach 64 at this time, then HashMap will expand the capacity first. If it has reached 64, then the chain will become a tree, and the node type is determined by Node becomes Tree Node type. Of course, if the number of nodes in the tree is judged to be less than 6 in the next resize method after the mapping relationship is removed, the tree will be converted into a linked list again.

4.2.4 Changes at the bottom of HashMap between JDK 8.0 and JDK 7.0:

  1. new HashMap(): The bottom layer did not create an array of length 16

  2. The underlying array of JDK 8.0 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.0 is only: array + linked list. The underlying structure in JDK 8.0: array + linked list + red-black tree.

    • When forming a linked list, it is up and down (jdk7: new elements point to old elements. jdk8: old elements point to new elements)
    • When the number of elements at a certain index position of the array in the form of a linked list is > 8 and the length of the current array is > 64, all the data at this index position will be stored in a red-black tree instead.

4.3 Description of the properties of the typical properties of the bottom layer of HashMap:

  • DEFAULT_INITIAL_CAPACITY : The default capacity of HashMap, 16
  • DEFAULT_LOAD_FACTOR: Default load factor for HashMap: 0.75
  • threshold: Critical value of expansion, = capacity * fill factor: 16 * 0.75 => 12
  • TREEIFY_THRESHOLD: The length of the linked list in the Bucket is greater than the default value, and it is converted into a red-black tree: introduced by JDK 8.0
  • MIN_TREEIFY_CAPACITY: The minimum hash table capacity when the Node in the bucket is treed: 64

4.4 The underlying implementation principle of LinkedHashMap

  • The underlying structure of LinkedHashMap is the same as that of HashMap, because LinkedHashMap inherits from HashMap.
  • The difference is that LinkedHashMap provides Entry inside, replacing Node in HashMap.
  • Similar to Linkedhash Set, LinkedHashMap can maintain the iteration order of Map: the iteration order is consistent with the insertion order of Key-value pairs

Internal class Node source code in HashMap:

static class Node<K,V> implements Map.Entry<K,V>{
    final int hash;
    final K key;
    V value;
    Node<K,V> next;
}


复制代码

Internal class Entry source code in LinkedHashM:

static class Entry<K,V> extends HashMap.Node<K,V> {
    Entry<K,V> before, after;//能够记录添加的元素的先后顺序
    Entry(int hash, K key, V value, Node<K,V> next) {
        super(hash, key, value, next);
    }
}


复制代码

5. Use of TreeMap

Add key-value to TreeMap, requiring that the key must be created by the same class. Objects must be sorted according to the key: natural sorting, custom sorting

Code example:

//自然排序
@Test
public void test() {
    TreeMap map = new TreeMap();
    User u1 = new User("Tom", 23);
    User u2 = new User("Jarry", 18);
    User u3 = new User("Bruce", 56);
    User u4 = new User("Davie", 23);

    map.put(u1, 98);
    map.put(u2, 16);
    map.put(u3, 92);
    map.put(u4, 100);

    Set entrySet = map.entrySet();
    Iterator iterator = entrySet.iterator();
    while (iterator.hasNext()) {
        Object obj = iterator.next();
        Map.Entry entry = (Map.Entry) obj;
        System.out.println(entry.getKey() + "=" + entry.getValue());
    }
}

//定制排序:按照年龄大小排
@Test
public void test2() {
    TreeMap map = new TreeMap(new Comparator() {
        @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());
            }
            throw new RuntimeException("输入数据类型错误");
        }
    });
    User u1 = new User("Tom", 23);
    User u2 = new User("Jarry", 18);
    User u3 = new User("Bruce", 56);
    User u4 = new User("Davie", 23);

    map.put(u1, 98);
    map.put(u2, 16);
    map.put(u3, 92);
    map.put(u4, 100);

    Set entrySet = map.entrySet();
    Iterator iterator = entrySet.iterator();
    while (iterator.hasNext()) {
        Object obj = iterator.next();
        Map.Entry entry = (Map.Entry) obj;
        System.out.println(entry.getKey() + "=" + entry.getValue());
    }
}


复制代码

6. Use Properties to read the configuration file

Code example:

//Properties:常用来处理配置文件。key和value都是String类型
public static void main(String[] args)  {
    FileInputStream fis = null;
    try {
        Properties pros = new Properties();

        fis = new FileInputStream("jdbc.properties");
        pros.load(fis);//加载流对应的文件

        String name = pros.getProperty("name");
        String password = pros.getProperty("password");

        System.out.println("name = " + name + ", password = " + password);
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if(fis != null){
            try {
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

}


复制代码

7. Interview questions

  1. The underlying implementation principle of HashMap?
  2. Similarities and differences between HashMap and Hashtable?
  3. Similarities and differences between CurrentHashMap and Hashtable?
  4. The size of the load factor value, the impact on the HashMap?
    • The size of the load factor determines the data density of the HashMap.
    • The greater the load factor, the greater the density, the higher the probability of collision, and the easier the linked list in the array is to grow, resulting in an increase in the number of comparisons during query or insertion and performance degradation
    • The smaller the load factor, the easier it is to trigger expansion, and the smaller the data density, which means that the probability of collision is smaller, the linked list in the array is shorter, and the number of comparisons during query and insertion is smaller, and the performance will be higher. . But it will waste a certain content space. Moreover, frequent expansion will also affect performance. It is recommended to initialize and preset a larger space
    • According to the reference and research experience of other languages, it will be considered to set the load factor to 0.7~0.75. At this time, the average retrieval length is close to a constant.

Seven, the use of Collection tools

1. Function:

Collections is a tool class for manipulating collections such as Set, Lit and Map

Collections provides a series of static methods to sort, query and modify collection elements, and also provides methods to set immutable collection objects and realize synchronization control on collection objects.

2. Common methods:

2.1 Sorting operation

  • reverse(List): Reverse the order of the elements in the List
  • shuffle(List): Randomly sort the elements of the List collection
  • sort(List): Sort the elements of the specified List collection in ascending order according to the natural order of the elements
  • sort(List,Comparator): Sort the List collection elements according to the order generated by the specified Comparator
  • swap(List,int, int): Exchange the element at i and the element at j in the specified list collection

Code example:

@Test
public void test1() {
    List list = new ArrayList();
    list.add(123);
    list.add(43);
    list.add(765);
    list.add(-97);
    list.add(0);
    System.out.println(list);//[123, 43, 765, -97, 0]

    //reverse(List):反转 List 中元素的顺序
    Collections.reverse(list);
    System.out.println(list);//[0, -97, 765, 43, 123]

    //shuffle(List):对 List 集合元素进行随机排序
    Collections.shuffle(list);
    System.out.println(list);//[765, -97, 123, 0, 43]

    //sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序
    Collections.sort(list);
    System.out.println(list);//[-97, 0, 43, 123, 765]

    //swap(List,int, int):将指定 list 集合中的 i 处元素和 j 处元素进行交换
    Collections.swap(list,1,4);
    System.out.println(list);//[-97, 765, 43, 123, 0]
}


复制代码

2.2 Find and replace

  • Object max(Collection): Returns the largest element in the given collection according to the natural order of the elements
  • Object max(Collection,Comparator): According to the order specified by Comparator, returns the largest element in the given collection
  • 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): Copy the contents of src to dest
  • boolean replaceAll(List list,Object oldVal,Object newVal): Replace all old values ​​of the List object with new values

Code example:

@Test
public void test2(){
    List list = new ArrayList();
    list.add(123);
    list.add(123);
    list.add(123);
    list.add(43);
    list.add(765);
    list.add(-97);
    list.add(0);
    System.out.println(list);//[123, 43, 765, -97, 0]
    //Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
    Comparable max = Collections.max(list);
    System.out.println(max);//765

    //Object min(Collection)
    Comparable min = Collections.min(list);
    System.out.println(min);//-97

    //int frequency(Collection,Object):返回指定集合中指定元素的出现次数
    int frequency = Collections.frequency(list,123);
    System.out.println(frequency);//3

    //void copy(List dest,List src):将src中的内容复制到dest中
    List dest = Arrays.asList(new Object[list.size()]);
    System.out.println(dest.size());//7
    Collections.copy(dest,list);
    System.out.println(dest);//[123, 123, 123, 43, 765, -97, 0]
    //boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换 List 对象的所有旧值
}


复制代码

2.3 Synchronous control

The Collections class provides multiple  synchronizedXxx() methods, which can wrap the specified collection into a thread-synchronized collection, so as to solve the thread safety problem when multiple threads access the collection concurrently

Code example:

@Test
public void test3() {
    List list = new ArrayList();
    list.add(123);
    list.add(123);
    list.add(123);
    list.add(43);
    list.add(765);
    list.add(-97);
    list.add(0);
    System.out.println(list);//[123, 43, 765, -97, 0]
    //返回的list1即为线程安全的List
    List list1 = Collections.synchronizedList(list);
    System.out.println(list1);//[123, 123, 123, 43, 765, -97, 0]
}


复制代码

8. Brief description of data structure

It is planned to open a series in the future to talk about the data structure.

1. Data structure overview

Data Structure (Data Structure is a discipline closely related to computer hardware and software. Its research focus is on how to organize and store data in the computer and use it efficiently in the field of computer programming. The content involved Including: logical relationship of data, data storage structure, sorting algorithm (Algorithm), search (or search), etc.

2. Understanding of data structures and algorithms

Whether the program can complete the predetermined task quickly and efficiently depends on whether the data structure is selected correctly, and whether the program can solve the problem clearly and correctly depends on the algorithm.

So everyone thinks: "Algorithms + Data Structures = Programs" (from: Nicklaus Wirth, father of Pascal)

Summary: Algorithms are designed to solve practical problems, and data structures are the problem carriers that algorithms need to deal with.

3. Research object of data structure

3.1 Logical structure between data

set structure

One-to-one: linear structure

One-to-many: tree structure

Many-to-many: graph structure

3.2 Data storage structure:

Linear list (sequence list, linked list, stack, queue) tree diagram

Explanation: It is customary to regard sequential lists and linked lists as basic data structures (or real data structures). It is customary to regard stacks, queues, trees, and graphs as abstract data types, referred to as ADT

4. Mind map:

Mind map download address: gitee.com/realbruce/b…

Data Structures and Algorithms:


 

 

Guess you like

Origin blog.csdn.net/SFalS/article/details/127332202
Recommended