Study Notes: Dark Horse Programmer Java-Advanced Chapter (Part 3)

Java language introduction to mastery chapters

  1. Study notes: Java-Basics (Part 1)_ljtxy.love’s blog-CSDN blog
  2. Study Notes: Java-Intermediate (Part 2)_ljtxy.love’s Blog-CSDN Blog
  3. Study Notes: Java-Advanced Chapter (Part 3)_ljtxy.love’s Blog-CSDN Blog
  4. Study Notes: Java-Advanced Chapter (1) (Part 4)_ljtxy.love's Blog-CSDN Blog
  5. Study Notes: Java-Advanced Chapter (2) (Part 5)_ljtxy.love’s Blog-CSDN Blog
  6. Study Notes: New Features of Java8_ljtxy.love’s Blog-CSDN Blog

Article directory

17. Collection class

Summary of notes: see each section

17.1 Collection Architecture

Summary of notes:

  1. Overview: Collections are divided into single-column collections and double-column collections .

    image-20230321141847845

  2. Features:

    image-20230421090605057

  3. Single column collection:

    • List series collection: ordered , repeatable collection
    • Set series collection: unordered , non-repeatable collection
    • Details: see each summary
  4. Two-column collection:

    • HashMap: Based on hash table implementation, can store null keys and null values , and does not guarantee the order of elements.
    • TreeMap: Based on red-black tree implementation, sorted according to the natural order of keys or a custom comparator. Null keys are not allowed, but null values ​​are allowed.
  5. Single column collection application scenarios:

    image-20230421161119362

17.1.1 Overview

A collection class in Java is a container used to store, manipulate and manage a set of objects. Sets can be classified into single-column sets and double-column sets.

image-20230321141743728

In Java, a single-column collection refers to a collection that can only store a sequence of elements , such as List, Set, Queue, etc. Double-column collections refer to collections that can store key-value pairs , such as Maps, etc. Single-column collections and dual-column collections differ in the way and purpose of saving and manipulating data.

17.1.2 Single column collection

Single-column collections are divided into: List series collections and Set series collections

image-20230321141847845

Replenish:

  • List series collection: an ordered , repeatable collection. Elements can be accessed by index and duplicate elements can be stored
  • Set series collection: unordered , non-repeatable collection. Elements cannot be accessed through indexes, and duplicate elements cannot be stored.

17.1.3 Two-column collections

​ A two-column collection in Java refers to a collection that can store key-value pair data structures, also called a mapping table or associative array.

image-20230424194516589

Replenish:

  • Two-column collection, one key corresponds to one value
  • Keys cannot be repeated, values ​​can be repeated

17.2Collection

Summary of notes:

  1. Overview: Collection is the ancestor interface of single-column collections. Its functions can be inherited and used by all single-column collections .

  2. Common member methods; add , clear , remove , contains , isEmpty , size

  3. traversal mode

    • iterators:

      1. Overview: Iterator is a special traversal method for collections . Iterators do not rely on indexes when traversing collections.

      2. Usage: Iterators need to master three methods

        while (it.hasNext()) {
                   
                    
            String s = it.next(); 
            System.out.println(s);
        }
        
      3. detail:

        1. When there are no elements in the iterator or element traversal is completed , and the it.next() method is called again, an error NoSuchElementException will be reported.
      4. After the iterator is traversed, the pointer will not be reset.

        1. The next method can only be used once in the loop (because the next method will do two things, namely getting the element and moving the pointer)
      5. When traversing the iterator, you cannot use collection methods to add or delete, otherwise a ConcurrentModificationException error will be reported.

  4. Principle: You can refer to the knowledge gas station

  • Enhanced for loop:

    1. Overview: Its internal principle is an Iterator iterator

    2. Format:

         for(集合/数组中元素的数据类型 变量名 :  集合/数组名) {
               
               
         // 已经将当前遍历到的元素封装到变量中了,直接使用变量即可
         }
         //例如
         for(string s : list){
               
               
             System.out.println(s);
         }
      
    3. Note: **Modifying the variables in enhanced for will not change the original data in the collection, **because it is assigned through a third-party variable

  • lambda expression

    1. Overview: A simpler, more direct way to traverse a collection

    2. Format:

         forEach(Consumer<? super T> action)
         //例如
         coll.forEach(s -> System.out.println(s));
      
    3. The underlying principle: In fact, it will traverse the collection by itself and obtain each element in turn . Pass each element obtained to the accept method below. s represents each data in the set in turn

17.2.1 Overview

Collection is the ancestor interface of single-column collections. Its functions can be inherited and used by all single-column collections.

Notice:

collection is an interface, we cannot create its objects directly. So, now when we learn his methods, we can only create objects of his implementation class

17.2.2 Common member methods

method name illustrate
boolean add(E e) Add element
boolean remove(Object o) Removes the specified element from the collection
boolean removeIf(Object o) Remove based on conditions
void clear() Clear elements from a collection
boolean contains(Object o) Determine whether the specified element exists in the collection
boolean isEmpty() Determine whether the collection is empty
int size() The length of the set, that is, the number of elements in the set

17.2.2.1add()

Collection<String> coll = new ArrayList<>();
coll.add("aaa");
coll.add("bbb");
coll.add("ccc");
System.out.println(coll);
  • If we want to add data to the List series collection, the method will always return true, because the List series allows repeated elements.
  • If we want to add data to the Set series collection, if the element to be added currently does not exist, the method returns true, indicating that the addition is successful. If the element currently to be added already exists, the method returns false, indicating that the addition failed. Because Set series collections do not allow duplication.

17.2.2.2clear()

Collection<String> coll = new ArrayList<>();
coll.clear();

17.2.2.3remove()

Collection<String> coll = new ArrayList<>();
System.out.println(coll.remove("aaa"));
System.out.println(coll);
  • Because Collection defines common methods, it cannot be deleted through indexing at this time. Deletion can only be done via the element's object.
  • The method will have a boolean return value, which returns true if the deletion is successful and false if the deletion fails.
  • If the element to be deleted does not exist, the deletion will fail.

17.2.2.4contains()

Collection<String> coll = new ArrayList<>(); 
boolean result1 = coll.contains("bbb");
System.out.println(result1);
  • The bottom layer relies on the equals method to determine whether it exists.
  • Therefore, if a custom object is stored in the collection and you want to use the contains method to determine whether it is included, then in the javabean class, you must override the equals method.

17.2.2.5isEmpty()

Collection<String> coll = new ArrayList<>(); 
boolean result2 = coll.isEmpty();
System.out.println(result2);//false

17.2.2.6size()

Collection<String> coll = new ArrayList<>(); 
coll.add("ddd");
int size = coll.size();
System.out.println(size);//3

17.2.2.7 Case – Student Query

//1.创建集合的对象
Collection<Student> coll = new ArrayList<>();

//2.创建三个学生对象
Student s1 = new Student("zhangsan",23);
Student s2 = new Student("lisi",24);
Student s3 = new Student("wangwu",25);


//3.把学生对象添加到集合当中
coll.add(s1);
coll.add(s2);
coll.add(s3);

//4.判断集合中某一个学生对象是否包含
Student s4 = new Student("zhangsan",23);
//因为contains方法在底层依赖equals方法判断对象是否一致的。
//如果存的是自定义对象,没有重写equals方法,那么默认使用Object类中的equals方法进行判断,而Object类中equals方法,依赖地址值进行判断。
//需求:如果同姓名和同年龄,就认为是同一个学生。
//所以,需要在自定义的Javabean类中,重写equals方法就可以了。
System.out.println(coll.contains(s4));

17.2.3 Traversal mode

17.2.3.1 Iterators

Overview: The class of iterator in Java is Iterator, and iterator is a dedicated traversal method for collections.

  • Collection collection gets iterator

    image-20230420154333383

  • Common member methods in Iterator

    image-20230420154407344

Code example:

public class IteratorDemo1 {
    
    
    public static void main(String[] args) {
    
    
        //创建集合对象
        Collection<String> c = new ArrayList<>();

        //添加元素
        c.add("hello");
        c.add("world");
        c.add("java");
        c.add("javaee");

        //Iterator<E> iterator():返回此集合中元素的迭代器,通过集合的iterator()方法得到
        Iterator<String> it = c.iterator(); // 1.获取迭代器

        //用while循环改进元素的判断和获取
        while (it.hasNext()) {
    
     // 2.判断是否有元素
            String s = it.next(); // 3.获取元素 // 4.移动指针
            System.out.println(s);
        }
    }
}

illustrate:

Iterator running process:

  1. Create pointer
  2. Determine whether there is an element
  3. Get element
  4. Move pointer

Notice:

1. When there are no elements in the iterator or element traversal is completed , and the it.next() method is called again, an error NoSuchElementException will be reported.

2. After the iterator is traversed, the pointer will not be reset.

3. The next method can only be used once in the loop (because the next method will do two things, namely getting the element and moving the pointer)

4. When traversing the iterator, you cannot use the collection method to add or delete, otherwise an error ConcurrentModificationException will be reported.

iterator delete

​ void remove(): Delete the element currently pointed to by the iterator object

Example:

public class IteratorDemo2 {
    
    
    public static void main(String[] args) {
    
    
        ArrayList<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("b");
        list.add("c");
        list.add("d");

        Iterator<String> it = list.iterator();
        while(it.hasNext()){
    
    
            String s = it.next();
            if("b".equals(s)){
    
    
                //指向谁,那么此时就删除谁.
                it.remove();
            }
        }
        System.out.println(list);
    }
}

Notice:

When traversing the iterator, you cannot use collection methods to add or delete, otherwise a ConcurrentModificationException error will be reported.

17.2.3.2 Enhanced for loop

Format:

for(集合/数组中元素的数据类型 变量名 :  集合/数组名) {
    
    
// 已经将当前遍历到的元素封装到变量中了,直接使用变量即可
}
//例如
for(string s : list){
    
    
    System.out.println(s);
}

Example:

public class MyCollectonDemo1 {
    
    
    public static void main(String[] args) {
    
    
        ArrayList<String> list =  new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
        list.add("e");
        list.add("f");

        //1,数据类型一定是集合或者数组中元素的类型
        //2,str仅仅是一个变量名而已,在循环的过程中,依次表示集合或者数组中的每一个元素
        //3,list就是要遍历的集合或者数组
        for(String str : list){
    
    
            System.out.println(str);
        }
    }
}

Notice:

**Modifying the variables in the enhanced for will not change the original data in the collection, **because it is assigned through a third-party variable

image-20230420160153625

17.2.3.3Lambda expression

Overview: Thanks to the new technology Lambda expression started in JDK8, it provides a simpler and more direct way to traverse a collection.

Common member methods:

image-20230420160321849

Example:

Collection<String> coll = new ArrayList<>();
coll.add("zhangsan");
coll.add("lisi");
coll.add("wangwu");
coll.forEach(s -> System.out.println(s));

Notice:

The underlying principle: In fact, it will traverse the collection by itself and obtain each element in turn. Pass each element obtained to the accept method below. s represents each data in the set in turn

image-20230420160647933

17.3List collection

Summary of notes:

  1. Overview: List is one of the commonly used collection types in Java, used to store ordered and repeatable sequences of elements.

  2. Common member methods: add , remove , set , get

  3. Traversal method: see Collection traversal method

    image-20230328210559638

17.3.1 Overview

image-20230420161417186

​ The methods of Collection are inherited by List. The methods of List are inherited by List. Because List collection has index, it has many more index operation methods. Listing collections has indexes, so there are many more methods for index operations.

  • Ordered set, order here refers to the order of access
  • Users have precise control over where each element in the list is inserted, users can access elements via integer indexes, and search for elements in the list
  • Unlike Set collections, Lists generally allow duplicate elements

Features

  • Orderly access
  • Can be repeated
  • There is an index

17.3.2 Common member methods

method name describe
E remove(int index) Delete the element at the specified index and return the deleted element
void add(int index,E element) Inserts the specified element at the specified position in this collection
E set(int index,E element) Modify the element at the specified index and return the modified element
E get(int index) Returns the element at the specified index

17.3.2.1add()

List<String> list = new ArrayList<>();
list.add("aaa");
list.add("bbb");//1
list.add("ccc");
// 或者
list.add(1,"QQQ") // 在此集合中的指定位置插入指定的元素

Notice:

The elements on the original index will be moved back in sequence.

17.3.2.2remove()

List<String> list = new ArrayList<>();
String remove = list.remove(0); //删除指定索引处的元素,返回被删除的元素
System.out.println(remove);//aaa

17.3.2.3set()

List<String> list = new ArrayList<>();
String result = list.set(0, "QQQ"); //修改指定索引处的元素,返回被修改的元素
System.out.println(result);

17.3.2.4get()

List<String> list = new ArrayList<>();
String s = list.get(0); //返回指定索引处的元素
System.out.println(s);

17.3.2.5 Case – Basic Operation

public class MyListDemo {
    
    
    public static void main(String[] args) {
    
    
        List<String> list = new ArrayList<>();
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
        //method1(list);
        //method2(list);
        //method3(list);
        //method4(list);
    }

    private static void method4(List<String> list) {
    
    
        //        E get(int index)		返回指定索引处的元素
        String s = list.get(0);
        System.out.println(s);
    }

    private static void method3(List<String> list) {
    
    
        //        E set(int index,E element)	修改指定索引处的元素,返回被修改的元素
        //被替换的那个元素,在集合中就不存在了.
        String result = list.set(0, "qqq");
        System.out.println(result);
        System.out.println(list);
    }

    private static void method2(List<String> list) {
    
    
        //        E remove(int index)		删除指定索引处的元素,返回被删除的元素
        //在List集合中有两个删除的方法
        //第一个 删除指定的元素,返回值表示当前元素是否删除成功
        //第二个 删除指定索引的元素,返回值表示实际删除的元素
        String s = list.remove(0);
        System.out.println(s);
        System.out.println(list);
    }

    private static void method1(List<String> list) {
    
    
        //        void add(int index,E element)	在此集合中的指定位置插入指定的元素
        //原来位置上的元素往后挪一个索引.
        list.add(0,"qqq");
        System.out.println(list);
    }
}

17.3.3 Traversal mode

Description: For this traversal method, please refer to Collection traversal method.

image-20230328210559638

Basic use case

package com.itheima.a02mylist;

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

public class A03_ListDemo3 {
    
    
    public static void main(String[] args) {
    
    
        /*
            List系列集合的五种遍历方式:
                1.迭代器
                2.列表迭代器
                3.增强for
                4.Lambda表达式
                5.普通for循环
         */


        //创建集合并添加元素
        List<String> list = new ArrayList<>();
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");

        //1.迭代器
        Iterator<String> it = list.iterator();
        while(it.hasNext()){
    
    
            String str = it.next();
            System.out.println(str);
        }


        //2.增强for
        //下面的变量s,其实就是一个第三方的变量而已。
        //在循环的过程中,依次表示集合中的每一个元素
       for (String s : list) {
    
    
            System.out.println(s);
        }

        //3.Lambda表达式
        //forEach方法的底层其实就是一个循环遍历,依次得到集合中的每一个元素
        //并把每一个元素传递给下面的accept方法
        //accept方法的形参s,依次表示集合中的每一个元素
        list.forEach(s->System.out.println(s) );


        //4.普通for循环
        //size方法跟get方法还有循环结合的方式,利用索引获取到集合中的每一个元素
        for (int i = 0; i < list.size(); i++) {
    
    
            //i:依次表示集合中的每一个索引
            String s = list.get(i);
            System.out.println(s);
        }

        // 5.列表迭代器
        //获取一个列表迭代器的对象,里面的指针默认也是指向0索引的

        //额外添加了一个方法:在遍历的过程中,可以添加元素
        ListIterator<String> it = list.listIterator();
        while(it.hasNext()){
    
    
            String str = it.next();
            if("bbb".equals(str)){
    
    
                //qqq
                it.add("qqq");
            }
        }
        System.out.println(list);
    }
}

17.4ArrayList set

Summary of notes:

  1. Overview; ArrayList is a class in Java that implements the List interface and is a collection class based on dynamic array implementation.
  2. Common member methods:
    • Constructor: ArrayList()
    • Member methods: add , remove , set , get , size
  3. The underlying principle:
    • Using the collection created with empty parameters , create an array with a default length of 0 at the bottom
    • When adding the first element, the bottom layer will create a new array with a length of 10. When it is full , it will expand by 1.5 times.
    • If multiple elements are added at one time and cannot fit 1.5 times, the length of the newly created array shall be subject to the actual length.

17.4.1 Overview

  • what is a collection

    ​ Provide a storage model with variable storage space, and the stored data capacity can change

  • Features of ArrayList Collection

    The length can vary and can only store reference data types.

  • Generic usage

    ​ Used to constrain the data type of elements stored in the collection

17.4.2 Common member methods

17.4.2.1 Construction methods

method name illustrate
public ArrayList() Create an empty collection object

17.4.2.2 Member methods

method name illustrate
public boolean add(element to be added) Appends the specified elements to the end of this collection
public boolean remove(element to be deleted) Delete the specified element, and the return value indicates whether the deletion is successful.
public E remove(int index) Delete the element at the specified index and return the deleted element
public E set(int index,E element) Modify the element at the specified index and return the modified element
public E get(int index) Returns the element at the specified index
public int size() Returns the number of elements in the collection

Example:

public class ArrayListDemo02 {
    
    
    public static void main(String[] args) {
    
    
        //创建集合
        ArrayList<String> array = new ArrayList<String>();

        //添加元素
        array.add("hello");
        array.add("world");
        array.add("java");

        //public boolean remove(Object o):删除指定的元素,返回删除是否成功
        //        System.out.println(array.remove("world"));
        //        System.out.println(array.remove("javaee"));

        //public E remove(int index):删除指定索引处的元素,返回被删除的元素
        //        System.out.println(array.remove(1));

        //IndexOutOfBoundsException
        //        System.out.println(array.remove(3));

        //public E set(int index,E element):修改指定索引处的元素,返回被修改的元素
        //        System.out.println(array.set(1,"javaee"));

        //IndexOutOfBoundsException
        //        System.out.println(array.set(3,"javaee"));

        //public E get(int index):返回指定索引处的元素
        //        System.out.println(array.get(0));
        //        System.out.println(array.get(1));
        //        System.out.println(array.get(2));
        //System.out.println(array.get(3)); //?????? 自己测试

        //public int size():返回集合中的元素的个数
        System.out.println(array.size());

        //输出集合
        System.out.println("array:" + array);
    }
}

17.4.3 Underlying principles

image-20230328211534089

illustrate:

  • When an array of length m (m<=10) is added with less than n (n<10) elements, the actual length of the underlying array is 10

  • When an array of length m (m<=10) is added with more than n (n>10) elements, the actual length of the underlying layer is n+10

  • When less than n (n<10) elements are added to an array with a length of m (m>10), the actual length of the underlying array is m*1.5

  • When an array of length m (m>10) is added with more than n (n>10) elements, the actual length of the underlying array is m+n

Source code analysis:

transient Object[] elementData; // non-private to simplify nested class access

The bottom layer of ArrayList is an array

add an element

image-20230329090130680

Add ten elements

image-20230329090105856

17.5LinkedList collection

Summary of notes:

  1. Overview: LinkedList is a doubly linked list implementation class in the Java collection framework , which can be used to store an ordered set of elements. LinkedList itself has many unique APIs that directly operate the first and last elements.
  2. Common member methods: addFirst , addLast , getFirst , getLast , removeFirst , removeLast
  3. The underlying principle: The underlying data structure is a double linked list , which is slow to query and fast to add and delete . However, if you operate on the first and last elements , the speed is also extremely fast.

17.5.1 Overview

LinkedList is a doubly linked list implementation class in the Java collection framework, which can be used to store an ordered set of elements . The elements of LinkedList are connected together through a linked list, and each element contains a reference to the previous element and the next element. Therefore, the time complexity of inserting and deleting elements is O(1 ), while the time complexity of randomly accessing elements is O(n)**, where n is the number of elements in the LinkedList.

17.5.2 Common member methods

method name illustrate
public void addFirst(E e) Inserts the specified element at the beginning of the list
public void addLast(E e) Appends the specified elements to the end of this list
public E getFirst() Returns the first element in this list
public E getLast() Returns the last element in this list
public E removeFirst() Removes and returns the first element from this list
public E removeLast() Removes and returns the last element from this list

Example:

public class MyLinkedListDemo4 {
    
    
    public static void main(String[] args) {
    
    
        LinkedList<String> list = new LinkedList<>();
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
//        public void addFirst(E e)	在该列表开头插入指定的元素
        //method1(list);

//        public void addLast(E e)	将指定的元素追加到此列表的末尾
        //method2(list);

//        public E getFirst()		返回此列表中的第一个元素
//        public E getLast()		返回此列表中的最后一个元素
        //method3(list);

//        public E removeFirst()		从此列表中删除并返回第一个元素
//        public E removeLast()		从此列表中删除并返回最后一个元素
        //method4(list);
      
    }

    private static void method4(LinkedList<String> list) {
    
    
        String first = list.removeFirst();
        System.out.println(first);

        String last = list.removeLast();
        System.out.println(last);

        System.out.println(list);
    }

    private static void method3(LinkedList<String> list) {
    
    
        String first = list.getFirst();
        String last = list.getLast();
        System.out.println(first);
        System.out.println(last);
    }

    private static void method2(LinkedList<String> list) {
    
    
        list.addLast("www");
        System.out.println(list);
    }

    private static void method1(LinkedList<String> list) {
    
    
        list.addFirst("qqq");
        System.out.println(list);
    }
}

17.5.3 Underlying principles

image-20230420183312596

illustrate:

When adding the first element, the head node and tail node will point to the first element, and the front index and back index of the first element will be empty.

image-20230420184549301

illustrate:

When adding the nth element, the tail node will point to the nth element, and the index before the nth element is n-1, and the index after the nth element is empty.

17.6Set collection

Summary of notes:

  1. Overview: It is used to store unique elements

  2. Common member methods:

    method name illustrate
    boolean add(E e) Add element
    boolean remove(Object o) Removes the specified element from the collection
    boolean removeIf(Object o) Remove based on conditions
    void clear() Clear elements from a collection
    boolean contains(Object o) Determine whether the specified element exists in the collection
    boolean isEmpty() Determine whether the collection is empty
    int size() The length of the set, that is, the number of elements in the set
  3. Traversal method:

    image-20230328210559638

17.6.1 Overview

Set collection is a kind of Java collection framework. It is used to store unique elements and is unordered.

Features:

  • Out of order: The access sequence is inconsistent
  • No duplication: Duplication can be removed
  • No index: There is no indexed method, so you cannot use an ordinary for loop to traverse, nor can you obtain elements through the index.

17.6.2 Common member methods

method name illustrate
boolean add(E e) Add element
boolean remove(Object o) Removes the specified element from the collection
boolean removeIf(Object o) Remove based on conditions
void clear() Clear elements from a collection
boolean contains(Object o) Determine whether the specified element exists in the collection
boolean isEmpty() Determine whether the collection is empty
int size() The length of the set, that is, the number of elements in the set

illustrate:

The method of Set collection is basically the same as the API of Collection.

17.6.3 Traversal method

For this traversal method, please refer to Collection traversal method.

image-20230328210559638

Example:

public class A01_SetDemo1 {
    
    
    public static void main(String[] args) {
    
    
       /*
           利用Set系列的集合,添加字符串,并使用多种方式遍历。
            迭代器
            增强for
            Lambda表达式

        */


        //1.创建一个Set集合的对象
        Set<String> s = new HashSet<>();

        //2,添加元素
        //如果当前元素是第一次添加,那么可以添加成功,返回true
        //如果当前元素是第二次添加,那么添加失败,返回false
        s.add("张三");
        s.add("张三");
        s.add("李四");
        s.add("王五");

        //3.打印集合
        //无序
        System.out.println(s);//[李四, 张三, 王五]

        //迭代器遍历
      Iterator<String> it = s.iterator();
        while (it.hasNext()){
    
    
            String str = it.next();
            System.out.println(str);
        }


        //增强for
       for (String str : s) {
    
    
            System.out.println(str);
        }

        // Lambda表达式
        s.forEach( str->System.out.println(str));


    }
}

17.7HashSet collection

Summary of notes:

  1. 概述:它是基于哈希表实现的,可以存储无序的不重复的元素
  2. 底层原理:
    • HashSet集合底层采取哈希表存储数据
    • 哈希表是一种对于增删改查数据性能都较好的结构
  3. HashSet的三个问题;
    1. HashSet为什么存和取的顺序不一样?
      • 答案:链表中添加的数据不是按照指定的顺序存储的,数据在链表中的添加顺序不同,因此存和取的顺序不一样。
    2. HashSet为什么没有索引?
      • 答案:HashSet底层是由数组、链表、红黑树组成。此时,在1索引的位置下挂着一个链表,如此多的元素都为1索引,看起来不合适,因此就取消掉了索引的机制
    3. HashSet是利用什么机制保证数据去重的?
      • 答案:HashSet是根据HashCodeequals方法,进行判断元素是否相同

17.7.1概述

哈希值

  • 含义:对象的整数表现形式

    image-20230811231656961

  • 概述:

    • 根据hashCode方法算出来的int类型的整数
    • 该方法定义在Object类中,所有对象都可以调用,默认使用地址值进行计算
    • 一般情况下,会重写hashCode方法,利用对象内部的属性值计算哈希值

对象的哈希值特点:

  • 如果没有重写hashCode方法,不同对象计算出的哈希值是不同的

    image-20230421110116935

  • 如果已经重写hashcode方法,不同的对象只要属性值相同,计算出的哈希值就是一样的

    image-20230421110409579

  • 在小部分情况下,不同的属性值或者不同的地址值计算出来的哈希值也有可能一样。(哈希碰撞)

    image-20230421110529071

    int的取值范围用将近42亿中,如果此时创建50亿个对象,就有可能8亿hash值相同

示例:

        //1.创建对象
        Student s1 = new Student("zhangsan",23);
        Student s2 = new Student("zhangsan",23);

        //2.如果没有重写hashCode方法,不同对象计算出的哈希值是不同的
        //  如果已经重写hashcode方法,不同的对象只要属性值相同,计算出的哈希值就是一样的
        System.out.println(s1.hashCode());//-1461067292
        System.out.println(s2.hashCode());//-1461067292


        //在小部分情况下,不同的属性值或者不同的地址值计算出来的哈希值也有可能一样。
        //哈希碰撞
        System.out.println("abc".hashCode());//96354
        System.out.println("acD".hashCode());//96354

17.7.2底层原理

HashSet底层原理

  • HashSet集合底层采取哈希表存储数据
  • 哈希表是一种对于增删改查数据性能都较好的结构

哈希表组成

  • JDK8之前:数组+链表
  • JDK8开始:数组+链表+红黑树

JDK1.8以前:

image-20230811230228107

JDK1.8以后:

  • 节点个数少于等于8个

    ​ 数组 + 链表

  • 节点个数多于8个

    ​ 数组 + 红黑树

image-20230811225123292

说明:

加载因子:又叫HashSet的扩容时机

当数组内存储了16x0.75 = 12个元素时,次数数组的长度会扩容到原来的两倍,也就是32

当链表长度大于8而且数组长度大于等于64,链表就会转换为红黑树

底层流程:

image-20230421112253380

image-20230421112312925

17.7.3HashSet的三个问题

image-20230421112454766

说明:

​ 当遍历数组时,下标为1索引时,存储为链表。链表中添加的数据不是按照指定的顺序存储的,数据在链表中的添加顺序不同,因此存和取的顺序不一样。HashSet的存储索引是 通过hashCode方法算出来的int类型的整数。

image-20230421112904950

说明:

​ HashSet底层是又数组、链表、红黑树组成。此时,在1索引的位置下挂着一个链表,如此多的元素都为1索引,看起来不合适,因此就取消掉了索引的机制

image-20230421113123565

说明:

​ HashSet是根据HashCode和equals方法,进行判断元素是否相同,若相同则不会添加到数组、链表或者红黑树当中。因此,在像HashSet中添加自定义对象是,一定要记得重写HashCode和equals方法,让底层的Hash值是根据对象的属性来生成

示例:

public class HashSetDemo02 {
    
    
    public static void main(String[] args) {
    
    
        //创建HashSet集合对象
        HashSet<Student> hs = new HashSet<Student>();

        //创建学生对象
        Student s1 = new Student("林青霞", 30);
        Student s2 = new Student("张曼玉", 35);
        Student s3 = new Student("王祖贤", 33);

        Student s4 = new Student("王祖贤", 33);

        //把学生添加到集合
        hs.add(s1);
        hs.add(s2);
        hs.add(s3);
        hs.add(s4);

        //遍历集合(增强for)
        for (Student s : hs) {
    
    
            System.out.println(s.getName() + "," + s.getAge());
        }
    }
}

注意:

​ HashSet集合存储自定义类型元素,要想实现元素的唯一,要求必须重写hashCode方法和equals方法

@Override
 public boolean equals(Object o) {
     
     
     if (this == o) return true;
     if (o == null || getClass() != o.getClass()) return false;

     Student student = (Student) o;

     if (age != student.age) return false;
     return name != null ? name.equals(student.name) : student.name == null;
 }

 @Override
 public int hashCode() {
     
     
     int result = name != null ? name.hashCode() : 0;
     result = 31 * result + age;
     return result;
 }

Idea中重写,可Alt+Insert进行快捷重写

17.8LinkedHashSet集合

笔记小结:

  1. 概述:LinkedHashSetHashSet 的一个子类,它使用了一个双向链表来维护插入顺序,同时也保持了 HashSet 的元素唯一性
  2. 特点:有序、不重复、无索引。
  3. 底层原理:底层数据结构是依然哈希表,只是每个元素又额外的多了一个双链表的机制记录存储顺序

17.8.1概述

17.8.2底层原理

  • 有序、不重复、无索引。
  • 这里的有序指的是保证存储和取出的元素顺序一致
  • 原理∶底层数据结构是依然哈希表,只是每个元素又额外的多了一个双链表的机制记录存储的顺序。

image-20230421114431793

示例:

public class A04_LinkedHashSetDemo {
    
    
    public static void main(String[] args) {
    
    
        //1.创建4个学生对象
        Student s1 = new Student("zhangsan",23);
        Student s2 = new Student("lisi",24);
        Student s3 = new Student("wangwu",25);
        Student s4 = new Student("zhangsan",23);


        //2.创建集合的对象
        LinkedHashSet<Student> lhs = new LinkedHashSet<>();


        //3.添加元素
        System.out.println(lhs.add(s3));
        System.out.println(lhs.add(s2));
        System.out.println(lhs.add(s1));
        System.out.println(lhs.add(s4));

        //4.打印集合
        System.out.println(lhs);
    }
}

说明:

​ LinkedHashSet存入和取出的数据是有序的

17.9TreeSet集合

笔记小节:

  1. 概述:TreeSet 是 Java 集合框架中的一个集合类,它实现了 SortedSet 接口,可以对元素进行排序
  2. 底层原理:TreeSet集合底层是基于红黑树的数据结构实现排序的,增删改查性能都较好
  3. 两种比较方式:默认排序/自然排序、比较器排序
  4. 细节:比较方式使用原则:默认使用第一种,如果第一种不能满足当前需求,就使用第二种,自定义排序

17.9.1概述

特点:

  • 不重复、无索引、可排序
  • 可排序:按照元素的默认规则(有小到大)排序
  • TreeSet集合底层是基于红黑树的数据结构实现排序的,增删改查性能都较好

TreeSet集合默认的规则:

  • 对于数值类型:Integer , Double,默认按照从小到大的顺序进行排序。
  • 对于字符、字符串类型:按照字符在ASClI码表中的数字升序进行排序。

17.9.2常用成员方法

类是于Set

基础示例:

 //1.创建TreeSet集合对象
        TreeSet<Integer> ts = new TreeSet<>();

        //2.添加元素
        ts.add(4);
        ts.add(5);
        ts.add(1);
        ts.add(3);
        ts.add(2);

        //3.打印集合
        //System.out.println(ts);

        //4.遍历集合(三种遍历)
        //迭代器
        Iterator<Integer> it = ts.iterator();
        while(it.hasNext()){
    
    
            int i = it.next();
            System.out.println(i);
        }

        System.out.println("--------------------------");
        //增强for
        for (int t : ts) {
    
    
            System.out.println(t);
        }
        System.out.println("--------------------------");
        //lambda
        ts.forEach( i-> System.out.println(i));

17.9.3两种排序比较方式

17.9.3.1默认排序/自然排序

Javabean类实现Comparable接口指定比较规则

public class Student implements Comparable<Student>{
    
    
    private String name;
    private int age;

    public Student() {
    
    
    }

    public Student(String name, int age) {
    
    
        this.name = name;
        this.age = age;
    }

    /**
     * 获取
     * @return name
     */
    public String getName() {
    
    
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
    
    
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
    
    
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
    
    
        this.age = age;
    }

    public String toString() {
    
    
        return "Student{name = " + name + ", age = " + age + "}";
    }

    @Override
    //this:表示当前要添加的元素
    //o:表示已经在红黑树存在的元素

    //返回值:
    //负数:表示当前要添加的元素是小的,存左边
    //正数:表示当前要添加的元素是大的,存右边
    //0 :表示当前要添加的元素已经存在,舍弃
    public int compareTo(Student o) {
    
    
        System.out.println("--------------");
        System.out.println("this:" + this);
        System.out.println("o:" + o);
        //指定排序的规则
        //只看年龄,我想要按照年龄的升序进行排列
        return this.getAge() - o.getAge();
    }
}

说明:

若需要将此类用于Treeset,需要实现Comparable接口,并在实现时指定泛型的类

public class A05_TreeSetDemo2 {
    
    
    public static void main(String[] args) {
    
    
        /*
            需求:创建TreeSet集合,并添加3个学生对象
            学生对象属性:
                姓名,年龄。
                要求按照学生的年龄进行排序
                同年龄按照姓名字母排列(暂不考虑中文)
                同姓名,同年龄认为是同一个人

            方式一:
                默认的排序规则/自然排序
                Student实现Comparable接口,重写里面的抽象方法,再指定比较规则
        */


        //1.创建三个学生对象
        Student s1 = new Student("zhangsan",23);
        Student s2 = new Student("lisi",24);
        Student s3 = new Student("wangwu",25);
        Student s4 = new Student("zhaoliu",26);


        //2.创建集合对象
        TreeSet<Student> ts = new TreeSet<>();

        //3.添加元素
        ts.add(s3);
        ts.add(s2);
        ts.add(s1);
        ts.add(s4);

        //4.打印集合
        System.out.println(ts);


        //TreeSet 底层是红黑树

    }
}

17.9.3底层原理:

image-20230421154711618

17.9.3.2比较器排序

创建TreeSet对象时候,传递比较器Comparator指定规则

public class A06_TreeSetDemo3 {
    
    
    public static void main(String[] args) {
    
    
       /*
            需求:请自行选择比较器排序和自然排序两种方式;
            要求:存入四个字符串, “c”, “ab”, “df”, “qwer”
            按照长度排序,如果一样长则按照首字母排序

            采取第二种排序方式:比较器排序
        */

        //1.创建集合
        //o1:表示当前要添加的元素
        //o2:表示已经在红黑树存在的元素
        //返回值规则跟之前是一样的
        TreeSet<String> ts = new TreeSet<>((o1, o2)->{
    
    
                // 按照长度排序
                int i = o1.length() - o2.length();
                //如果一样长则按照首字母排序
                i = i == 0 ? o1.compareTo(o2) : i;
                return i;
        });

        //2.添加元素
        ts.add("c");
        ts.add("ab");
        ts.add("df");
        ts.add("qwer");


        //3.打印集合
        System.out.println(ts);


    }
}

17.9.4方法返回值特点

  • 负数:表示当前要添加的元素是小的,存左边
  • 正数:表示当前要添加的元素是大的,存右边
  • 0:表示当前要添加的元素已经存在,舍弃

17.10单列集合应用场景(重点)

image-20230421161119362

17.11Map集合

笔记小结:

  1. 概述:Map 是一种用于存储键值对的集合,每个键对应一个唯一的

  2. 常用成员方法:putremoveclearcontainsKeycontainsValueisEmptysize.

  3. 遍历方式:

    • 键找值,API:map.keySet()

      Set<String> keys = map.keySet();
      for (String key : keys) {
               
               
          String value = map.get(key);
      }
      
    • 键值对,API:map.entrySet()

      Set<Map.Entry<String, String>> entries = map.entrySet();
      for (Map.Entry<String, String> entry : entries) {
               
               
          String key = entry.getKey();
          String value = entry.getValue();
      }
      
    • Lambda表达式,API:map.forEach()

      map.forEach(new BiConsumer<String, String>() {
               
               
          @Override
          public void accept(String key, String value) {
               
               
              System.out.println(key + "=" + value);
          }
      });
      

17.11.1概述

​ 在 Java 中,Map 是一种用于存储键值对的集合,每个键对应一个唯一的值。它是一种非常常用的集合,可用于快速查找和访问数据。

格式:

interface Map<K,V>  K:键的类型;V:值的类型

17.11.2常用成员方法

方法名 说明
V put(K key,V value) 添加元素
V remove(Object key) 根据键删除键值对元素
void clear() 移除所有的键值对元素
boolean containsKey(Object key) 判断集合是否包含指定的键
boolean containsValue(Object value) 判断集合是否包含指定的值
boolean isEmpty() 判断集合是否为空
int size() 集合的长度,也就是集合中键值对的个数

17.11.2.1put()

Map<String,String> map = new HashMap<String,String>();
map.put("张无忌","赵敏");
map.put("郭靖","黄蓉");
map.put("杨过","小龙女");
  • 在添加数据的时候,如果键不存在,那么直接把键值对对象添加到map集合当中,方法返回null
  • 在添加数据的时候,如果键是存在的,那么会把原有的键值对对象覆盖,会把返回被覆盖的值

17.11.2.2clear()

Map<String,String> map = new HashMap<String,String>();
map.clear();

17.11.2.3remove()

Map<String,String> map = new HashMap<String,String>();    
String result = map.remove("郭靖"); 
  • 在删除数据的时候,如果键不存在,那么直接把键值对对象添加到map集合当中,方法返回null
  • 在删除数据的时候,如果键是存在的,那么会把原有的键值对对象覆盖,会把返回被删除的值

17.11.2.4containsKey()

Map<String,String> map = new HashMap<String,String>();    
boolean keyResult = m.containsKey("郭靖");
System.out.println(valueResult);

17.11.2.5containsValue()

Map<String,String> map = new HashMap<String,String>();    
boolean valueResult = map.containsValue("小龙女2");
System.out.println(valueResult);

17.11.2.6isEmpty()

Map<String,String> map = new HashMap<String,String>();    
boolean result = map.isEmpty();
System.out.println(result);

17.11.2.7size()

Map<String,String> map = new HashMap<String,String>();   
int size = map.size();
System.out.println(size);

17.11.2.8案例–神话人物查询

public class MapDemo02 {
    
    
    public static void main(String[] args) {
    
    
        //创建集合对象
        Map<String,String> map = new HashMap<String,String>();

        //V put(K key,V value):添加元素
        map.put("张无忌","赵敏");
        map.put("郭靖","黄蓉");
        map.put("杨过","小龙女");

        //V remove(Object key):根据键删除键值对元素
//        System.out.println(map.remove("郭靖"));
//        System.out.println(map.remove("郭襄"));

        //void clear():移除所有的键值对元素
//        map.clear();

        //boolean containsKey(Object key):判断集合是否包含指定的键
//        System.out.println(map.containsKey("郭靖"));
//        System.out.println(map.containsKey("郭襄"));

        //boolean isEmpty():判断集合是否为空
//        System.out.println(map.isEmpty());

        //int size():集合的长度,也就是集合中键值对的个数
        System.out.println(map.size());

        //输出集合对象
        System.out.println(map);
    }
}

17.11.3遍历方式

17.11.3.1键找值

概述:通过Map集合的键来获得值

方法介绍:

方法名 说明
V get(Object key) 根据键获取值
Set keySet() 获取所有键的集合
Collection values() 获取所有值的集合

基本用例:

public class MapDemo01 {
    
    
    public static void main(String[] args) {
    
    
        //1.创建Map集合的对象
        Map<String,String> map = new HashMap<>();

        //2.添加元素
        map.put("尹志平","小龙女");
        map.put("郭靖","穆念慈");
        map.put("欧阳克","黄蓉");

        //3.通过键找值

        //3.1获取所有的键,把这些键放到一个单列集合当中
        Set<String> keys = map.keySet();
        //3.2遍历单列集合,得到每一个键
        for (String key : keys) {
    
    
            //System.out.println(key);
            //3.3 利用map集合中的键获取对应的值  get
            String value = map.get(key);
            System.out.println(key + " = " + value);
        }
        //4.直接找值
        Collection<String> values = map.values();
        for(String value : values) {
    
    
            System.out.println(value);
        }
    }
}

17.11.3.2键值对

概述:通过Map集合获取键值对

方法介绍:

方法名 说明
Set<Map.Entry<K,V>> entrySet() 获取所有键值对对象的集合

基本用例:

public class MapDemo03 {
    
    
    public static void main(String[] args) {
    
    
        //Map集合的第二种遍历方式
        
        //1.创建Map集合的对象
        Map<String, String> map = new HashMap<>();

        //2.添加元素
        //键:人物的外号
        //值:人物的名字
        map.put("标枪选手", "马超");
        map.put("人物挂件", "明世隐");
        map.put("御龙骑士", "尹志平");

        //3.Map集合的第二种遍历方式
        //通过键值对对象进行遍历
        //3.1 通过一个方法获取所有的键值对对象,返回一个Set集合
        Set<Map.Entry<String, String>> entries = map.entrySet();
        //3.2 遍历entries这个集合,去得到里面的每一个键值对对象
        for (Map.Entry<String, String> entry : entries) {
    
    //entry  --->  "御龙骑士","尹志平"
            //3.3 利用entry调用get方法获取键和值
            String key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key + "=" + value);
        }
    }
}

17.11.3.3Lambda表达式

概述:得益于JDK8开始的新技术Lambda表达式,提供了一种更简单、更直接的遍历集合的方式。

基本用例:

public class MapDemo03 {
    
    
    public static void main(String[] args) {
    
    
       //Map集合的第三种遍历方式


        //1.创建Map集合的对象
        Map<String,String> map = new HashMap<>();

        //2.添加元素
        //键:人物的名字
        //值:名人名言
        map.put("鲁迅","这句话是我说的");
        map.put("曹操","不可能绝对不可能");
        map.put("刘备","接着奏乐接着舞");
        map.put("柯镇恶","看我眼色行事");

        //3.利用lambda表达式进行遍历
        //底层:
        //forEach其实就是利用第二种方式进行遍历,依次得到每一个键和值
        //再调用accept方法
        map.forEach(new BiConsumer<String, String>() {
    
    
            @Override
            public void accept(String key, String value) {
    
    
                System.out.println(key + "=" + value);
            }
        });

        System.out.println("-----------------------------------");

        map.forEach((String key, String value)->{
    
    
                System.out.println(key + "=" + value);
            }
        );

        System.out.println("-----------------------------------");

        map.forEach((key, value)-> System.out.println(key + "=" + value));

    }
}

17.12HashMap集合

笔记小结:

  1. 概述:HashMap 是 Java 中的一个集合类,它实现了 Map 接口,可以用来存储键值对
  2. 特点:无序的、 允许使用 null 作为键或值、键是唯一的,插入键相同则覆盖线程不安全的、HashMap 的实现是基于哈希表的,使用哈希算法来确定键值对的存储位置,因此插入和查询时间复杂度为 O(1)
  3. 底层原理:
    • HashMap底层是哈希表结构
    • 依赖hashCode方法和equals方法保证键的唯一
    • 如果要存储的是自定义对象需要重写hashCode和equals方法(此处注意!!!!)。如果要存储的是自定义对象,不需要重写hashCode和equals方法0
    • 待完善,详细参见视频!!!

17.12.1概述

image-20230424195034363

HashMap 是 Java 中的一个集合类,它实现了 Map 接口,可以用来存储键值对。

特点:

  • HashMap 中的键值对是无序的。
  • HashMap 允许使用 null 作为键或值。
  • HashMap 的键是唯一的,如果插入了两个相同的键,则后插入的值会覆盖先插入的值。
  • HashMap 是线程不安全的,如果多个线程同时对 HashMap 进行操作,可能会导致数据不一致。
  • HashMap 的实现是基于哈希表的,使用哈希算法来确定键值对的存储位置,因此插入和查询的时间复杂度为 O(1)。

基本用例:

public class HashMapDemo {
    
    
    public static void main(String[] args) {
    
    
        //创建HashMap集合对象
        HashMap<Student, String> hm = new HashMap<Student, String>();

        //创建学生对象
        Student s1 = new Student("林青霞", 30);
        Student s2 = new Student("张曼玉", 35);
        Student s3 = new Student("王祖贤", 33);
        Student s4 = new Student("王祖贤 ", 33);

        //把学生添加到集合
        hm.put(s1, "西安");
        hm.put(s2, "武汉");
        hm.put(s3, "郑州");
        hm.put(s4, "北京");

        //遍历集合
        Set<Student> keySet = hm.keySet();
        for (Student key : keySet) {
    
    
            String value = hm.get(key);
            System.out.println(key.getName() + "," + key.getAge() + "," + value);
        }
    }
}

17.12.2底层原理

image-20230424204844400

说明:

此图为HashMap底层源码的改写版本,通俗易懂

image-20230811225217966

  • HashMap底层是哈希表结构的
  • 依赖hashCode方法和equals方法保证键的唯一
  • 如果要存储的是自定义对象,需要重写hashCode和equals方法。如果要存储的是自定义对象,不需要重写hashCode和equals方法0

参考资料:集合进阶-13-HashMap源码超详细解析(一)_哔哩哔哩_bilibili

17.13LinkedHashMap集合

笔记小结:

  1. 概述:LinkedHashMap 是 HashMap 的一个子类
  2. 特点:不重复无索引有序性
  3. 底层原理:底层数据结构是依然哈希表,只是每个键值对元素又额外的多了一个双链表的机制记录存储的顺序。跟HashSet一样

17.13.1概述

image-20230424195741868

LinkedHashMap 是 HashMap 的一个子类

特点:

  • 不重复
  • 无索引
  • 有序性:LinkedHashMap 中的元素按照插入顺序排序,也可以按照访问顺序排序(通过构造函数传入 accessOrder 参数为 true 实现)。

17.13.2底层原理

底层数据结构是依然哈希表,只是每个键值对元素又额外的多了一个双链表的机制记录存储的顺序。跟HashSet一样

17.14TreeMap集合

笔记小结:

  1. 概述:TreeMap 是 Java 中的一种双列集合,它基于红黑树实现。TreeMap 通过 key-value 存储数据,支持根据 key 值进行排序和查找,可以保证元素有序,因此在需要对集合中的元素进行排序时,可以使用 TreeMap。

  2. 特点:

    • TreeMap底层是红黑树结构
    • 依赖自然排序或者比较器排序,对键进行排序
    • 如果存储的是自定义对象,需要实现Comparable接口或者在创建TreeMap对象时候给出比较器排序规则
    • 注意:默认按照键的从小到大进行排序,也可以自己规定键的排序规则
  3. 底层原理:待完善,详细参见视频!!!

17.14.1概述

特点:

  • TreeMap底层是红黑树结构
  • 依赖自然排序或者比较器排序,对键进行排序
  • 如果键存储的是自定义对象,需要实现Comparable接口或者在创建TreeMap对象时候给出比较器排序规则
  • 注意:默认按照键的从小到大进行排序,也可以自己规定键的排序规则

基本用例:

public class Test1 {
    
    
    public static void main(String[] args) {
    
    
      	// 创建TreeMap集合对象
        TreeMap<Student,String> tm = new TreeMap<>();
      
		// 创建学生对象
        Student s1 = new Student("xiaohei",23);
        Student s2 = new Student("dapang",22);
        Student s3 = new Student("xiaomei",22);
      
		// 将学生对象添加到TreeMap集合中
        tm.put(s1,"江苏");
        tm.put(s2,"北京");
        tm.put(s3,"天津");
      
		// 遍历TreeMap集合,打印每个学生的信息
        tm.forEach(
                (Student key, String value)->{
    
    
                    System.out.println(key + "---" + value);
                }
        );
    }
}

也需要在student类中进行接口实现

public class Student implements Comparable<Student>{
    
    
	……………………
    @Override
    public int compareTo(Student o) {
    
    
        //按照年龄进行排序
        int result = o.getAge() - this.getAge();
        //次要条件,按照姓名排序。
        result = result == 0 ? o.getName().compareTo(this.getName()) : result;
        return result;
    }
}

17.14.2底层原理

参考资料:集合进阶-17-TreeMap源码超详细解析(一)_哔哩哔哩_bilibili

17.15不可变集合

笔记小结:

  1. 概述:是一个长度不可变内容无法修改的集合

  2. 特点:定义完成后

    • 不可修改
    • 不可添加
    • 不可删除
  3. 常用成员方法:List、Set、Map接口中,都存在of方法可以创建不可变集合

  4. 三种方式的细节:

    1. List:直接用

       List<String> list = List.of("张三", "李四", "王五", "赵六");
      
    2. Set:元素不能重复

       Set<String> set = Set.of("张三", "张三", "李四", "王五", "赵六");
      
    3. Map:元素不能重复、键值对数量最多是10个。

      • 少于10个用of方法

            Map<String, String> map = Map.of("张三", "南京", "张三",……);
        
      • 超过10个用ofEntries方法

           HashMap<String, String> hm = new HashMap<>();
        hm.put("张三", "南京");
        hm.put("李四", "北京");
        Map<String, String> map = Map.copyOf(hm); // 此方法为JDK10之后才拥有的
        

17.15.1概述

是一个长度不可变,内容也无法修改的集合

17.15.2使用场景

​ 如果某个数据不能被修改,把它防御性地拷贝不可变集合中是个很好的实践。

​ 当集合对象被不可信的库调用时,不可变形式是安全的。

简单理解:

​ 不想让别人修改集合中的内容

17.15.3分类

  • 不可变的list集合
  • 不可变的set集合
  • 不可变的map集合

常用成员方法

image-20230425092421946

17.15.3.1不可变的list集合

public class ImmutableDemo1 {
    
    
    public static void main(String[] args) {
    
    
        /*
            创建不可变的List集合
            "张三", "李四", "王五", "赵六"
        */

        //一旦创建完毕之后,是无法进行修改的,在下面的代码中,只能进行查询操作
        List<String> list = List.of("张三", "李四", "王五", "赵六");

        System.out.println(list.get(0));
        System.out.println(list.get(1));
        System.out.println(list.get(2));
        System.out.println(list.get(3));

        System.out.println("---------------------------");

        for (String s : list) {
    
    
            System.out.println(s);
        }

        System.out.println("---------------------------");


        Iterator<String> it = list.iterator();
        while(it.hasNext()){
    
    
            String s = it.next();
            System.out.println(s);
        }
        System.out.println("---------------------------");

        for (int i = 0; i < list.size(); i++) {
    
    
            String s = list.get(i);
            System.out.println(s);
        }
        System.out.println("---------------------------");

        //list.remove("李四");
        //list.add("aaa");
        list.set(0,"aaa");
    }
}

17.15.3.2不可变的Set集合

public class ImmutableDemo2 {
    
    
    public static void main(String[] args) {
    
    
        /*
           创建不可变的Set集合
           "张三", "李四", "王五", "赵六"


           细节:
                当我们要获取一个不可变的Set集合时,里面的参数一定要保证唯一性
        */

        //一旦创建完毕之后,是无法进行修改的,在下面的代码中,只能进行查询操作
        Set<String> set = Set.of("张三", "张三", "李四", "王五", "赵六");

        for (String s : set) {
    
    
            System.out.println(s);
        }

        System.out.println("-----------------------");

        Iterator<String> it = set.iterator();
        while(it.hasNext()){
    
    
            String s = it.next();
            System.out.println(s);
        }

        System.out.println("-----------------------");
        //set.remove("王五");
    }
}

17.15.3.3不可变的Map集合

  • 键值对个数小于等于10
public class ImmutableDemo3 {
    
    
    public static void main(String[] args) {
    
    
       /*
        创建Map的不可变集合
            细节1:
                键是不能重复的
            细节2:
                Map里面的of方法,参数是有上限的,最多只能传递20个参数,10个键值对
            细节3:
                如果我们要传递多个键值对对象,数量大于10个,在Map接口中还有一个方法
        */

        //一旦创建完毕之后,是无法进行修改的,在下面的代码中,只能进行查询操作
        Map<String, String> map = Map.of("张三", "南京", "张三", "北京", "王五", "上海",
                "赵六", "广州", "孙七", "深圳", "周八", "杭州",
                "吴九", "宁波", "郑十", "苏州", "刘一", "无锡",
                "陈二", "嘉兴");

        Set<String> keys = map.keySet();
        for (String key : keys) {
    
    
            String value = map.get(key);
            System.out.println(key + "=" + value);
        }

        System.out.println("--------------------------");

        Set<Map.Entry<String, String>> entries = map.entrySet();
        for (Map.Entry<String, String> entry : entries) {
    
    
            String key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key + "=" + value);
        }
        System.out.println("--------------------------");
    }
}
  • 键值对个数大于10
public class ImmutableDemo4 {
    
    
    public static void main(String[] args) {
    
    

        /*
            创建Map的不可变集合,键值对的数量超过10个
        */

        //1.创建一个普通的Map集合
        HashMap<String, String> hm = new HashMap<>();
        hm.put("张三", "南京");
        hm.put("李四", "北京");
        hm.put("王五", "上海");
        hm.put("赵六", "北京");
        hm.put("孙七", "深圳");
        hm.put("周八", "杭州");
        hm.put("吴九", "宁波");
        hm.put("郑十", "苏州");
        hm.put("刘一", "无锡");
        hm.put("陈二", "嘉兴");
        hm.put("aaa", "111");

        //2.利用上面的数据来获取一个不可变的集合
/*
        //获取到所有的键值对对象(Entry对象)
        Set<Map.Entry<String, String>> entries = hm.entrySet();
        //把entries变成一个数组
        Map.Entry[] arr1 = new Map.Entry[0];
        //toArray方法在底层会比较集合的长度跟数组的长度两者的大小
        //如果集合的长度 > 数组的长度 :数据在数组中放不下,此时会根据实际数据的个数,重新创建数组
        //如果集合的长度 <= 数组的长度:数据在数组中放的下,此时不会创建新的数组,而是直接用
        Map.Entry[] arr2 = entries.toArray(arr1);
        //不可变的map集合
        Map map = Map.ofEntries(arr2);
        map.put("bbb","222");*/


        //Map<Object, Object> map = Map.ofEntries(hm.entrySet().toArray(new Map.Entry[0]));

        Map<String, String> map = Map.copyOf(hm);
        map.put("bbb","222");
    }
}

17.16Collections集合工具类

笔记小结:

  1. 概述:java.util.Collections:是集合工具类
  2. 常用成员方法:
    1. 新增:addAll
    2. 顺序:打乱shuffle()、排序sort()、指定排序sort()、交换swap()
    3. 拷贝:copy()
    4. 填充:fill()
    5. 最大最小:max/min()
    6. 查询:binarySearch()

17.16.1概述

java.util.Collections:是集合工具类

作用:Collections不是集合,而是集合的工具类

17.16.2常用成员方法

image-20230425091419212

17.16.3基本用例

案例1

public class CollectionsDemo1 {
    
    
    public static void main(String[] args) {
    
    

        //addAll  批量添加元素
        //1.创建集合对象
        ArrayList<String> list = new ArrayList<>();
        //2.批量添加元素
        Collections.addAll(list,"abc","bcd","qwer","df","asdf","zxcv","1234","qwer");
        //3.打印集合
        System.out.println(list);

        //shuffle 打乱
        Collections.shuffle(list);

        System.out.println(list);

    }
}

案例2

public class CollectionsDemo2 {
    
    
    public static void main(String[] args) {
    
    
      /*
        public static <T> void sort(List<T> list)                       排序
        public static <T> void sort(List<T> list, Comparator<T> c)      根据指定的规则进行排序
        public static <T> int binarySearch (List<T> list,  T key)       以二分查找法查找元素
        public static <T> void copy(List<T> dest, List<T> src)          拷贝集合中的元素
        public static <T> int fill (List<T> list,  T obj)               使用指定的元素填充集合
        public static <T> void max/min(Collection<T> coll)              根据默认的自然排序获取最大/小值
        public static <T> void swap(List<?> list, int i, int j)         交换集合中指定位置的元素
     */


        System.out.println("-------------sort默认规则--------------------------");
        //默认规则,需要重写Comparable接口compareTo方法。Integer已经实现,按照从小打大的顺序排列
        //如果是自定义对象,需要自己指定规则
        ArrayList<Integer> list1 = new ArrayList<>();
        Collections.addAll(list1, 10, 1, 2, 4, 8, 5, 9, 6, 7, 3);
        Collections.sort(list1);
        System.out.println(list1);


        System.out.println("-------------sort自己指定规则规则--------------------------");
        Collections.sort(list1, new Comparator<Integer>() {
    
    
            @Override
            public int compare(Integer o1, Integer o2) {
    
    
                return o2 - o1;
            }
        });
        System.out.println(list1);

        Collections.sort(list1, (o1, o2) -> o2 - o1);
        System.out.println(list1);

        System.out.println("-------------binarySearch--------------------------");
        //需要元素有序
        ArrayList<Integer> list2 = new ArrayList<>();
        Collections.addAll(list2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        System.out.println(Collections.binarySearch(list2, 9));
        System.out.println(Collections.binarySearch(list2, 1));
        System.out.println(Collections.binarySearch(list2, 20));

        System.out.println("-------------copy--------------------------");
        //把list3中的元素拷贝到list4中
        //会覆盖原来的元素
        //注意点:如果list3的长度 > list4的长度,方法会报错
        ArrayList<Integer> list3 = new ArrayList<>();
        ArrayList<Integer> list4 = new ArrayList<>();
        Collections.addAll(list3, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        Collections.addAll(list4, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
        Collections.copy(list4, list3);
        System.out.println(list3);
        System.out.println(list4);

        System.out.println("-------------fill--------------------------");
        //把集合中现有的所有数据,都修改为指定数据
        ArrayList<Integer> list5 = new ArrayList<>();
        Collections.addAll(list5, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        Collections.fill(list5, 100);
        System.out.println(list5);

        System.out.println("-------------max/min--------------------------");
        //求最大值或者最小值
        ArrayList<Integer> list6 = new ArrayList<>();
        Collections.addAll(list6, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        System.out.println(Collections.max(list6));
        System.out.println(Collections.min(list6));

        System.out.println("-------------max/min指定规则--------------------------");
        // String中默认是按照字母的abcdefg顺序进行排列的
        // 现在我要求最长的字符串
        // 默认的规则无法满足,可以自己指定规则
        // 求指定规则的最大值或者最小值
        ArrayList<String> list7 = new ArrayList<>();
        Collections.addAll(list7, "a","aa","aaa","aaaa");
        System.out.println(Collections.max(list7, new Comparator<String>() {
    
    
            @Override
            public int compare(String o1, String o2) {
    
    
                return o1.length() - o2.length();
            }
        }));

        System.out.println("-------------swap--------------------------");
        ArrayList<Integer> list8 = new ArrayList<>();
        Collections.addAll(list8, 1, 2, 3);
        Collections.swap(list8,0,2);
        System.out.println(list8);



    }
}

18.泛型

笔记小结:

  1. 概述:泛型是Java中的一种特性,它可以将类或方法中的数据类型作为参数进行传递和使用

  2. 格式

    <E> <T>
    
  3. 好处:

    • 把运行时期的问题提前到了编译期间
    • 避免了强制类型转换
  4. 注意:在java中在编译为class文件时,是会擦除掉泛型的

  5. 细节:

    • 泛型中不能写基本数据类型
    • 指定泛型的具体类型后,传递数据时,可以传入该类类型或者其子类类型
    • 如果不写泛型,类型默认是Object
  6. 分类:

    1. 泛型类

      • 概念:在类名后面定义泛型,创建该类对象的时候,确定类型

      • 格式:

        修饰符 class 类名<类型>{
                   
                   
        }
        // 例如
        public class Arraylist<T>{
                   
                   
        }
        
    2. 泛型方法

      • 概念:在修饰符后面定义方法,调用该方法的时候,确定类型

      • 格式:

        修饰符<类型> 返回值类型方法名(类型变量名){
                   
                   
        }
        // 例如
        public<T> void show (T t){
                   
                   
        }
        
    3. 泛型接口

      • 概念:在接口名后面定义泛型,实现类确定类型,实现类延续泛型

      • 格式:

        修饰符 interface 接口名<类型>{
                   
                   
        }
        // 例如
        public interface List<E>{
                   
                   
        }
        
  7. 泛型通配符

    • 泛型不具备继承性,但是数据具备继承性

      public static void method( ArrayList<Animal> list) {
               
               
      }
      // 此处method方法所传入的任何参数,只能是Animal类的集合,其余任何类的集合都不行,包括子类继承的类集合也不行
      
      ArrayList<Ye> list1 = new ArrayList<>();
      list1.add(new Ye());
      list1.add(new Fu());
      list1.add(new zi());
      // 与泛型类形成对比,数据具备继承性
      
    • 泛型的通配符:?

      // 格式
      ? extend E // 传递子类
      ? super E //传递父类
      // 例如
      public static void keepPet(ArrayList<? extends Animal> list){
               
               
      }
      public static void keepPet(ArrayList<? super Animal> list){
               
               
      }
      
  8. 应用场景:

    • 定义类、方法、接口的时候,如果类型不确定,就可以定义泛型
    • 如果类型不确定,但是能知道是哪个继承体系中的,可以使用泛型的通配符

18.1概述

​ Java泛型是Java SE 5中引入的一种编程机制,它通过参数化类型来实现代码的重用。使用泛型可以让代码更加通用和类型安全,避免了在编译时期因类型转换错误导致的运行时异常。

格式:

  • <类型>: 指定一种类型的格式.尖括号里面可以任意书写,一般只写一个字母.例如:
  • <类型1,类型2…>: 指定多种类型的格式,多种类型之间用逗号隔开.例如: <E,T> <K,V>

好处:

  • 把运行时期的问题提前到了编译期间
  • 避免了强制类型转换

image-20230420203633208

说明:

在java中在编译为class文件时,是会擦除掉泛型的

细节:

  • 泛型中不能写基本数据类型
  • 指定泛型的具体类型后,传递数据时,可以传入该类类型或者其子类类型
  • 如果不写泛型,类型默认是Object

说明:

因为泛型的基本数据类型是Object类型,基本数据类型无法自动转换为Object类型

18.2分类

18.2.1泛型类

概念:泛型类(Generic Class)指在类的定义中使用泛型类型参数的类,可以在类中使用泛型类型参数,从而增强代码的可重用性和类型安全性。

格式:

修饰符 class 类名<类型>{
    
    
    
}
// 例如
public class Arraylist<T>{
    
    
    
}

说明:

此处E可以理解为变量,但是不是用来记录数据的,而是记录数据的类型,可以写成T、E、K、V等

示例:

image-20230420204756615

18.2.2泛型方法

概述:泛型方法(Generic Method)指在方法定义中使用泛型类型参数的方法,可以在方法中使用泛型类型参数,从而增强代码的可重用性和类型安全性。

格式

修饰符<类型> 返回值类型方法名(类型变量名){
    
    
}
// 例如
public<T> void show (T t){
    
    
}

说明:

此处T可以理解为变量,但是不是用来记录数据的,而是记录类型的,可以写成:.E、K、V等

image-20230420205709842

补充:

当使用 E … 作为参数时, … 表示可变参数,此时传入的参数个数也是不确定的

18.2.3泛型接口

概念:泛型接口(Generic Interface)指在接口的定义中使用泛型类型参数的接口,可以在接口中使用泛型类型参数,从而增强代码的可重用性和类型安全性。

格式:

修饰符 interface 接口名<类型>{
    
    
}
// 例如
public interface List<E>{
    
    
}

使用:

  • 实现类给出具体类型

image-20230420210317464

  • 实现类延续泛型,创建对象时再确定

image-20230420210249881

18.3通配符

​ 概念:泛型的通配符指的是 Java 中的通配符类型(Wildcard Type),使用 ? 表示。通配符类型是一种类型实参,可以用于表示某个泛型类型的类型参数可以是任何类型。通配符类型可以用于方法参数类型、变量类型、返回值类型等。

通配符:?也表示不确定的类型

分类:

  • ? extends E: 表示可以传递E或者E所有的子类类型
  • ? super E:表示可以传递E或者E所有的父类类型

特点:

  • 泛型的继承和通配符
  • 泛型不具备继承性,但是数据具备继承性

应用场景:

  • 如果我们在定义类、方法、接口的时候,如果类型不确定,就可以定义泛型类、泛型方法、泛型接口。
  • 如果类型不确定,但是能知道以后只能传递某个继承体系中的,就可以泛型的通配符

意义:限定类型的范围

代码:

public class Test1 {
    
    
    public static void main(String[] args) {
    
    
        /*
            需求:
                定义一个继承结构:
                                    动物
                         |                           |
                         猫                          狗
                      |      |                    |      |
                   波斯猫   狸花猫                泰迪   哈士奇


                 属性:名字,年龄
                 行为:吃东西
                       波斯猫方法体打印:一只叫做XXX的,X岁的波斯猫,正在吃小饼干
                       狸花猫方法体打印:一只叫做XXX的,X岁的狸花猫,正在吃鱼
                       泰迪方法体打印:一只叫做XXX的,X岁的泰迪,正在吃骨头,边吃边蹭
                       哈士奇方法体打印:一只叫做XXX的,X岁的哈士奇,正在吃骨头,边吃边拆家

            测试类中定义一个方法用于饲养动物
                public static void keepPet(ArrayList<???> list){
                    //遍历集合,调用动物的eat方法
                }
            要求1:该方法能养所有品种的猫,但是不能养狗
            要求2:该方法能养所有品种的狗,但是不能养猫
            要求3:该方法能养所有的动物,但是不能传递其他类型
         */


        ArrayList<PersianCat> list1 = new ArrayList<>();
        ArrayList<LiHuaCat> list2 = new ArrayList<>();
        ArrayList<TeddyDog> list3 = new ArrayList<>();
        ArrayList<HuskyDog> list4 = new ArrayList<>();

        keepPet(list1);
        keepPet(list2);
        keepPet(list3);
        keepPet(list4);
    }

    //该方法能养所有的动物,但是不能传递其他类型
    public static void keepPet(ArrayList<? extends Animal> list){
    
    
        //遍历集合,调用动物的eat方法
    }



  /*  //  要求2:该方法能养所有品种的狗,但是不能养猫
    public static void keepPet(ArrayList<? extends Dog> list){
        //遍历集合,调用动物的eat方法
    }*/


    /*//要求1:该方法能养所有品种的猫,但是不能养狗
    public static void keepPet(ArrayList<? extends Cat> list){
        //遍历集合,调用动物的eat方法
    }*/
}

知识加油站

1.数据结构

笔记小结:

  1. 概述:数据结构是计算机存储、组织数据的方式
  2. 栈:后进先出,先进后出。
  3. 队列:先进先出,后进后出。
  4. 数组:内存连续区域,查询快,增删慢。
  5. 链表:元素是游离的,查询慢,首尾操作极快。
  6. 树:请查看各个小节

1.1概述

​ 数据结构是计算机存储、组织数据的方式,是指数据元素之间的相互关系,以及它们之间在计算机存储器中的组织方式。常见的数据结构包括数组、链表、栈、队列、树、图等,它们在实际的计算机程序设计中扮演着重要的角色

image-20230328210954016

1.2栈

栈特点:先进后出,后进先出

image-20230420170514263

java中方法

image-20230420170558867

说明:

方法存在栈内存中,当function<-method<-main方法入栈后,会以function->methon->main的方式出栈

1.3队列

队列特点:先进先出,后进后出

image-20230420170844956

说明:

类似于生活中的排队买票

1.4数组

特点:数组是一种查询快,增删慢的模型

image-20230420171022878

  • **查询速度快:**查询数据通过地址值和索引定位,查询任意数据耗时相同。(元素在内存中是连续存储的)
  • 删除效率低:要将原始数据删除,同时后面每个数据前移。
  • 添加效率极低:添加位置后的每个数据后移,再添加元素。

1.5链表

特点:链表中的结点是独立的对象,在内存中是不连续的,每个结点包含数据值和下一个结点的地址

image-20230420171528194

  • 链表查询慢,无论查询哪个数据都要从头开始找。
  • 链表增删相对快

image-20230420171502885

1.6树

笔记小节:

  1. 概述:

    • 节点: 在树结构中,每一个元素称之为节点

      image-20230421092414995

    • 度: 每一个节点的子节点数量称之为度

  2. 二叉树:

    ​ 每个节点最多两个子节点,分别称为左子节点和右子节点。左子节点的值小于或等于父节点的,右子节点的值大于父节点的,这种性质使得二叉树在查找、排序等方面有很好的应用。二叉树的子树也是二叉树,即每个节点都可以看作是根节点

    image-20230811230654303

  3. 二叉查找数:

    ​ 每个节点包含一个键值对(key-value)、左子树的所有节点的键值小于根节点的键值、右子树的所有节点的键值大于根节点的键值左子树右子树也是二叉查找树。

    image-20230811230406817

  4. 平衡二叉树:

    ​ 叉树左右两个子树的高度差不超过1、任意节点的左右两个子树都是一颗平衡二叉树image-20230423083649743

  5. 红黑数:

    1. 特点:平衡二叉B树、每一个节点可以是红或者黑、红黑树不是高度平衡的,它的平衡是通过"自己的红黑规则"进行实现的

    2. 红黑规则:

      ​ 每一个节点或是红色的,或者是黑色的。根节点必须是黑色。如果一个节点没有子节点或者父节点,则该节点相应的指针属性值为Nil,这些Nil视为叶节点,每个叶节点(Nil)是黑色的。如果某一个节点是红色,那么它的子节点必须是黑色(不能出现两个红色节点相连 的情况)。对每一个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点

    image-20230811225057199

  6. 树的演变image-20230421092905390

1.6.1二叉树

特点:二叉树中,任意一个节点的度要小于等于2

  • 节点: 在树结构中,每一个元素称之为节点

    image-20230811231622595

  • 度: 每一个节点的子节点数量称之为度

image-20230811224958660

1.6.2二叉查找树

特点:

  • 每一个节点上最多有两个子节点
  • 任意节点左子树上的值都小于当前节点
  • 任意节点右子树上的值都大于当前节点

image-20230811230851159

1.6.3平衡二叉树

image-20230423083627548

特点:

  • 二叉树左右两个子树的高度差不超过1
  • 任意节点的左右两个子树都是一颗平衡二叉树

旋转:

  1. 旋转触发时机

    • 当添加一个节点之后,该树不再是一颗平衡二叉树
  2. 左旋:

    • 就是将根节点的右侧往左拉,原先的右子节点变成新的父节点,并把多余的左子节点出让,给已经降级的根节点当右子节点
      • image-20230811230957523
      • image-20230811231031684
  3. 右旋:

    • 就是将根节点的左侧往右拉,左子节点变成了新的父节点,并把多余的右子节点出让,给已经降级根节点当左子节点
      • image-20230811231105098
      • image-20230811231113475
  4. 平衡二叉树旋转的四种情况:

    1. 左左:当根节点左子树的左子树有节点插入,导致二叉树不平衡

      • 如何旋转: 直接对整体进行右旋即可

        image-20230811231246299

    2. 左右: 当根节点左子树的右子树有节点插入,导致二叉树不平衡

      • 如何旋转: 先在左子树对应的节点位置进行左旋,在对整体进行右旋

        image-20230811231255872

    3. 右右: 当根节点右子树的右子树有节点插入,导致二叉树不平衡

      • 如何旋转: 直接对整体进行左旋即可
    • image-20230811231402589
  5. 右左:当根节点右子树的左子树有节点插入,导致二叉树不平衡

    • 如何旋转: 先在右子树对应的节点位置进行右旋,在对整体进行左旋

      image-20230811225021706

参考资料:集合进阶-11数据结构(平衡二叉树旋转机制)_哔哩哔哩_bilibili

1.6.4红黑树

特点:

  • 平衡二叉B树
  • 每一个节点可以是红或者黑
  • 红黑树不是高度平衡的,它的平衡是通过"自己的红黑规则"进行实现的

红黑规则:

  1. 每一个节点或是红色的,或者是黑色的

  2. 根节点必须是黑色

  3. 如果一个节点没有子节点或者父节点,则该节点相应的指针属性值为Nil,这些Nil视为叶节点,每个叶节点(Nil)是黑色的

  4. 如果某一个节点是红色,那么它的子节点必须是黑色(不能出现两个红色节点相连 的情况)

  5. 对每一个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点

image-20230811225047728

  • 红黑树添加节点的默认颜色:添加节点时,默认为红色,效率高

    image-20230811231504780

  • 红黑树添加节点后如何保持红黑规则

    image-20230421103132809

2.可变参数

笔记小结:

  1. 概述:可变参数是一种Java方法的参数类型,允许方法接受任意数量的参数

  2. 特点:可变参数本质上就是一个数组

  3. 作用:在形参中接收多个数据

  4. 格式:数据类型…参数名称

    getSum(1,2,3,4,5,6,7,8,9,10);
    
    public static int getSum( int a,int...args) {
           
           
        return 0;
    }
    
  5. 注意:

    • 形参列表中可变参数只能有一个可变参数
    • 形参列表中可变参数必须放在形参列表的最后面

2.1定义

​ 可变参数是一种Java方法的参数类型,允许方法接受任意数量的参数。在方法声明中,可变参数使用省略号(…)来表示,它可以接收0个或多个相同类型的参数。使用可变参数的方法可以接受任意数量的参数,而无需提前声明它们的数量。在方法中,可变参数实际上是作为数组来处理的

2.2特点

  • 可变参数本质上就是一个数组

2.3作用

  • 在形参中接收多个数据

格式

  • 数据类型…参数名称

基本用例:

public class ArgsDemo4 {
    
    
    public static void main(String[] args) {
    
    
        //可变参数的小细节:
        //1.在方法的形参中最多只能写一个可变参数
        //可变参数,理解为一个大胖子,有多少吃多少
        //2.在方法的形参当中,如果出了可变参数以外,还有其他的形参,那么可变参数要写在最后
        getSum(1,2,3,4,5,6,7,8,9,10);
    }

    public static int getSum( int a,int...args) {
    
    
        return 0;
    }
}

3.Lambda表达式

3.1概述

​ Lambda表达式是Java编程语言中引入的一种语法特性,用于创建匿名函数或闭包。它允许您以更简洁的方式定义单个方法的接口实现。Lambda表达式在函数式编程和简化代码编写方面具有重要作用,特别是在集合处理和多线程编程中。

补充:

​ 此处的单个方法的接口实现,简称函数式接口。该接口有且仅有一个抽象方法。有且仅有一个抽象方法的接口叫做函数式接口,接口上方可以加**@Functionallnterface**注解。

image-20230321135748558

说明:

​ 在本方法中,简化new出来的接口为箭头函数

3.2作用

​ 把Lambda表达式理解为是一段可以传递的代码,它可以写出更简洁更灵活的代码,作为一种更紧凑的代码风格,使Java语言表达能力得到了提升。换句话说,简化函数式接口的匿名内部类的写法

3.3语法

省略核心:可推导,可省略

  • 参数类型可以省略不写。
  • 如果只有一个参数,参数类型可以省略,同时**()也可以省略**。
  • 如果Lambda表达式的方法体只有一行大括号,分号,return可以省略不写,需要同时省略。

3.4函数式编程

​ 函数式编程(Functional programming)是一种思想特点。面向对象∶先找对象,让对象做事情。

​ 函数式编程思想,忽略面向对象的复杂语法,强调做什么,而不是谁去做。

格式:

() ->{
    
     //( )对应着方法的形参 ->固定格式
    
} //{ } 对应着方法的方法体

说明:

  • Lambda表达式可以用来简化匿名内部类的书写
  • Lambda表达式只能简化函数式接口的匿名内部类的写法

4.函数式接口

​ 函数式接口是指只包含一个抽象方法的接口。在Java中,可以使用@FunctionalInterface注解来标记一个接口是函数式接口,这样做可以帮助编译器检查接口是否符合函数式接口的定义。

​ 函数式接口在Java 8中引入了Lambda表达式和方法引用等新特性。Lambda表达式可以将函数式接口作为参数进行传递,从而简化代码实现。Java标准库中的一些函数式接口包括ConsumerSupplierPredicateFunction等等,这些接口可以用于在Java中实现函数式编程的思想。

​ Functional interface means that you can use Lambad expressions or anonymous inner classes to pass, thereby simplifying code implementation.

5. Iterator source code analysis

image-20230420201035922

illustrate:

  • list.iterator(), a new iterator will be created each time it is called

  • hasNext(), determines whether the current pointer position is the same as the length of the iterated object

  • next(), first determines whether the add or delete method in the collection is used, then returns the element of the current index, and then moves the pointer to the next position

6.Equals() 方法和==` operator difference

equals()Methods are used to compare whether the values ​​of two objects are equal. Methods are usually overridden in custom classes equals()to implement custom equality comparison rules. By default, equals()methods are effectively equivalent to ==operators, which compare references to two objects for equality.

The operator is ==used to compare whether the references of two objects point to the same memory address. Two objects are equal if their references point to the same memory address, otherwise they are not equal.

String str1 = "hello";
String str2 = "hello";
String str3 = new String("hello");

System.out.println(str1 == str2); // true,因为它们指向同一字符串常量池中的对象
System.out.println(str1 == str3); // false,因为它们指向不同的内存地址
System.out.println(str1.equals(str3)); // true,因为它们的值相等

​ It should be noted that for basic data types, ==operators can be used to compare whether their values ​​are equal, because basic data types store their values ​​in memory rather than references. But for object types, ==operators compare object references, not values. equals()Therefore, you should use methods instead of operators when comparing objects for equality ==.

Guess you like

Origin blog.csdn.net/D_boj/article/details/132241235