Advanced path for Java engineers

Knowledge point 01: Nine sorting algorithms

public class Sort {
    public static void main(String[] args) {
        testTime();
        testSort();
    }

    public static void testTime() {
        int[] arr = new int[10000];
        for (int i = 0; i < 10000; i++) {
            arr[i] = (int) (Math.random() * 100 + 1);
        }
        long s = System.currentTimeMillis();
//        bubbleSort(arr);
//        selectionSort(arr);
//        insertionSort(arr);
//        shellSort(arr);
//        quickSort(arr, 0, arr.length - 1);
//        mergeSort(arr, 0, arr.length - 1, new int[arr.length]);
//        radixSort(arr);
//        countingSort(arr);
//        heapSort(arr);
        long e = System.currentTimeMillis();
        System.out.println((e - s) + "ms");
    }

    public static void testSort() {
        int[] arr = new int[50];
        for (int i = 0; i < 50; i++) {
            arr[i] = (int) (Math.random() * 100 + 1);
        }
//        bubbleSort(arr);
//        selectionSort(arr);
//        insertionSort(arr);
//        shellSort(arr);
//        quickSort(arr, 0, arr.length - 1);
//        mergeSort(arr, 0, arr.length - 1, new int[arr.length]);
//        radixSort(arr);
//        countingSort(arr);
//        heapSort(arr);
        System.out.println(Arrays.toString(arr));
    }

    //Heap sorting (large top heap: ascending algorithm, small top heap: descending algorithm)
    public static void heapSort(int arr[]) {
        //Create large top heap
        for (int i = arr.length / 2 - 1; i >= 0; i--) {
            heapAdjust(arr, i, arr.length);
        }
        //Adjust the large top reactor
        for (int i = arr.length - 1; i > 0; i--) {
            //Exchange element
            int temp = arr[i];
            arr[i] = arr[0];
            arr[0] = temp;
            //Adjust new heap
            heapAdjust(arr, 0, i);
        }
    }

    //Heap adjustment
    public static void heapAdjust(int arr[], int ci, int length) {
        //Cache current node
        int temp = arr[ci];
        //Start cycle adjustment
        for (int li = ci * 2 + 1; li < length; li = li * 2 + 1) {
            //It indicates that the value of the left child node is less than that of the right child node
            if (li + 1 < length && arr[li] < arr[li + 1]) {
                li = li + 1;
            }
            //Indicates that the value of the current child node is greater than that of the parent node
            if (arr[li] > temp) {
                arr[ci] = arr[li];
                ci = li;
            } else {
                break;
            }
        }
        //Place in the adjustment position
        arr[ci] = temp;
    }

    //Count sorting: ascending algorithm
    public static void countingSort(int[] arr) {
        if (arr == null || arr.length == 0) return;
        int max = arr[0];
        int min = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if (arr[i] > max) max = arr[i];
            if (arr[i] < min) min = arr[i];
        }
        //Statistical times
        int[] counts = new int[max - min + 1];
        for (int i = 0; i < arr.length; i++) {
            counts[arr[i] - min]++;
        }
        //accumulative frequency
        for (int i = 1; i < counts.length; i++) {
            counts[i] += counts[i - 1];
        }
        //Reverse rearrangement
        int[] newArr = new int[arr.length];
        for (int i = arr.length - 1; i >= 0; i--) {
            newArr[--counts[arr[i] - min]] = arr[i];
        }
        //Copy array
        for (int i = 0; i < arr.length; i++) {
            arr[i] = newArr[i];
        }
    }

    //Cardinality sorting: ascending algorithm
    public static void radixSort(int[] arr) {
        if (arr == null || arr.length == 0) return;
        int max = arr[0];
        int min = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if (arr[i] > max) max = arr[i];
            if (arr[i] < min) min = arr[i];
        }
        for (int i = 0; i < arr.length; i++) {
            arr[i] -= min;
        }
        int maxLength = String.valueOf(max - min).length();
        int[][] bucket = new int[10][arr.length];
        int[] bucketIndex = new int[10];
        for (int rounds = 0, base = 1; rounds < maxLength; rounds++, base *= 10) {
            for (int i = 0; i < arr.length; i++) {
                int digit = arr[i] / base % 10;
                bucket[digit][bucketIndex[digit]++] = arr[i];
            }
            int pos = 0;
            for (int i = 0; i < bucketIndex.length; i++) {
                for (int j = 0; j < bucketIndex[i]; j++) {
                    arr[pos++] = bucket[i][j];
                }
                bucketIndex[i] = 0;
            }
        }
        for (int i = 0; i < arr.length; i++) {
            arr[i] += min;
        }
    }

    //Merge sort: ascending algorithm
    public static void mergeSort(int[] arr, int L, int R, int[] temp) {
        if (L >= R) return;
        int tIdx = L, left = L, middle = (L + R) / 2, right = middle + 1;
        mergeSort(arr, L, middle, temp);
        mergeSort(arr, right, R, temp);
        while (left <= middle && right <= R) {
            if (arr[left] <= arr[right]) {
                temp[tIdx++] = arr[left++];
            } else {
                temp[tIdx++] = arr[right++];
            }
        }
        while (left <= middle) temp[tIdx++] = arr[left++];
        while (right <= R) temp[tIdx++] = arr[right++];
        for (int i = L; i <= R; i++) {
            arr[i] = temp[i];
        }
    }

    //Quick sort: ascending algorithm
    public static void quickSort(int[] arr, int L, int R) {
        if (L >= R) return;
        int left = L, right = R, pivot = arr[L];
        while (left < right) {
            while (left < right && arr[right] >= pivot) right--;
            arr[left] = arr[right];
            while (left < right && arr[left] <= pivot) left++;
            arr[right] = arr[left];
        }
        arr[left] = pivot;
        quickSort(arr, L, left - 1);
        quickSort(arr, left + 1, R);
    }

    //Hill sorting: ascending algorithm
    public static void shellSort(int[] arr) {
        for (int step = arr.length / 2; step > 0; step /= 2) {
            for (int i = step; i < arr.length; i++) {
                int temp = arr[i];
                int j = i - step;
                while (j >= 0 && arr[j] > temp) {
                    arr[j + step] = arr[j];
                    j -= step;
                }
                arr[j + step] = temp;
            }
        }
    }

    //Insert sort: ascending algorithm
    public static void insertionSort(int[] arr) {
        for (int i = 1; i < arr.length; i++) {
            int temp = arr[i];
            int j = i - 1;
            while (j >= 0 && arr[j] > temp) {
                arr[j + 1] = arr[j];
                j -= 1;
            }
            arr[j + 1] = temp;
        }
    }

    //Select Sorting: ascending algorithm
    public static void selectionSort(int[] arr) {
        for (int i = 0; i < arr.length - 1; i++) {
            int minIndex = i;
            for (int j = i + 1; j < arr.length; j++) {
                if (arr[minIndex] > arr[j]) {
                    minIndex = j;
                }
            }
            if (minIndex != i) {
                int temp = arr[minIndex];
                arr[minIndex] = arr[i];
                arr[i] = temp;
            }
        }
    }

    //Bubble sorting: ascending algorithm
    public static void bubbleSort(int[] arr) {
        for (int i = 0; i < arr.length - 1; i++) {
            for (int j = 0; j < arr.length - 1 - i; j++) {
                if (arr[j] > arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
    }
}

Knowledge point 02: binary search algorithm

Recursive version:

public static int binarySearch(int[] arr, int target) {
    return binarySearch(arr, 0, arr.length - 1, target);
}

private static int binarySearch(int[] arr, int left, int right, int target) {
    while (left <= right) {
        int middle = (left + right) / 2;
        if (target < arr[middle]) {
            right = middle - 1;
        } else if (target > arr[middle]) {
            left = middle + 1;
        } else {
            return middle;
        }
    }
    return -1;
}

Iteration:

public static int binarySearch(int[] arr, int target) {
    return binarySearch(arr, 0, arr.length - 1, target);
}

private static int binarySearch(int[] arr, int left, int right, int target) {
    if (left > right) return -1;
    int middle = (left + right) / 2;
    if (target < arr[middle]) {
        return binarySearch(arr, left, middle - 1, target);
    } else if (target > arr[middle]) {
        return binarySearch(arr, middle + 1, right, target);
    } else {
        return middle;
    }
}

Knowledge point 03: traversal of binary tree

Tree node:

class TreeNode {
    int data;
    TreeNode left;
    TreeNode right;

    public TreeNode() {}

    public TreeNode(int data) {
        this.data = data;
    }
}

Recursive version:

//Middle left and right
public static void preOrder(TreeNode root) {
    if (root == null) return;
    System.out.print(root.data + " ");
    preOrder(root.left);
    preOrder(root.right);
}

//Left middle right
public static void midOrder(TreeNode root) {
    if (root == null) return;
    midOrder(root.left);
    System.out.print(root.data + " ");
    midOrder(root.right);
}

//Zuo Youzhong
public static void postOrder(TreeNode root) {
    if (root == null) return;
    postOrder(root.left);
    postOrder(root.right);
    System.out.print(root.data + " ");
}

Iteration:

//Middle left and right = > right left (hollow)
public static void preOrder(TreeNode root) {
    if (root == null) return;
    Stack<TreeNode> stack = new Stack<>();
    stack.push(root);
    while (!stack.isEmpty()) {
        TreeNode node = stack.pop();
        if (node != null) {
            if (node.right != null) stack.push(node.right);
            if (node.left != null) stack.push(node.left);
            stack.push(node);
            stack.push(null);
        } else {
            node = stack.pop();
            System.out.print(node.data + " ");
        }
    }
}

//Left middle right = > right (hollow)
public static void midOrder(TreeNode root) {
    if (root == null) return;
    Stack<TreeNode> stack = new Stack<>();
    stack.push(root);
    while (!stack.isEmpty()) {
        TreeNode node = stack.pop();
        if (node != null) {
            if (node.right != null) stack.push(node.right);
            stack.push(node);
            stack.push(null);
            if (node.left != null) stack.push(node.left);
        } else {
            node = stack.pop();
            System.out.print(node.data + " ");
        }
    }
}

//Left and right middle = > (hollow) right and left
public static void postOrder(TreeNode root) {
    if (root == null) return;
    Stack<TreeNode> stack = new Stack<>();
    stack.push(root);
    while (!stack.isEmpty()) {
        TreeNode node = stack.pop();
        if (node != null) {
            stack.push(node);
            stack.push(null);
            if (node.right != null) stack.push(node.right);
            if (node.left != null) stack.push(node.left);
        } else {
            node = stack.pop();
            System.out.print(node.data + " ");
        }
    }
}

Sequence traversal:

public static void layerOrder(TreeNode root) {
    if (root == null) return;
    Queue<TreeNode> queue = new LinkedList<>();
    queue.offer(root);
    while (!queue.isEmpty()) {
        TreeNode node = queue.poll();
        System.out.print(node.data + " ");
        if (node.left != null) queue.offer(node.left);
        if (node.right != null) queue.offer(node.right);
    }
}

Knowledge point 04: Spring IOC

Execution process:

Life cycle:

Circular dependency:

nameComplete definitionStorage type
L1 cacheprivate final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);Finished product object
L2 cacheprivate final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);Semi finished product object
L3 cacheprivate final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);lambda expressions

1. If there is only one level cache, can we solve the problem of circular dependency?

If there is only one level cache, it means that both finished objects and semi-finished objects should be placed in the first level cache. When obtaining objects, it is possible to obtain semi-finished objects, which cannot be used directly. Therefore, it is necessary to use the first level cache to store finished objects and the second level cache to store semi-finished objects.

2. Can only L1 and L2 cache solve the problem of circular dependency?

Only the L1 and L2 caches can solve the circular dependency problem, but there are preconditions. The premise is that AOP is not used. If AOP is enabled, Spring will create proxy objects. If there is a circular dependency problem of proxy objects, it still exists.

3. Then the question comes again. Why do you need L3 cache?

The purpose of L3 cache is to solve the problem of circular dependency in the process of proxy.

4. Use the code to demonstrate the whole process of circular dependency execution?

<bean id="a" class="io.github.caochenlei.domain.A">
    <property name="b" ref="b"></property>
</bean>

<bean id="b" class="io.github.caochenlei.domain.B">
    <property name="a" ref="a"></property>
</bean>
public class ABTest {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("ab.xml");
        A a = applicationContext.getBean(A.class);
        System.out.println(a);
        B b = applicationContext.getBean(B.class);
        System.out.println(b);
    }
}

Knowledge point 05: Spring AOP

Not updated yet

Knowledge point 06: TCP triple handshake

  • First handshake: at first, both ends are CLOSED. The Client sets the flag SYN to 1, randomly generates a value seq=x, and sends the packet to the Server. The Client enters the SYN-SENT state and waits for the Server to confirm;
  • The second handshake: after the Server receives the data packet, the flag bit SYN=1 knows that the Client requests to establish a connection. The Server sets the flag bits SYN and ack to 1, ack=x+1, randomly generates a value seq=y, and sends the data packet to the Client to confirm the connection request. The Server enters the SYN-RCVD state. At this time, the operating system allocates TCP cache and variables for the TCP connection;
  • The third Handshake: after receiving the confirmation, the Client checks whether the ACK is x+1 and the ACK is 1. If it is correct, set the flag bit ack to 1 and ack=y+1. At this time, the operating system allocates TCP cache and variables for the TCP connection and sends the data packet to the Server. The Server checks whether the ACK is y+1 and ACK is 1. If it is correct, the connection is ESTABLISHED successfully, The Client and Server enter the ESTABLISHED state, complete the handshake three times, and then the Client and Server can start transmitting data.

Knowledge point 07: TCP wave four times

  • Waving for the first time: the application process of A sends A connection release message segment (FIN=1, sequence number seq=u) to its TCP, stops sending data again, actively closes the TCP connection, enters the FIN-WAIT-1 state, and waits for the confirmation of B.
  • Second wave: after receiving the connection release message segment, B sends A confirmation message segment (ACK=1, seq=v, ack=u+1). B enters the CLOSE-WAIT state. At this time, TCP is in the semi closed state and the connection from A to B is released. After receiving the confirmation from B, A enters the FIN-WAIT-2 state and waits for the connection release message segment sent by B.
  • The third wave: B has no data to send to A, B sends the connection release message segment (FIN=1, ACK=1, seq=w, ack=u+1), B enters the LAST-ACK state and waits for A's confirmation.
  • The fourth wave: after receiving the connection release message segment from B, A sends A confirmation message segment (ACK=1, seq=u+1, ack=w+1), and A enters the TIME-WAIT state. At this time, TCP is not released, and A enters the CLOSED state after the time 2MSL set by the time waiting timer.

Keywords: Java

Added by why not on Sat, 18 Dec 2021 06:15:41 +0200