Java advanced key analysis

Posted by zelot1980 on Sun, 02 Jan 2022 01:58:54 +0100

Singleton mode

Hungry Han Trilogy (waste of resources)

1. Privatize the constructor (resulting in that the external cannot directly new your class instance)

    private GirlFriend(String name) {
        this.name = name;
    }

2. Create directly within the class (create your own girlfriend in your own class)

private static GirlFriend gf = new GirlFriend("Honghong");

3. Provide a static public method to return gf object (static keyword is the premise)

public static GirlFriend getInstance(){
        return gf;
    }

Total code (the external can't new or create multiple objects, and the external can only get it by calling this method that returns the girlfriend object through this class)

public class single {
    public static void main(String[] args) {
        GirlFriend instance = GirlFriend.getInstance();
        System.out.println(instance);
    }
}
//There is a class, GirlFriend
//Only one girlfriend
class GirlFriend{
    private String name;
    //In order to return gf object in static method, modify it to static
    private static GirlFriend gf = new GirlFriend("Honghong");
    //Only one GirlFriend object can be created
    //step
    //1. Privatize the constructor
    //2. Create directly inside the class
    //3. Provide a static public method to return gf object
    private GirlFriend(String name) {
        this.name = name;
    }
    public static GirlFriend getInstance(){
        return gf;
    }
    @Override
    public String toString() {
        return "GirlFriend{" +
                "name='" + name + '\'' +
                '}';
    }
}

Lazy Trilogy (thread unsafe)

1. Privatization of constructor

    private Cat(String name) {
        this.name = name;
    }

2. Define a static attribute object

private static Cat cat;

3. Provide a public static method that can return a Cat object (in case of multiple threads, multiple threads new Cat at the same time, resulting in unsafe threads, an object can also be returned)

public static Cat getInstance(){
    if (cat == null){//If the cat object is not created
        cat = new Cat("Cutie");
    }
    return cat;
}

4. Lazy. Only when the user uses getInstance, the cat object will be returned. When calling again, the cat object created last time will be returned (they will reuse the existing object and are too lazy to create it)

Total code

public class single2 {
    public static void main(String[] args) {
        Cat instance = Cat.getInstance();
        System.out.println(instance);
    }
}
//I hope that only one cat can be created while the program is running
//Use singleton mode
class Cat{
    private String name;
    private static Cat cat;
    //step
    //1. Privatization of constructor
    //2. Define a static attribute object
    //3. Provide a public static method to return a Cat object
    //4. Lazy. Only when the user uses getInstance, the cat object will be returned. When calling again, the cat object created last time will be returned
    //Guaranteed monotonicity
    private Cat(String name) {
        this.name = name;
    }
    public static Cat getInstance(){
        if (cat == null){//If the cat object is not created
            cat = new Cat("Cutie");
        }
        return cat;
    }
    @Override
    public String toString() {
        return "Cat{" +
                "name='" + name + '\'' +
                '}';
    }
}

Exception - exception

First knowledge of exception code

(abnormal mathematical operation)

    public static void main(String[] args) {
        int num1 = 10;
        int num2 = 0;
        int res = num1 / num2;
        System.out.println("The program continues to run....");
    }

Solution - try catch

Catch exceptions to ensure that the program can continue to run (exception handling mechanism)

    public static void main(String[] args) {
        int num1 = 10;
        int num2 = 0;
        //1. num1 / num2 => 10 / 0
        //2. When num1 / num2 is executed, because num2 = 0, the program will throw an exception ArithmeticException
        //3. When an exception is thrown, the program exits and crashes, and the following code is not executed
        //4. Can you think of such a procedure? No, there should not be a non fatal problem that will lead to the collapse of the whole system
        //5. java designers provide an exception handling mechanism to solve this problem 
        // int res = num1 / num2;
        //If a programmer thinks that an exception may occur in a piece of code, he can use the try catch exception handling mechanism to solve it
        //So as to ensure the robustness of the program 
        //Select the code block - > check - > shortcut Ctrl + Alt + T - > check try catch
        //6. If exception handling is performed, the program can continue to execute even if an exception occurs
        try {
            int res = num1 / num2;
        } catch (Exception e) {
            //e.printStackTrace();
            System.out.println("Cause of abnormality=" + e.getMessage());
            //Output exception information}
            System.out.println("The program continues to run....");
        }
    }

Error and Exception

Anomaly system diagram

Common runtime exceptions

\1) Null pointerexception null pointer exception

\2) ArithmeticException mathematical operation exception

\3) ArrayIndexOutOfBoundsException array index out of bounds exception

\4) ClassCastException type conversion exception

\5) NumberFormatException the number format is incorrect. Exception []

\1) Null pointerexception null pointer exception

    public static void main(String[] args) {
        String name = null;
        System.out.println(name.length());
    }

\2)ArithmeticException mathematical operation exception

    public static void main(String[] args) {
        int num1 = 10;
        int num2 = 0;
        int res = num1 / num2;
        System.out.println("The program continues to run....");
    }

\3) ArrayIndexOutOfBoundsException array index out of bounds exception

    public static void main(String[] args) {
        int[] arr = {1, 2, 3};
        for (int i = 0; i <= arr.length; i++) {
            System.out.println(arr[i]);
        }
    }

\4) ClassCastException type conversion exception

    public static void main(String[] args) {
        A b = new B(); //Upward transformation
        B b2 = (B) b;//Downward transformation, here is OK
        C c2 = (C) b;//ClassCastException is thrown here
    }
class A { }
class B extends A { }
class C extends A { }

\5) NumberFormatException number format is incorrect exception

    public static void main(String[] args) {
        String name = "Xiao Wang learns programming"; //Convert String to int
        int num = Integer.parseInt(name);//Throw NumberFormatException
        System.out.println(num);//1234
    }

Compilation exception

FileNotFoundException

public static void main(String[] args) {
    try {
        FileInputStream fis;
        fis = new FileInputStream("d:\\aa.jpg");
        int len;
        while ((len = fis.read()) != -1) {
            System.out.println(len);
        }
        fis.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

try-catch-finally

public static void main(String[] args) {
    //ctrl + atl + t
    //1. If an exception occurs, the code after the exception will not be executed and directly enters the catch block
    //2. If the exception does not occur, the code blocks of try will be executed sequentially and will not enter the catch
    //3. If you want to execute a piece of code (such as closing a connection, releasing resources, etc.) regardless of whether an exception occurs or not, use the following code - finally
    try {
        String str = "Xiao Wang";
        int a = Integer.parseInt(str);
        System.out.println("Number:" + a);
    } catch (NumberFormatException e) {
        System.out.println("Abnormal information=" + e.getMessage());
    } finally {
        System.out.println("finally The code block is executed...");
    }
    System.out.println("The program continues...");
}

Try catch finally execution sequence summary

Integer class: unpacking and packing

Transformation and principle of packaging class and basic data

    public static void main(String[] args) {
        //Demonstrate boxing and unpacking of int < -- > integer
        //Before jdk5, it is manual packing and unpacking
        //Manual boxing int - > integer
        int n1 = 100;
        Integer integer = new Integer(n1);
        Integer integer1 = Integer.valueOf(n1);
        //Manual unpacking
        // Integer -> int
        int i = integer.intValue();
        //After jdk5, you can automatically pack and unpack 
        int n2 = 200;
        // Auto boxing int - > integer 
        Integer integer2 = n2;
        // The bottom layer uses integer valueOf(n2) 
        // Automatic unpacking integer - > int 
        int n3 = integer2;
        // The bottom layer still uses the intValue() method
    }

Interview questions

Conversion between wrapper type and String type

public static void main(String[] args) {
        //Wrapper class (integer) - > string
        Integer i = 100;
        //Automatic packing
        //Mode 1
        String str1 = i + "";
        //Mode 2
        String str2 = i.toString();
        //Mode 3
        String str3 = String.valueOf(i);
        //String - > wrapper class (Integer)
        String str4 = "12345";
        Integer i2 = Integer.parseInt(str4);
        //Use to auto box
        Integer i3 = new Integer(str4);
        //constructor 
        System.out.println("ok~~");
    }

Integer interview questions

public static void main(String[] args) {
        Integer i = new Integer(1);
        Integer j = new Integer(1);
        System.out.println(i == j); //False
        //Therefore, we mainly look at the range - 128 ~ 127, which is a direct return
        /*
        //1. If i is in integercache low(-128)~IntegerCache. High (127) is returned directly from the array
        //2. If it is not - 128 ~ 127, directly new Integer(i)
        public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
        }
        */
        Integer m = 1; //Underlying integer valueOf(1); ->  Read source code
        Integer n = 1;//Underlying integer valueOf(1);
        System.out.println(m == n); //T
        //Therefore, we mainly look at the range - 128 ~ 127, which is a direct return
        //, otherwise, new Integer(xx);
        Integer x = 128;//Underlying integer valueOf(1);
        Integer y = 128;//Underlying integer valueOf(1);
        System.out.println(x == y);//False
    }
public static void main(String[] args) {
    //Example 1
    Integer i1 = new Integer(127);
    Integer i2 = new Integer(127);
    System.out.println(i1 == i2);//F
    //Example 2
    Integer i3 = new Integer(128);
    Integer i4 = new Integer(128);
    System.out.println(i3 == i4);//F
    //Example 3
    Integer i5 = 127;//Underlying integer valueOf(127)
    Integer i6 = 127;//-128~127
    System.out.println(i5 == i6); //T
    //Example 4
    Integer i7 = 128;
    Integer i8 = 128;
    System.out.println(i7 == i8);//F
    //Example 5
    Integer i9 = 127; //Integer.valueOf(127)
    Integer i10 = new Integer(127);
    System.out.println(i9 == i10);//F
    //Example 6
    Integer i11=127;
    int i12=127;
    //There are only basic data types, and the judgment is
    //Are the values the same
    System.out.println(i11==i12); //T
    //Example 7
    Integer i13=128;
    int i14=128;
    System.out.println(i13==i14);//T
}

String class

Understanding and creating objects of String class

public static void main(String[] args) {
    //1. The string object is used to save a string, that is, a set of character sequences
    //2."jack" string constant, a character sequence enclosed in double quotation marks
    //3. The characters of the string are encoded by Unicode characters. One character (regardless of letters or Chinese characters) occupies two bytes
    //4. The string class has many constructors, which are overloaded
    //Commonly used are String s1 = new String();
    //String s2 = new String(String original);
    //String s3 = new String(char[] a);
    //String s4 = new String(char[] a,int startIndex,int count)
    //String s5 = new String(byte[] b)
    //5. The String class implements the interface Serializable [String can be serialized: it can be transmitted over the network]
    //Interface Comparable [String object can compare size]
    //6. String is a final class and cannot be inherited by other classes
    //7. String has the attribute private final char value []; Used to store string contents
    //8. It must be noted that value is a final type and cannot be modified (requires skill): that is, value cannot point to
    //New address, but the content of a single character can be changed
    String name = "jack";
    name = "tom";
    System.out.println(name);
    final char[] value = {'a','b','c'};
    char[] v2 = {'t','o','m'};
    value[0] = 'H';
    //value = v2;  The value address cannot be modified
}

There are two ways to create String objects

Differences between two methods of creating String objects

Interview questions

Common methods of String class

public static void main(String[] args) {
    //1. equals has been mentioned earlier Compare whether the contents are the same, case sensitive
    String str1 = "hello";
    String str2 = "Hello";
    System.out.println(str1.equals(str2));//F
    // 2.equalsIgnoreCase ignores case to judge whether the contents are equal
    String username = "johN";
    if ("john".equalsIgnoreCase(username)) {
        System.out.println("Success!");
    } else {
        System.out.println("Failure!");
    }
    // 3.length gets the number of characters and the length of the string
    System.out.println("Xiao Wang".length());
    // 4.indexOf gets the index of the first occurrence of the character in the string object. The index starts from 0. If it is not found, it returns - 1
    String s1 = "wer@terwe@g";
    int index = s1.indexOf('@');
    System.out.println(index);// 3
    System.out.println("weIndex=" + s1.indexOf("we"));//0
    // 5.lastIndexOf gets the index of the last occurrence of the character in the string. The index starts from 0. If it is not found, it returns - 1
    s1 = "wer@terwe@g@";
    index = s1.lastIndexOf('@');
    System.out.println(index);//11
    System.out.println("ter Location of=" + s1.lastIndexOf("ter"));//4
    // 6.substring intercepts substrings in the specified range
    String name = "hello,Zhang San";
    //Below is name Substring (6) intercepts all subsequent contents from index 6
    System.out.println(name.substring(6));//Intercept the following characters
    //name.substring(0,5) means to intercept from index 0 to index 5-1 = 4
    System.out.println(name.substring(2,5));//llo
}

public static void main(String[] args) {
    // 1. Convert touppercase to uppercase
    String s = "heLLo";
    System.out.println(s.toUpperCase());//HELLO
    // 2.toLowerCase
    System.out.println(s.toLowerCase());//hello
    // 3.concat splice string
    String s1 = "Baoyu";
    s1 = s1.concat("Lin Daiyu").concat("Xue Baochai").concat("together");
    System.out.println(s1);//Baoyu Lin Daiyu Xue Baochai together
    // 4.replace replace characters in string
    s1 = "Baoyu and Lin Daiyu Lin Daiyu Lin Daiyu";
    //In s1, replace all Lin Daiyu with Xue Baochai
    // Lao Han's interpretation: s1 After the replace () method is executed, the returned result is replaced// Note that there is no effect on s1
    String s11 = s1.replace("Baoyu", "jack");
    System.out.println(s1);//Baoyu and Lin Daiyu Lin Daiyu Lin Daiyu
    System.out.println(s11);//jack and Lin Daiyu Lin Daiyu Lin Daiyu
    // 5.split split split string. For some split characters, we need to escape, such as \ \
    String poem = "Hoe standing grain gradually pawning a midday,Sweat drops under the grass,Who knows Chinese food,Every single grain is the fruit of hard work.";
    // 1. Divide the poem based on the, and return an array
    // 2. When splitting a string, if there are special characters, you need to add an escape character\
    String[] split = poem.split(",");
    poem = "E:\\aaa\\bbb";
    split = poem.split("\\\\");
    System.out.println("==Split content===");
    for (int i = 0; i < split.length; i++) {
        System.out.println(split[i]);
    }
    // 6.toCharArray to character array
    s = "happy";
    char[] chs = s.toCharArray();
    for (int i = 0; i < chs.length; i++) {
        System.out.println(chs[i]);
    }
    // 7.compareTo compare the size of two strings. If the former is large,
    // Returns a positive number. If the latter is large, it returns a negative number. If it is equal, it returns 0
    // (1) If the length is the same and each character is the same, 0 is returned
    // (2) If the length is the same or different, but the comparison can be case sensitive
    // If (C1! = C2) is returned{
    // return c1 - c2;
    // }
    // (3) If the previous parts are the same, STR1. 0 is returned len - str2. len
    String a = "jcck";// len = 3
    String b = "jack";// len = 4
    System.out.println(a.compareTo(b)); // The return value is the value of 'c' - 'a' = 2
    // 8.format string
    /* Placeholders are:
     * %s String% c character% d integer%. 2f floating point
     */
    String name = "john";
    int age = 10;
    double score = 56.857;
    char gender = 'male';
    //Splice all the information into a string
    String info = "My name is" + name + "Age is" + age + ",The result is" + score + "Gender is" + gender + ". I hope you like me!";
    
    System.out.println(info);
    //1.% s,% D,%. 2F,% C are called placeholders
    //2. These placeholders are replaced by the following variables
    //3.% s indicates that it is replaced by a string
    //4.% d is an integer to replace
    //5.%. 2F means to replace with decimal. After replacement, only two decimal places will be reserved and rounded
    //6.%c replace with char type
    String formatStr = "My name is%s Age is%d,The result is%.2f Gender is%c.I hope you like me!";
    String info2 = String.format(formatStr, name, age, score, gender);
    System.out.println("info2=" + info2);
}

StringBuffer and StringBuilder

StringBuffer class Basic introduction

public static void main(String[] args) {
        //1. The direct parent class of StringBuffer is AbstractStringBuilder
        //2. StringBuffer implements Serializable, that is, the objects of StringBuffer can be serialized
        //3. AbstractStringBuilder has the attribute char[] value in the parent class, not final
        // The value array stores the string contents and leads out the values stored in the heap
        //4. StringBuffer is a final class and cannot be inherited
        //5. Because the StringBuffer character content has char[] value, all are changing (add / delete)
        // It is not necessary to change the address every time (that is, it is not necessary to create a new object every time), so the efficiency is higher than that of String
        StringBuffer stringBuffer = new StringBuffer("hello");
    }

String VS StringBuffer

String and StringBuffer are converted to each other

    public static void main(String[] args) {
        //See String - > StringBuffer
        String str = "hello tom";
        //Mode 1 using constructors
        //Note: the returned string buffer object has no effect on str itself
        StringBuffer stringBuffer = new StringBuffer(str);
        //Method 2 uses the append method
        StringBuffer stringBuffer1 = new StringBuffer();
        stringBuffer1 = stringBuffer1.append(str);
        //Look at StringBuffer - > string
        StringBuffer stringBuffer3 = new StringBuffer("Xiao Wang learns programming");
        //Method 1: use the toString method provided by StringBuffer
        String s = stringBuffer3.toString();
        //Method 2: use the constructor to do it
        String s1 = new String(stringBuffer3);
    }

Common methods of StringBuffer class

public static void main(String[] args) {
        StringBuffer s = new StringBuffer("hello");
        //increase
        s.append(',');// "hello,"
        s.append("Zhang Sanfeng");//"hello, Zhang Sanfeng"
        s.append("Zhao Min").append(100).append(true).append(10.5);//"hello, Zhang Sanfeng, Zhao Min 100true10.5" system out. println(s);// "hello, Zhang Sanfeng, Zhao Min 100true10.5"
        //Delete
        /*
         * Delete characters at index > = start & & < end
         * Interpretation: delete characters 11 ~ 14 [11, 14)
         */
        s.delete(11, 14);
        System.out.println(s);//"hello, Zhang Sanfeng, Zhao Min, true10.5"
        //change
        //Interpretation, use Zhou Zhiruo to replace the characters of index 9-11 [9,11)
        s.replace(9, 11, "Zhou Zhiruo");
        System.out.println(s);//"hello, Zhang Sanfeng, Zhou Zhiruo, true10.5"
        //Finds the index of the specified substring at the first occurrence of the string. If it is not found, it returns - 1
        int indexOf = s.indexOf("Zhang Sanfeng");
        System.out.println(indexOf);//6
        //insert
        //Lao Han interpreted that "Zhao Min" was inserted at the position with index 9, and the content with index 9 was automatically moved back
        s.insert(9, "Zhao Min");
        System.out.println(s);//"hello, Zhang Sanfeng, Zhao Min, Zhou Zhiruo, true10.5"
        //length
        System.out.println(s.length());//22
        System.out.println(s);
    }

StringBuffer class classroom test questions

public static void main(String[] args) {
    String str = null;// ok
    StringBuffer sb = new StringBuffer(); //ok
    sb.append(str);//Depending on the source code, the bottom layer calls the appendNull of AbstractStringBuilder
    System.out.println(sb.length());//4
    System.out.println(sb);//null
    //The following constructor will throw NullpointerException
    StringBuffer sb1 = new StringBuffer(str);//Look at the underlying source code super(str.length() + 16);
    System.out.println(sb1);
}

StringBuffer class classroom test question 2

public static void main(String[] args) {
    /*
    Enter the product name and price, and ask to print the effect example, using the method learned earlier:
    Commodity name commodity price mobile phone 123564.59 / / for example, price 3456789.88
    Requirement: every three digits in front of the decimal point of the price shall be separated by commas in the output.
    Train of thought analysis
    1. Define a Scanner object to receive the price (String) entered by the user
    2. If you want to use the insert of StringBuffer, you need to convert String to StringBuffer
    3. Then use relevant methods to process the string
    code implementation
    */
    //new Scanner(System.in)
    String price = "8123564.59";
    StringBuffer sb = new StringBuffer(price);
    //First complete the simplest implementation 123564.59
    //Find the index of the decimal point, and then insert it in the first 3 digits of the position
    // int i = sb.lastIndexOf(".");
    // sb = sb.insert(i - 3, ",");
    //The above two steps need to be processed in a loop, which is correct
    for (int i = sb.lastIndexOf(".") - 3; i > 0; i -= 3) {
        sb = sb.insert(i, ",");
    }
    System.out.println(sb);//8,123,564.59
}

StringBuilder class Basic introduction

public static void main(String[] args) {
    //1. The direct parent class of StringBuffer is AbstractStringBuilder
    //2. StringBuffer implements Serializable, that is, the objects of StringBuffer can be serialized
    //3. AbstractStringBuilder has the attribute char[] value in the parent class, not final
    // The value array stores the string contents and leads out the values stored in the heap
    //4. StringBuffer is a final class and cannot be inherited
    //5. Because the StringBuffer character content has char[] value, all are changing (add / delete)
    // It is not necessary to change the address every time (that is, it is not necessary to create a new object every time), so the efficiency is higher than that of String
    StringBuffer stringBuffer = new StringBuffer("hello");
}

StringBuilder common methods

public static void main(String[] args) {
    //1. StringBuilder inherits AbstractStringBuilder class
    //2. Serializable is implemented, which shows that the StringBuilder object can be serialized (the object can be transmitted over the network and saved to a file)
    //3. StringBuilder is a final class and cannot be inherited
    //4. The character sequence of the StringBuilder object is still the char[] value stored in its parent class AbstractStringBuilder;
    // Therefore, the character sequence is in the heap
    //5. The StringBuilder method is not mutually exclusive, that is, there is no synchronized keyword, so it is used in the case of single thread
    // StringBuilder
    StringBuilder stringBuilder = new StringBuilder();
}

Comparison of String, StringBuffer and StringBuilder

StringVsStringBufferVsStringBuilder.java efficiency: StringBuilder > StringBuffer > string

public static void main(String[] args) {
    long startTime = 0L;
    long endTime = 0L;
    StringBuffer buffer = new StringBuffer("");
    startTime = System.currentTimeMillis();
    for (int i = 0; i < 80000; i++) {//StringBuffer splicing 20000 times
        buffer.append(String.valueOf(i));
    }
    endTime = System.currentTimeMillis();
    System.out.println("StringBuffer Execution time of:" + (endTime - startTime));
    StringBuilder builder = new StringBuilder("");
    startTime = System.currentTimeMillis();
    for (int i = 0; i < 80000; i++) {//StringBuilder splicing 20000 times
        builder.append(String.valueOf(i));
    }
    endTime = System.currentTimeMillis();
    System.out.println("StringBuilder Execution time of:" + (endTime - startTime));
    String text = "";
    startTime = System.currentTimeMillis();
    for (int i = 0; i < 80000; i++) {//String splicing 20000
        text = text + i;
    }
    endTime = System.currentTimeMillis();
    System.out.println("String Execution time of:" + (endTime - startTime));
}

Selection of String, StringBuffer and StringBuilder

List | ArrayList | Vector

List interface and common methods

Basic introduction to List interface

@SuppressWarnings({"all"})
public static void main(String[] args) {
    //1. The elements in the list collection class are orderly (i.e. the addition order is consistent with the extraction order) and repeatable [case]
    List list = new ArrayList();
    list.add("jack");
    list.add("tom");
    list.add("mary");
    list.add("hsp");
    list.add("tom");
    System.out.println("list=" + list);
    //2. Each element in the list set has its corresponding sequential index, that is, it supports index
    // The index starts at 0
    System.out.println(list.get(3));//hsp
}

Common methods of List interface

@SuppressWarnings({"all"})
public static void main(String[] args) {
    List list = new ArrayList();
    list.add("Zhang Sanfeng");
    list.add("Jia Baoyu");
    // void add(int index, Object ele): inserts an ele element at the index position
    //Insert an object at index = 1
    list.add(1, "oracle ");
    System.out.println("list=" + list);
    // boolean addAll(int index, Collection eles): add all elements in eles from the index position
    List list2 = new ArrayList();
    list2.add("jack");
    list2.add("tom");
    list.addAll(1, list2);
    System.out.println("list=" + list);
    // Object get(int index): gets the element at the specified index position
    //Yes
    // int indexOf(Object obj): returns the position where obj first appears in the collection
    System.out.println(list.indexOf("tom"));//2
    // int lastIndexOf(Object obj): returns the last occurrence of obj in the current collection
    list.add("oracle ");
    System.out.println("list=" + list);
    System.out.println(list.lastIndexOf("oracle "));
    // Object remove(int index): removes the element at the specified index position and returns this element
    list.remove(0);
    System.out.println("list=" + list);
    // Object set(int index, Object ele): sets the element at the specified index position to ele, which is equivalent to replacement list.set(1, "Mary");
    System.out.println("list=" + list);
    // List subList(int fromIndex, int toIndex): returns a subset from fromIndex to toIndex
    // Note the returned subset fromindex < = sublist < toindex
    List returnlist = list.subList(0, 2);
    System.out.println("returnlist=" + returnlist);
}

List interface classroom exercises

@SuppressWarnings({"all"})
public static void main(String[] args) {
    /*
    Add more than 10 elements (such as String "hello") and insert an element "Han Shunping education" in position 2,
    Get the fifth element, delete the sixth element, modify the seventh element, and traverse the collection using an iterator,
    Requirement: use the implementation class ArrayList of List to complete.
     */
    List list = new ArrayList();
    for (int i = 0; i < 12; i++) {
        list.add("hello" + i);
    }
    System.out.println("list=" + list);
    //Insert an element "Han Shunping education" in position 2
    list.add(1, "Han Shunping Education");
    System.out.println("list=" + list);
    //Get the 5th element
    System.out.println("Fifth element=" + list.get(4));
    //Delete the 6th element
    list.remove(5);
    System.out.println("list=" + list);
    //Modify the 7th element
    list.set(6, "Romance of the Three Kingdoms");
    System.out.println("list=" + list);
    //Traversing collections using iterators
    Iterator iterator = list.iterator();
    while (iterator.hasNext()) {
        Object obj = iterator.next();
        System.out.println("obj=" + obj);
    }
}

Three traversal methods of List [ArrayList, LinkedList,Vector]

@SuppressWarnings({"all"})
public static void main(String[] args) {
    //The implementation subclass of the List interface is Vector LinkedList
    //List list = new ArrayList();
    //List list = new Vector();
    List list = new LinkedList();
    list.add("jack");
    list.add("tom");
    list.add("Yu-Shiang Shredded Pork");
    list.add("Beijing roast duck");
    //ergodic
    //1. Iterator
    Iterator iterator = list.iterator();
    while (iterator.hasNext()) {
        Object obj = iterator.next();
        System.out.println(obj);
    }
    System.out.println("=====enhance for=====");
    //2. Enhance for
    for (Object o : list) {
        System.out.println("o=" + o);
    }
    System.out.println("=====ordinary for====");
    //3. Use common for
    for (int i = 0; i < list.size(); i++) {
        System.out.println("object=" + list.get(i));
    }
}

Class exercise 2 of implementation class

public static void main(String[] args) {
    //List list = new ArrayList();
    List list = new LinkedList();
    //List list = new Vector();
    list.add(new Book("The Dream of Red Mansion", "Cao Xueqin", 100));
    list.add(new Book("Journey to the West", "Wu Chengen", 10));
    list.add(new Book("Water Margin", "Shi Naian", 19));
    list.add(new Book("three countries", "Luo Guanzhong", 80));
    //list.add(new Book("journey to the west", "Wu Chengen", 10));
    //How to sort collections
    //ergodic
    for (Object o : list) {
        System.out.println(o);
    }
    //Bubble sorting
    sort(list);
    System.out.println("==After sorting==");
    for (Object o : list) {
        System.out.println(o);
    }
}

//Static method
//The price requirement is from small to large
public static void sort(List list) {
    int listSize = list.size();
    for (int i = 0; i < listSize - 1; i++) {
        for (int j = 0; j < listSize - 1 - i; j++) {
            //Take out the object Book
            Book book1 = (Book) list.get(j);
            Book book2 = (Book) list.get(j + 1);
            if (book1.getPrice() > book2.getPrice()) {//exchange
                list.set(j, book2);
                list.set(j + 1, book1);
            }
        }
    }
}

ArrayList underlying structure and source code analysis

Precautions for ArrayList

Source code analysis of the underlying operation mechanism of ArrayList (key and difficult points)

public static void main(String[] args) {
    //Lao Han interpretation source code
    //Note, note, note that by default, the data displayed by Debug is simplified. If you want to see the complete data
    //Settings are required// Creating an ArrayList object using a parameterless constructor
    //ArrayList list = new ArrayList();
    ArrayList list = new ArrayList(8);
    //Use for to add 1-10 data to the list set
    for (int i = 1; i <= 10; i++) {
        list.add(i);
    }
    //Use for to add 11-15 data to the list set
    for (int i = 11; i <= 15; i++) {
        list.add(i);
    }
    list.add(100);
    list.add(200);
    list.add(null);
}

[external chain picture transfer failed. The source station may have anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-joznbm1j-1640872377264)( https://gitee.com/wanghanhao/haostudent/raw/master/image-20211230214353275.png )]

Vector underlying structure and source code analysis

Basic introduction of Vector

public static void main(String[] args) {
    //Parameterless constructor
    //Parametric construction
    Vector vector = new Vector(8);
    for (int i = 0; i < 10; i++) {
        vector.add(i);
    }
    vector.add(100);
    System.out.println("vector=" + vector);
    //Lao Han interpretation source code
    //1. new Vector() bottom layer
    /*
    public Vector() {
        this(10);
    }
    Supplement: if it is Vector vector = new Vector(8);
    How to walk:
    public Vector(int initialCapacity) {
        this(initialCapacity, 0);
    }
    2. vector.add(i)
    2.1 //The following method adds data to the vector collection
    public synchronized boolean add(E e) {
        modCount++;
        ensureCapacityHelper(elementCount + 1);
        elementData[elementCount++] = e;
        return true;
    }
    2.2 //Determine whether capacity expansion is required: mincapacity - elementdata length>0
    private void ensureCapacityHelper(int minCapacity) {
        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
        grow(minCapacity);
    }
    2.3 //If the required array size is not enough, expand the capacity, and the expansion algorithm
    //newCapacity = oldCapacity + ((capacityIncrement > 0) ?
    // capacityIncrement : oldCapacity);
    //That's double the expansion private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
    capacityIncrement : oldCapacity);
    if (newCapacity - minCapacity < 0)
    newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
    newCapacity = hugeCapacity(minCapacity);
    elementData = Arrays.copyOf(elementData, newCapacity);
    }
    */
}

Comparison of Vector and ArrayList

LinkedList underlying structure

Comprehensive description of LinkedList

Underlying operating mechanism of LinkedList

public static void main(String[] args) {
    //Simulate a simple two-way linked list
    Node jack = new Node("jack");
    Node tom = new Node("tom");
    Node hsp = new Node("Lao Han");
    //Connect three nodes to form a two-way linked list
    //jack -> tom -> hsp
    jack.next = tom;
    tom.next = hsp;
    //hsp -> tom -> jack
    hsp.pre = tom;
    tom.pre = jack;
    Node first = jack;//Let the first reference point to jack, which is the head node of the two-way linked list
    Node last = hsp; //Let the last reference point to hsp, which is the tail node of the two-way linked list
    //Demonstration, traversal from beginning to end
    System.out.println("===Traversal from beginning to end===");
    while (true) {
        if (first == null) {
            break;
        }
        //Output first information
        System.out.println(first);
        first = first.next;
    }
    //Demonstration, traversal from end to end
    System.out.println("====End to end traversal====");
    while (true) {
        if (last == null) {
            break;
        }
        //Output last information
        System.out.println(last);
        last = last.pre;
    }
    //Demonstrate how convenient it is to add objects / data to the linked list
    //The requirement is to insert an object smith directly in tom ----------- Lao Han
    //1. First create a Node, whose name is smith
    Node smith = new Node("smith");
    //Now add smith to the two-way linked list
    smith.next = hsp;
    smith.pre = tom;
    hsp.pre = smith;
    tom.next = smith;
    //Let first point to jack again
    first = jack;//Let the first reference point to jack, which is the head node of the two-way linked list
    System.out.println("===Traversal from beginning to end===");
    while (true) {
        if (first == null) {
            break;
        }
        //Output first information
        System.out.println(first);
        first = first.next;
    }
    last = hsp; //Let last point to the last node again
    //Demonstration, traversal from end to end
    System.out.println("====End to end traversal====");
    while (true) {
        if (last == null) {
            break;
        }
        //Output last information
        System.out.println(last);
        last = last.pre;
    }
}
//Define a Node class, and the Node object represents a Node of the bidirectional linked list
class Node {
    public Object item; //Real data storage
    public Node next; //Point to the next node
    public Node pre; //Point to previous node
    public Node(Object name) {
        this.item = name;
    }
    public String toString() {
        return "Node name=" + item;
    }
}

Cases of addition, deletion, modification and query of LinkedList

public static void main(String[] args) {
    LinkedList linkedList = new LinkedList();
    linkedList.add(1);
    linkedList.add(2);
    linkedList.add(3);
    System.out.println("linkedList=" + linkedList);
    //Demonstrate a method of deleting nodes
    linkedList.remove(); // The first node is deleted by default
    //linkedList.remove(2);
    System.out.println("linkedList=" + linkedList);
    //Modify a node object
    linkedList.set(1, 999);
    System.out.println("linkedList=" + linkedList);
    //Get a node object
    //get(1) is the second object to get the bidirectional linked list
    Object o = linkedList.get(1);
    System.out.println(o);//999
    //Because LinkedList implements the List interface and traversal mode
    System.out.println("===LinkeList Traversal iterator====");
    Iterator iterator = linkedList.iterator();
    while (iterator.hasNext()) {
        Object next = iterator.next();
        System.out.println("next=" + next);
    }
    System.out.println("===LinkeList Ergodic enhancement for====");
    for (Object o1 : linkedList) {
        System.out.println("o1=" + o1);
    }
    System.out.println("===LinkeList Ergodic ordinary for====");
    for (int i = 0; i < linkedList.size(); i++) {
        System.out.println(linkedList.get(i));
    }
    //Old Korean source code reading
    /* 1. LinkedList linkedList = new LinkedList();
    public LinkedList() {}
    2. At this time, the linklist property first = null, last = null
    3. Execute add
    public boolean add(E e) {
        linkLast(e);
        return true;
    }
    4.Add the new node to the end of the bidirectional linked list
    void linkLast(E e) {
        final Node<E> l = last;
        final Node<E> newNode = new Node<>(l, e, null);
        last = newNode;
        if (l == null)
            first = newNode;
        else
            l.next = newNode;
        size++;
        modCount++;
    }
    */
    /*
    Lao Han reads the source code LinkedList remove(); //  The first node is deleted by default
    1. Execute removeFirst
    public E remove() {
    return removeFirst();
    }
    2. implement
    public E removeFirst() {
    final Node<E> f = first;
    if (f == null)
    throw new NoSuchElementException();
    return unlinkFirst(f);
    }
    3. Execute unlinkFirst to remove the first node of the two-way linked list pointed to by f
    private E unlinkFirst(Node<E> f) {
    // assert f == first && f != null;
    final E element = f.item;
    final Node<E> next = f.next;
    f.item = null;
    f.next = null; // help GC
    first = next;
    if (next == null)
    last = null;
    else
    next.prev = null;
    size--;
    modCount++;
    return element;
    }
    */
}

ArrayList and LinkedList comparison

vv

HashSet and LinkedHashSet

Set interface and common methods

Basic introduction to Set interface

Common methods of Set interface

Like the List interface, the Set interface is also a sub interface of the Collection. Therefore, the common methods are the same as the Collection interface

Traversal mode of Set interface

Examples of common methods of Set interface

public static void main(String[] args) {
    //Lao Han's interpretation
    //1. Explain the method of Set interface with the implementation class HashSet of Set interface
    //2. The object of the implementation class of the Set interface (Set interface object) cannot store duplicate elements, and a null can be added
    //3. The data stored in the set interface object is out of order (that is, the order of adding is inconsistent with the order of taking out)
    //4. Note: Although the order of taking out is not the order of adding, it is fixed
    Set set = new HashSet();
    set.add("john");
    set.add("lucy");
    set.add("john");//repeat
    set.add("jack");
    set.add("hsp");
    set.add("mary");
    set.add(null);//
    set.add(null);//Add null again
    for (int i = 0; i < 10; i++) {
        System.out.println("set=" + set);
    }
    //ergodic
    //Method 1: use iterators
    System.out.println("=====Using Iterators ====");
    Iterator iterator = set.iterator();
    while (iterator.hasNext()) {
        Object obj = iterator.next();
        System.out.println("obj=" + obj);
    }
    set.remove(null);
    //Mode 2: enhanced for
    System.out.println("=====enhance for====");
    for (Object o : set) {
        System.out.println("o=" + o);
    }
    //The set interface object cannot be obtained by index
}

Set interface implementation class - HashSet

Comprehensive description of HashSet

public static void main(String[] args) {
    //Lao Han's interpretation
    //1. The source code of the constructor
    /*
    public HashSet() {
        map = new HashMap<>();
    }
    2. HashSet Null can be stored, but there can only be one null, that is, the element cannot be repeated
    */
    Set hashSet = new HashSet();
    hashSet.add(null);
    hashSet.add(null);
    System.out.println("hashSet=" + hashSet);
}

HashSet case description

public static void main(String[] args) {
    HashSet set = new HashSet();
    //explain
    //1. After executing the add method, a boolean value will be returned
    //2. If the addition is successful, return true; otherwise, return false
    //3. You can specify which object to delete through remove
    System.out.println(set.add("john"));//T
    System.out.println(set.add("lucy"));//T
    System.out.println(set.add("john"));//F
    System.out.println(set.add("jack"));//T
    System.out.println(set.add("Rose"));//T
    set.remove("john");
    System.out.println("set=" + set);//3
    set = new HashSet();
    System.out.println("set=" + set);//0
    //4 can't HashSet add the same element / data?
    set.add("lucy");//Added successfully
    set.add("lucy");//Can't join
    set.add(new Dog("tom"));//OK
    set.add(new Dog("tom"));//Ok
    System.out.println("set=" + set);
    //It's deepening Very classic interview questions
    //Look at the source code and do analysis. First leave a hole for the little partner. After talking about the source code, you will know
    //Go to his source code, that is, what happened to add? = > Underlying mechanism set.add(new String("hsp"));//ok
    set.add(new String("hsp"));//I can't join System.out.println("set=" + set);
}
class Dog { //The Dog class is defined
    private String name;

    public Dog(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                '}';
    }
}

HashSet underlying mechanism description

public static void main(String[] args) {
    HashSet hashSet = new HashSet();
    hashSet.add("java");//At this position, the first add analysis is completed hashSet.add("php");// At this position, the second add analysis is completed
    hashSet.add("java");
    System.out.println("set=" + hashSet);
    /*
    Lao Han's interpretation of the source code of HashSet
    1. Execute HashSet()
    public HashSet() {
        map = new HashMap<>();
    }
    2. Execute add()
    public boolean add(E e) {//e = "java"
        return map.put(e, PRESENT)==null;//(static) PRESENT = new Object();
    }
    3.Execute put(), which will execute hash(key) to get the hash value corresponding to the key, and the algorithm H = key hashCode()) ^ (h >>> 16)
    public V put(K key, V value) {//key = "java" value = PRESENT share
        return putVal(hash(key), key, value, false, true);
    }
    4.Execute putVal
    final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) {
        Node<K,V>[] tab; Node<K,V> p; int n, i; //Auxiliary variables are defined
        //table It is an array of HashMap. The type is Node []
        //if Statement indicates if the current table is null or size = 0
        //This is the first expansion to 16 spaces
        if ((tab = table) == null || (n = tab.length) == 0)
            n = (tab = resize()).length;
        //(1)According to the key, get the hash to calculate which index position the key should be stored in the table
        //And assign the object at this position to p
        //(2)Determine whether p is null
        //(2.1) If p is null, it means that the element has not been stored, and a node is created (key = "Java", value = present)
        //(2.2) Put it in this position tab[i] = newNode(hash, key, value, null)
        if ((p = tab[i = (n - 1) & hash]) == null)
            tab[i] = newNode(hash, key, value, null);
        else {
            //A development tip: when you need local variables (auxiliary variables), create
            Node<K,V> e; K k; //
            //If the first element of the linked list corresponding to the current index position is the same as the hash value of the key to be added
            //And meet one of the following two conditions:
            //(1) The key to be added and the key of the Node pointed to by p are the same object
            //(2) p The equals() of the key of the Node pointed to is the same as the key to be added after comparison
            //You can't join
     if (p.hash == hash &&((k = p.key) == key || (key != null && key.equals(k))))
            e = p;
    //Then judge whether p is a red black tree. / / if it is a red black tree, call putTreeVal to add it
    else if (p instanceof TreeNode)
        e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
    else {//If the table corresponds to the index position and is already a linked list, use the for loop comparison
        //(1) If it is different from each element of the linked list in turn, it will be added to the end of the linked list
        // Note that after adding elements to the linked list, you can immediately judge whether the linked list has reached 8 nodes
        // , Call treeifyBin() to tree the current linked list (turn it into a red black tree)
        // Note that when turning to red black tree, judge the conditions
        // if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY(64))
        // resize();
        // If the above conditions are true, expand the table first// Only when the above conditions are not tenable can it be transformed into red black tree
        //(2) In the process of comparing with each element of the linked list in turn, if there is the same situation, break directly
    for (int binCount = 0; ; ++binCount) {
        if ((e = p.next) == null) {
            p.next = newNode(hash, key, value, null);
            if (binCount >= TREEIFY_THRESHOLD(8) - 1) // -1 for 1st
                treeifyBin(tab, hash);
            break;
    }
    if (e.hash == hash &&
    ((k = e.key) == key || (key != null && key.equals(k))))
            break;
        p = e;
        }
    }
    if (e != null) { // existing mapping for key
        V oldValue = e.value;
    if (!onlyIfAbsent || oldValue == null)
        e.value = value;
        afterNodeAccess(e);
        return oldValue;
        }
    }
    ++modCount;
    //size That is, every node we add (k, V, h, next), size++
    if (++size > threshold)
        resize();//Capacity expansion
        afterNodeInsertion(evict);
        return null;
    }
    */
}

public static void main(String[] args) {
    /*
    HashSet The bottom layer is HashMap. When it is added for the first time, the table array is expanded to 16,
    The threshold is 16 * the LoadFactor is 0.75 = 12
    If the table array uses the critical value of 12, it will be expanded to 16 * 2 = 32,
    The new critical value is 32 * 0.75 = 24, and so on
    */
    HashSet hashSet = new HashSet();
    // for(int i = 1; i <= 100; i++) {
    // hashSet.add(i);//1,2,3,4,5...100
    // }
    /*
    In Java 8, if the number of elements in a linked list reaches treeify_ Threshold (default is 8),
    And the size of the table > = min_ TREEIFY_ Capacity (64 by default) will be trealized (red black tree), otherwise the array expansion mechanism will still be adopted
    */
    // for(int i = 1; i <= 12; i++) {
    //      hashSet.add(new A(i));//
    // }
    /*
    When we add an element to hashset - > node - > table, we add a size++
    */
    for (int i = 1; i <= 7; i++) {//Seven A objects are added to A linked list of table
        hashSet.add(new A(i));//
    }
    for (int i = 1; i <= 7; i++) {//Seven B objects are added to another linked list of table
        hashSet.add(new B(i));//
    }
}
class B {
    private int n;

    public B(int n) {
        this.n = n;
    }

    @Override
    public int hashCode() {
        return 200;
    }
}

class A {
    private int n;

    public A(int n) {
        this.n = n;
    }

    @Override
    public int hashCode() {
        return 100;
    }
}

HashSet classroom exercise 1

public static void main(String[] args) {
    /**
     Define an Employee class, which contains: private member attribute name,age requirements:
     Create three Employee objects and put them into the HashSet
     When the values of name and age are the same, they are considered to be the same employees and cannot be added to the HashSet collection
     */
    HashSet hashSet = new HashSet();
    hashSet.add(new Employee("milan", 18));//ok
    hashSet.add(new Employee("smith", 28));//ok
    hashSet.add(new Employee("milan", 18));//Failed to join// Answer, how many? 3
    System.out.println("hashSet=" + hashSet);
}
//Create Employee
class Employee {
    private String name;
    private int age;

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public void setAge(int age) {
        this.age = age;
    }

    //If the name and age values are the same, the same hash value is returned
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Employee employee = (Employee) o;
        return age == employee.age &&
                Objects.equals(name, employee.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

HashSet after class exercise 2

Set interface implementation class LinkedHashSet

Comprehensive description of LinkedHashSet

LinkedHashSet after class exercises

public static void main(String[] args) {
    LinkedHashSet linkedHashSet = new LinkedHashSet();
    linkedHashSet.add(new Car("Alto", 1000));//OK
    linkedHashSet.add(new Car("audi", 300000));//OK
    linkedHashSet.add(new Car("Ferrari", 10000000));//OK
    linkedHashSet.add(new Car("audi", 300000));//Can't join
    linkedHashSet.add(new Car("Porsche", 70000000));//OK
    linkedHashSet.add(new Car("audi", 300000));//Can't join
    System.out.println("linkedHashSet=" + linkedHashSet);
}
/**
 * Car Class (attribute: name,price). If name is the same as price,
 * It is considered to be the same element and cannot be added. 5min
 */
class Car {
    private String name;
    private double price;

    public Car(String name, double price) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "\nCar{" +
                "name='" + name + '\'' +
                ", price=" + price +
                '}';
    }

    //Override the equals method and hashCode
    //When the name and price are the same, the same hashCode value is returned, and equals returns t
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Car car = (Car) o;
        return Double.compare(car.price, price) == 0 &&
                Objects.equals(name, car.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, price);
    }
}

HashMap and HashTable (super focus)

Map interface and common methods

Characteristics of Map interface implementation class [very practical]

public static void main(String[] args) {
    //Lao Han interprets the characteristics of the Map interface implementation class and uses the implementation class HashMap
    //1. Map and Collection exist side by side. Used to save data with mapping relationship: key value (double column element)
    //2. The key and value in the map can be data of any reference type and will be encapsulated in the HashMap$Node object
    //3. Duplicate key s in map are not allowed. The reason is the same as HashSet. The source code has been analyzed earlier// 4. The value in the map can be repeated
    //5. The key and value of map can be null. Note that the key is null
    // There can only be one, value is null, and there can be multiple
    //6. String class is often used as the key of Map
    //7. There is a one-way one-to-one relationship between key and value, that is, the corresponding value can always be found through the specified key
    Map map = new HashMap();
    map.put("no1", "oracle ");//k-v
    map.put("no2", "zhang wuji");//k-v
    map.put("no1", "Zhang Sanfeng");//When there is the same K, it is equivalent to substitution map.put("no3", "Zhang Sanfeng")// k-v
    map.put(null, null); //k-v
    map.put(null, "abc"); //Equivalent substitution
    map.put("no4", null); //k-v
    map.put("no5", null); //k-v
    map.put(1, "Zhao Min");//k-v
    map.put(new Object(), "Golden King ");//k-v
    // Pass in the key through the get method, and the corresponding value will be returned
    System.out.println(map.get("no2"));//zhang wuji
    System.out.println("map=" + map);
}

Common methods of Map interface

public static void main(String[] args) {
    //Demonstrate common methods of map interface
    Map map = new HashMap();
    map.put("Deng Chao", new Book("", 100));//OK
    map.put("Deng Chao", "Sun Li");//Replace - > analysis source code
    map.put("Wang Baoqiang", "Ma Rong");//OK
    map.put("Song Zhe", "Ma Rong");//OK
    map.put("Liu Lingbo", null);//OK
    map.put(null, "Liu Yifei");//OK
    map.put("Lu Han", "Guan Xiaotong");//OK
    map.put("hsp", "hsp My wife");
    System.out.println("map=" + map);
    // remove: deletes the mapping relationship based on the key
    map.remove(null);
    System.out.println("map=" + map);
    // Get: get value according to key
    Object val = map.get("Lu Han");
    System.out.println("val=" + val);
    // size: get the number of elements
    System.out.println("k-v=" + map.size());
    // isEmpty: judge whether the number is 0
    System.out.println(map.isEmpty());//F
    // Clear: clear k-v
    //map.clear();
    System.out.println("map=" + map);
    // containsKey: find whether the key exists
    System.out.println("result=" + map.containsKey("hsp"));//T
}
class Book {
    private String name;
    private int num;

    public Book(String name, int num) {
        this.name = name;
        this.num = num;
    }
}

Map interface traversal method

public static void main(String[] args) {
    Map map = new HashMap();
    map.put("Deng Chao", "Sun Li");
    map.put("Wang Baoqiang", "Ma Rong");
    map.put("Song Zhe", "Ma Rong");
    map.put("Liu Lingbo", null);
    map.put(null, "Liu Yifei");
    map.put("Lu Han", "Guan Xiaotong");
    //Group 1: take out all keys first, and take out the corresponding Value through the Key
    Set keyset = map.keySet();
    //(1) Enhanced for
    System.out.println("-----The first way-------");
    for (Object key : keyset) {
        System.out.println(key + "-" + map.get(key));
    }
    //(2) Iterator
    System.out.println("----The second way--------");
    Iterator iterator = keyset.iterator();
    while (iterator.hasNext()) {
        Object key = iterator.next();
        System.out.println(key + "-" + map.get(key));
    }
    //Group 2: take out all values
    Collection values = map.values();
    //Here you can use the traversal methods used by all Collections
    //(1) Enhanced for
    System.out.println("---Remove all value enhance for----");
    for (Object value : values) {
        System.out.println(value);
    }
    //(2) Iterator
    System.out.println("---Remove all value iterator ----");
    Iterator iterator2 = values.iterator();
    while (iterator2.hasNext()) {
        Object value = iterator2.next();
        System.out.println(value);
    }
    //Group 3: get k-v through EntrySet
    Set entrySet = map.entrySet();// EntrySet<Map.Entry<K,V>>
    //(1) Enhanced for
    System.out.println("----use EntrySet of for enhance(Type 3)----");
    for (Object entry : entrySet) {
        //Convert entry to map Entry
        Map.Entry m = (Map.Entry) entry;
        System.out.println(m.getKey() + "-" + m.getValue());
    }
    //(2) Iterator
    System.out.println("----use EntrySet Iterator for(Type 4)----");
    Iterator iterator3 = entrySet.iterator();
    while (iterator3.hasNext()) {
        Object entry = iterator3.next();
        //System.out.println(next.getClass());//HashMap$Node - Implementation - > map Entry (getKey,getValue)
        //Transition down map Entry
        Map.Entry m = (Map.Entry) entry;
        System.out.println(m.getKey() + "-" + m.getValue());
    }
}

Map interface class exercise

public static void main(String[] args) {
    //Completion code
    Map hashMap = new HashMap();
    //Add object
    hashMap.put(1, new Emp("jack", 300000, 1));
    hashMap.put(2, new Emp("tom", 21000, 2));
    hashMap.put(3, new Emp("milan", 12000, 3));
    //There are two ways to traverse
    //And traverse the employees with salary > 18000 (at least two traversal methods)
    //1. Use keyset - > enhance for
    Set keySet = hashMap.keySet();
    System.out.println("====The first traversal method====");
    for (Object key : keySet) {
    //Get value first
        Emp emp = (Emp) hashMap.get(key);
        if (emp.getSal() > 18000) {
            System.out.println(emp);
        }
    }
    //2. Use entryset - > iterator
    // Reflect difficult knowledge points
    // Taste slowly, the more you taste 
    Set entrySet = hashMap.entrySet();
    System.out.println("======iterator ======");
    Iterator iterator = entrySet.iterator();
    while (iterator.hasNext()) {
        Map.Entry entry = (Map.Entry) iterator.next();
        //Get key and value through entry
        Emp emp = (Emp) entry.getValue();
        if (emp.getSal() > 18000) {
            System.out.println(emp);
        }
    }
}
/**
 * Add 3 employee objects using HashMap. It is required to
 * Key: employee id
 * Value: employee object
 * <p>
 * And traverse the employees with salary > 18000 (at least two traversal methods)
 * Employee category: name, salary, employee id
 */
class Emp {
    private String name;
    private double sal;
    private int id;

    public Emp(String name, double sal, int id) {
        this.name = name;
        this.sal = sal;
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getSal() {
        return sal;
    }

    public void setSal(double sal) {
        this.sal = sal;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "name='" + name + '\'' +
                ", sal=" + sal +
                ", id=" + id +
                '}';
    }
}

Map interface implementation class - HashMap

HashMap summary

HashMap underlying mechanism and source code analysis

HashMap underlying mechanism and source code analysis

public static void main(String[] args) {
    HashMap map = new HashMap();
    map.put("java", 10);//ok
    map.put("php", 10);//ok
    map.put("java", 20);//Replace value
    System.out.println("map=" + map);//
    /*Lao Han interprets the source code + diagram of HashMap
    1. Execute constructor new HashMap()
    Initialization load factor loadfactor = 0.75
    HashMap$Node[] table = null
    2. Execute put, call the hash method, and calculate the hash value of the key (H = key. Hashcode()) ^ (H > > > 16)
    public V put(K key, V value) {//K = "java" value = 10
        return putVal(hash(key), key, value, false, true);
    }
    3. Execute putVal
    final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) {
            Node<K,V>[] tab; Node<K,V> p; int n, i;//Auxiliary variable
    //If the underlying table array is null or length =0, it will be expanded to 16
    if ((tab = table) == null || (n = tab.length) == 0)
            n = (tab = resize()).length;
    //Take out the Node at the index position of the table corresponding to the hash value. If it is null, directly add the k-v
    //, Create a Node and join the location
    if ((p = tab[i = (n - 1) & hash]) == null)
            tab[i] = newNode(hash, key, value, null);
    else {
            Node<K,V> e; K k;//Auxiliary variable
    // If the hash value of the key at the index position of the table is the same as that of the new key,
    // (the key of the existing node of the table and the key to be added are the same object | equals returns true)
    // I think we can't add a new k-v
    if (p.hash == hash &&
            ((k = p.key) == key || (key != null && key.equals(k))))
                e = p;
    else if (p instanceof TreeNode)//If the existing Node of the current table is a red black tree, it will be processed as a red black tree
            e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
    else {
    //If the found node is followed by a linked list, it will be compared circularly
        for (int binCount = 0; ; ++binCount) {//Dead cycle
        if ((e = p.next) == null) {//If the whole linked list is not the same as him, it will be added to the end of the linked list
        p.next = newNode(hash, key, value, null);
    //After adding, judge whether the number of the current linked list has reached 8, and then
    //The treeifyBin method is called to convert the red black tree
    if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
            treeifyBin(tab, hash);
            break;
    }
    if (e.hash == hash && //If you find the same in the process of cyclic comparison, you break and just replace value
            ((k = e.key) == key || (key != null && key.equals(k))))
            break;
            p = e;
    	}
    }
    if (e != null) { // existing mapping for key
        V oldValue = e.value;
    if (!onlyIfAbsent || oldValue == null)
        e.value = value; //Replace, key corresponds to value
        afterNodeAccess(e);
    return oldValue;
    	}
    }
    ++modCount;//Every time a Node is added, the size is increased++
    if (++size > threshold[12-24-48])//If size > critical value, expand the capacity
    resize();
        afterNodeInsertion(evict);
        return null;
    }
    5. About tree (turning into red black tree)
    //If the table is null or the size has not reached 64, it will not be treed temporarily, but will be expanded// Otherwise, it will be really tree - > pruning
    final void treeifyBin(Node<K,V>[] tab, int hash) {
    int n, index; Node<K,V> e;
    if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)
        resize();
    }
    */
}

public static void main(String[] args) {
    HashMap hashMap = new HashMap();
    for (int i = 1; i <= 12; i++) {
        hashMap.put(i, "hello");
    }
    hashMap.put("aaa", "bbb");
    System.out.println("hashMap=" + hashMap);//12 k-v
    //Assign a task, design your own code to verify, and expand the capacity of the table
    //0 -> 16(12) -> 32(24) -> 64(64*0.75=48)-> 128 (96) ->
    //Design your own program, verify - enhance your ability to read the source code Look at someone else's code.}
}

class A {
    private int num;

    public A(int num) {
        this.num = num;
    }

    //The hashCode of all A objects is 100
    // @Override
    // public int hashCode() {
    // return 100;
    // }
    @Override
    public String toString() {
        return "\nA{" +
                "num=" + num +
                '}';
    }
}

Map interface implementation class - Hashtable

Basic introduction to HashTable

Comparison between Hashtable and HashMap

Summary - how to select collection implementation classes in development (remember)

Multithreading explanation

Thread related concepts

Program

process

What is a thread

Other related concepts

Basic thread usage

There are two ways to create threads

Thread application case 1 - inherit thread class

public static void main(String[] args) throws InterruptedException {
        //Create a Cat object that can be used as a thread
        Cat cat = new Cat();
        //Old Korean reading source code
        /*
        (1)
        public synchronized void start() {
            start0();
        }
        (2)
        //start0() It is a local method, a JVM call, and the bottom layer is a c/c + + implementation
        //The real effect of multithreading is start0(), not run
        private native void start0();
        */
        cat.start();//Start the thread - > the run method of cat will eventually be executed
        //cat. run();// The run method is an ordinary method. If a thread is not really started, the run method will be executed until it is completed
        //Note: when the main thread starts a sub thread thread Thread-0, the main thread will not block and will continue to execute
        //At this time, the main thread and sub thread execute alternately System.out.println("main thread continues to execute" + thread. Currentthread() getName());// Name main
        for (int i = 0; i < 60; i++) {
            System.out.println("Main thread i=" + i);
            //Hibernate the main thread
            Thread.sleep(1000);
        }
    }
//Lao Han description
//1. When a class inherits the Thread class, it can be used as a Thread
//2. We will rewrite the run method and write our own business code
//3. The run thread class implements the run method of the Runnable interface
        /*
        @Override
        public void run() {
        if (target != null) {
            target.run();
            }
        }
        */
class Cat extends Thread {
    int times = 0;

    @Override
    public void run() {//Rewrite the run method and write your own business logic
        while (true) {
            //The thread every 1 second. Output "meow, meow, I'm a kitten" on the console
            System.out.println("Meow meow, I'm a kitten" + (++times) + " Thread name=" + Thread.currentThread().getName());
            //Let the thread sleep for 1 second ctrl+alt+t
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (times == 80) {
                break;//When the times reaches 80, exit while, and the thread will exit..}
            }
        }
    }
}

Thread application case 2 - Implementation of Runnable interface

public static void main(String[] args) {
    Dog dog = new Dog();
    //dog.start();  Start cannot be called here
    //Create the Thread object, put the dog object (Runnable) into the Thread
    Thread thread = new Thread(dog);
    thread.start();
    // Tiger tiger = new Tiger();// Runnable is implemented
    // ThreadProxy threadProxy = new ThreadProxy(tiger);
    // threadProxy.start();
}
class Animal {
}

class Tiger extends Animal implements Runnable {
    @Override
    public void run() {
        System.out.println("The tiger howled....");
    }
}

//Thread agent class simulates a minimalist thread class
class ThreadProxy implements Runnable {//You can think of the Proxy class as ThreadProxy
    private Runnable target = null;//Property, type Runnable

    @Override
    public void run() {
        if (target != null) {
            target.run();//Dynamic binding (run type Tiger)
        }
    }

    public ThreadProxy(Runnable target) {
        this.target = target;
    }

    public void start() {
        start0();//This method really implements a multithreaded method
    }

    public void start0() {
        run();
    }
}

class Dog implements Runnable { //Develop threads by implementing Runnable interface
    int count = 0;

    @Override
    public void run() { //Common method
        while (true) {
            System.out.println("The dog barked..hi" + (++count) + Thread.currentThread().getName());
            //Sleep for 1 second
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (count == 10) {
                break;
            }
        }
    }
}

Thread usage case - multithreaded execution

    public static void main(String[] args) {
        T1 t1 = new T1();
        T2 t2 = new T2();
        Thread thread1 = new Thread(t1);
        Thread thread2 = new Thread(t2);
        thread1.start();//Start the first thread
        thread2.start();//Start the second thread
//... }
    }
class T1 implements Runnable {
    int count = 0;

    @Override
    public void run() {
        while (true) {
//Output "hello,world" every 1 second and output 10 times
            System.out.println("hello,world " + (++count));
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (count == 60) {
                break;
            }
        }
    }
}

class T2 implements Runnable {
    int count = 0;

    @Override
    public void run() {
//Output "hi" every 1 second for 5 times
        while (true) {
            System.out.println("hi " + (++count));
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (count == 50) {
                break;
            }
        }
    }
}

How do threads understand

The difference between inheriting thread and implementing Runnable

public static void main(String[] args) {
    //test
    // SellTicket01 sellTicket01 = new SellTicket01();
    // SellTicket01 sellTicket02 = new SellTicket01();
    // SellTicket01 sellTicket03 = new SellTicket01();
    //
    // //We'll oversold here// sellTicket01.start();// Start ticket selling thread
    // sellTicket02.start();// Start ticket selling thread
    // sellTicket03.start();// Start ticket selling thread
    System.out.println("===Use the implementation interface to sell tickets=====");
    SellTicket02 sellTicket02 = new SellTicket02();
    new Thread(sellTicket02).start();//Thread 1 - window
    new Thread(sellTicket02).start();//2nd thread - window
    new Thread(sellTicket02).start();//3rd thread - window
}
//Using Thread mode
class SellTicket01 extends Thread {
    private static int ticketNum = 100;//Let multiple threads share ticketNum

    @Override
    public void run() {
        while (true) {
            if (ticketNum <= 0) {
                System.out.println("End of ticket sales...");
                break;
            }
            //Sleep for 50 ms, analog
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("window " + Thread.currentThread().getName() + " Sell a ticket" + " Remaining votes=" + (--ticketNum));
        }
    }
}

//Implementation interface mode
class SellTicket02 implements Runnable {
    private int ticketNum = 100;//Let multiple threads share ticketNum

    @Override
    public void run() {
        while (true) {
            if (ticketNum <= 0) {
                System.out.println("End of ticket sales...");
                break;
            }
            //Sleep for 50 ms, analog
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("window " + Thread.currentThread().getName() + " Sell a ticket" + " Remaining votes=" + (--ticketNum));//1 - 0 - -1 - -2
        }
    }
}

Thread termination

Basic description

Application case

Common thread methods

Common methods group I

Precautions and details

Application case

Common methods group II

Application case

Test the yield and join methods, pay attention to the characteristics of the method, and watch the teacher's code demonstration

Classroom practice

public static void main(String[] args) throws InterruptedException {
    Thread t3 = new Thread(new T3());//Create child thread
    for (int i = 1; i <= 10; i++) {
        System.out.println("hi " + i);
        if (i == 5) {//This indicates that the main thread outputs hi five times
            t3.start();//Start the child thread to output Hello t3. join();// Immediately insert the T3 sub thread into the main thread and let T3 execute first
        }
        Thread.sleep(1000);//Output hi once and let the main thread sleep for 1s
    }
}
class T3 implements Runnable {
    private int count = 0;

    @Override
    public void run() {
        while (true) {
            System.out.println("hello " + (++count));
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (count == 10) {
                break;
            }
        }
    }
}

User thread and daemon thread

Application case

Let's test how to set a thread as a daemon thread

Thread life cycle

Thread. Is used in JDK The state enumeration represents several states of a thread

[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-belqvtsi-1640872377285) (C: \ users \ Wang \ appdata \ roaming \ typora user images \ image-20211230180943404. PNG)]

Thread state transition diagram

Write program to view thread status

public static void main(String[] args) throws InterruptedException {
    T t = new T();
    System.out.println(t.getName() + " state " + t.getState());
    t.start();
    while (Thread.State.TERMINATED != t.getState()) {
        System.out.println(t.getName() + " state " + t.getState());
        Thread.sleep(500);
    }
    System.out.println(t.getName() + " state " + t.getState());
}
class T extends Thread {
    @Override
    public void run() {
        while (true) {
            for (int i = 0; i < 10; i++) {
                System.out.println("hi " + i);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            break;
        }
    }
}

Thread synchronization

Let's look at one question first

Synchronized

Thread synchronization mechanism

Synchronization specific method - Synchronized

Analysis of synchronization principle

mutex

Basic introduction

Use mutex lock to solve ticket selling problem

public static void main(String[] args) {
    //test
    // SellTicket01 sellTicket01 = new SellTicket01();
    // SellTicket01 sellTicket02 = new SellTicket01();
    // SellTicket01 sellTicket03 = new SellTicket01();
    //
    // //We'll oversold here// sellTicket01.start();// Start ticket selling thread
    // sellTicket02.start();// Start ticket selling thread
    // sellTicket03.start();// Start ticket selling thread
    // System.out.println("= = = use the implementation interface to sell tickets = = = =");
    // SellTicket02 sellTicket02 = new SellTicket02();
    //
    // new Thread(sellTicket02).start();// Thread 1 - window
    // new Thread(sellTicket02).start();// 2nd thread - window
    // new Thread(sellTicket02).start();// 3rd thread - window
    //Test one
    SellTicket03 sellTicket03 = new SellTicket03();
    new Thread(sellTicket03).start();//Thread 1 - window
    new Thread(sellTicket03).start();//2nd thread - window
    new Thread(sellTicket03).start();//3rd thread - window
}
//Implement the interface mode, and use synchronized to realize thread synchronization
class SellTicket03 implements Runnable {
    private int ticketNum = 100;//Let multiple threads share ticketNum
    private boolean loop = true;//Control run method variables
    Object object = new Object();
    //The lock of the synchronous method (static) is the current class itself
    //Lao Han's interpretation
    //1. The public synchronized static void m1() {} lock is added to sellticket03 class
    //2. If in a static method, implement a synchronous code block
    /*
        synchronized (SellTicket03 .class)

        {
            System.out.println("m2");
        }
    */

    public synchronized static void m1() {
    }

    public static void m2() {
        synchronized (SellTicket03.class) {
            System.out.println("m2");
        }
    }

    //Lao Han description
    //1. public synchronized void sell() {} is a synchronization method
    //2. Lock this object at this time
    //3. You can also write synchronize on the code block, synchronize the code block, and whether the mutex is on this object
    public /*synchronized*/ void sell() { //Synchronous method. At the same time, only one thread can execute the sell method
        synchronized (/*this*/ object) {
            if (ticketNum <= 0) {
                System.out.println("End of ticket sales...");
                loop = false;
                return;
            }
    //Sleep for 50 ms, analog
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("window " + Thread.currentThread().getName() + " Sell a ticket" + " Remaining votes=" + (--ticketNum));//1 - 0 - -1 - -2
        }
    }

    @Override
    public void run() {
        while (loop) {
            sell();//The sell method is a common synchronization method
        }
    }
}

//Using Thread mode
// new SellTicket01().start()
// new SellTicket01().start();
class SellTicket01 extends Thread {
    private static int ticketNum = 100;//Let multiple threads share ticketNum

    // public void m1() {
    // synchronized (this) {
    // System.out.println("hello");
    // }
    // }
    @Override
    public void run() {
        while (true) {
            if (ticketNum <= 0) {
                System.out.println("End of ticket sales...");
                break;
            }
            //Sleep for 50 ms, analog
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("window " + Thread.currentThread().getName() + " Sell a ticket" + " Remaining votes=" + (--ticketNum));
        }
    }
}

//Implementation interface mode
class SellTicket02 implements Runnable {
    private int ticketNum = 100;//Let multiple threads share ticketNum

    @Override
    public void run() {
        while (true) {
            if (ticketNum <= 0) {
                System.out.println("End of ticket sales...");
                break;
            }
            //Sleep for 50 ms, analog
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("window " + Thread.currentThread().getName() + " Sell a ticket" + " Remaining votes=" + (--ticketNum));//1 - 0 - -1 - -2
        }
    }
}

Precautions and details

Thread deadlock

Basic introduction

Application case

Application case

public static void main(String[] args) {
    //Simulate deadlock
    DeadLockDemo A = new DeadLockDemo(true);
    A.setName("A thread ");
    DeadLockDemo B = new DeadLockDemo(false);
    B.setName("B thread ");
    A.start();
    B.start();
}
//thread 
class DeadLockDemo extends Thread {
    static Object o1 = new Object();// Ensure multithreading and share an object. Here, use static
    static Object o2 = new Object();
    boolean flag;

    public DeadLockDemo(boolean flag) {//constructor 
        this.flag = flag;
    }

    @Override
    public void run() {
    //The following is the analysis of business logic
    //1. If the flag is T, thread A will first obtain / hold the o1 object lock, and then try to obtain the o2 object lock
    //2. If thread A cannot get o2 object lock, it will be Blocked
    //3. If the flag is F, thread B will get / hold the o2 object lock first, and then try to get the o1 object lock
    //4. If thread B cannot get the o1 object lock, it will be Blocked
        if (flag) {
            synchronized (o1) {//Object mutex, the following is the synchronization code
                System.out.println(Thread.currentThread().getName() + " Enter 1");
                synchronized (o2) { // Here you get the monitoring right of the li object
                    System.out.println(Thread.currentThread().getName() + " Enter 2");
                }
            }
        } else {
            synchronized (o2) {
                System.out.println(Thread.currentThread().getName() + " Enter 3");
                synchronized (o1) { // Here you get the monitoring right of the li object
                    System.out.println(Thread.currentThread().getName() + " Enter 4");
                }
            }
        }
    }
}

Release lock

The following operation will release the lock

The following operation will not release the lock

rintln("end of ticket sales...);
break;
}
//Sleep for 50 ms, analog
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("window" + Thread.currentThread().getName() + "one ticket sold" + "number of remaining tickets =" + (– ticketNum));
}
}
}

//Implementation interface mode
class SellTicket02 implements Runnable {
private int ticketNum = 100;// Let multiple threads share ticketnum

@Override
public void run() {
    while (true) {
        if (ticketNum <= 0) {
            System.out.println("End of ticket sales...");
            break;
        }
        //Sleep for 50 ms, analog
        try {
            Thread.sleep(50);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("window " + Thread.currentThread().getName() + " Sell a ticket" + " Remaining votes=" + (--ticketNum));//1 - 0 - -1 - -2
    }
}

}

### Precautions and details

[External chain picture transfer...(img-2MDjHzIn-1640872377287)]

## Thread deadlock

### Basic introduction

[External chain picture transfer...(img-mlqWXWub-1640872377287)]

### Application case

[External chain picture transfer...(img-KtH2e7q0-1640872377287)]

### Application case

```java
public static void main(String[] args) {
    //Simulate deadlock
    DeadLockDemo A = new DeadLockDemo(true);
    A.setName("A thread ");
    DeadLockDemo B = new DeadLockDemo(false);
    B.setName("B thread ");
    A.start();
    B.start();
}
//thread 
class DeadLockDemo extends Thread {
    static Object o1 = new Object();// Ensure multithreading and share an object. Here, use static
    static Object o2 = new Object();
    boolean flag;

    public DeadLockDemo(boolean flag) {//constructor 
        this.flag = flag;
    }

    @Override
    public void run() {
    //The following is the analysis of business logic
    //1. If the flag is T, thread A will first obtain / hold the o1 object lock, and then try to obtain the o2 object lock
    //2. If thread A cannot get o2 object lock, it will be Blocked
    //3. If the flag is F, thread B will get / hold the o2 object lock first, and then try to get the o1 object lock
    //4. If thread B cannot get the o1 object lock, it will be Blocked
        if (flag) {
            synchronized (o1) {//Object mutex, the following is the synchronization code
                System.out.println(Thread.currentThread().getName() + " Enter 1");
                synchronized (o2) { // Here you get the monitoring right of the li object
                    System.out.println(Thread.currentThread().getName() + " Enter 2");
                }
            }
        } else {
            synchronized (o2) {
                System.out.println(Thread.currentThread().getName() + " Enter 3");
                synchronized (o1) { // Here you get the monitoring right of the li object
                    System.out.println(Thread.currentThread().getName() + " Enter 4");
                }
            }
        }
    }
}

Release lock

The following operation will release the lock

[external chain picture transferring... (IMG elbjkstj-1640872377288)]

The following operation will not release the lock

[external chain picture transferring... (img-3UlKXnUV-1640872377288)]

Topics: Java Interview Singleton pattern