亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

java 排序算法之歸并排序

 更新時(shí)間:2021年09月01日 15:03:25   作者:天然呆dull  
本文主要講解了排序算法中的歸并排序,文中運(yùn)用大量的圖片和代碼講解的非常詳細(xì),感興趣的朋友可以學(xué)習(xí)一下這篇文章,相信可以幫助到你

簡(jiǎn)單介紹

歸并排序(merge sort)是利用 歸并 的思想實(shí)現(xiàn)的排序方法,該算法采用經(jīng)典的分治(divide-and-conquer)策略

  • 分(divide):將問(wèn)題分成一些小的問(wèn)題,然后遞歸求解
  • 治(conquer):將分的階段得到的各答案「修補(bǔ)」在一起

即:分而治之

該算法是采用分治法(Divide and Conquer)的一個(gè)非常典型的應(yīng)用。將已有序的子序列合并,得到完全有序的序列;即先使每個(gè)子序列有序,再使子序列段間有序。若將兩個(gè)有序表合并成一個(gè)有序表,稱為二路歸并。

基本思想

  • 分:分的過(guò)程只是為了分解
  • 治:分組完成后,開(kāi)始對(duì)每組進(jìn)行排序,然后合并成一個(gè)有序序列,直到最后將所有分組合并成一個(gè)有序序列

可以看到這種結(jié)構(gòu)很像一棵完全二叉樹(shù),本文的歸并排序我們采用遞歸實(shí)現(xiàn)(也可采用迭代的方式實(shí)現(xiàn))。分階段可以理解為就是遞歸拆分子序列的過(guò)程。

:這些數(shù)從始至終都在一個(gè)數(shù)組里(只是抽象的想想成兩個(gè)數(shù)組),除了排序時(shí)會(huì)把要排序的數(shù)copy到一個(gè)臨時(shí)數(shù)組里面,這里如果不懂后面看了代碼后,再返回來(lái)思考就懂了。一定要思考?。。?!

下面的動(dòng)圖可以很直觀的看到整個(gè)算法實(shí)現(xiàn)的過(guò)程,初體驗(yàn)一下吧,后面的代碼可以結(jié)合上面的圖,和這個(gè)動(dòng)圖,來(lái)整理一下邏輯

多個(gè)數(shù)排序動(dòng)圖:

思路分析

對(duì)于分階段相對(duì)較簡(jiǎn)單,下面著重來(lái)對(duì)治階段進(jìn)行分析。

合并相鄰有序子序列分析:下圖以 歸并排序的最后一次合并 為例來(lái)分析,即對(duì)應(yīng)上圖的 [4,5,7,8][1,2,3,6] 兩個(gè)已經(jīng)有序的子序列合并為最終序列 [1,2,3,4,5,6,7,8],下圖展示了實(shí)現(xiàn)步驟

如圖所示:這是最后一次的合并 操作,是兩個(gè)有序序列合并為最終的有序序列。

  • 1.從有序序列開(kāi)始挨個(gè)比較,這里比較 4 和 1,1 < 4,那么 1 進(jìn)入臨時(shí)數(shù)組 temp中,并且將自己的指針右移動(dòng)一位
  • 2.由于圖上綠色部分上一次 4 大于 1,指針并未移動(dòng),然后 4 和 2 對(duì)比,2 < 4 , 2 進(jìn)入到臨時(shí)數(shù)組中,并且將自己的指針右移動(dòng)一位
  • 3. ...
  • 4.如果某一組已經(jīng)全部進(jìn)入了臨時(shí)數(shù)組,那么剩余一組的剩余有序序列直接追加到臨時(shí)數(shù)組中
  • 5.最后,將 temp 內(nèi)容拷貝到原數(shù)組中去,完成排序

代碼實(shí)現(xiàn)

先實(shí)現(xiàn)合并方法,這個(gè)是該算法中最重要的,你也看可以直接看后面的完整算法代碼,再返回來(lái)思考,這個(gè)都隨你。此次是因?yàn)? 的步驟需要用到 的這個(gè),所以我這里就先放 合并的代碼了。

 /**
     * 
     *  最難的是合并,所以可以先完成合并的方法,此方法請(qǐng)參考 基本思想 和 思路分析中的圖解來(lái)完成
     *  動(dòng)腦筋
     *
     * 
     *
     * @param arr   要排序的原始數(shù)組
     * @param left  因?yàn)槭呛喜ⅲ砸玫阶笥覂蛇叺牡臄?shù)組信息,這個(gè)是左側(cè)數(shù)組的第一個(gè)索引值
     * @param mid   因?yàn)槭且粋€(gè)數(shù)組,標(biāo)識(shí)是第一個(gè)數(shù)組的最后一個(gè)索引,即 mid+1 是右側(cè)數(shù)組的第一個(gè)索引,即中間索引
     * @param right 右側(cè)數(shù)組的結(jié)束索引,右邊數(shù)組的最后一個(gè)數(shù)
     * @param temp  臨時(shí)空間,臨時(shí)數(shù)組
     */
    public void merge(int[] arr, int left, int mid, int right, int[] temp) {
        // 定時(shí)臨時(shí)變量,用來(lái)遍歷數(shù)組比較
        int l = left;  // 左邊有序數(shù)組的初始索引
        int r = mid + 1; // 右邊有序數(shù)組的初始索引
        int t = 0; // temp 數(shù)組中當(dāng)前最后一個(gè)有效數(shù)據(jù)的索引
        
        // 1. 按思路先將兩個(gè)數(shù)組(有序的)有序的合并到 temp 中
        // 因?yàn)槭呛喜蓚€(gè)數(shù)組,所以需要兩邊的數(shù)組都還有值的時(shí)候才能進(jìn)行 比較合并
        // 若其中一個(gè)數(shù)組的值遍歷完了(取完了),那么就跳出該循環(huán),把另一個(gè)數(shù)組所剩的值,直接copy進(jìn)臨時(shí)數(shù)組即可
        while (l <= mid && r <= right) {
            // 如果左邊的比右邊的小,則將左邊的該元素填充到 temp 中
            // 并移動(dòng) t++,l++,好繼續(xù)下一個(gè)
            if (arr[l] < arr[r]) {
                temp[t] = arr[l];
                t++;//移動(dòng) temp 臨時(shí)數(shù)組中當(dāng)前最后一個(gè)有效數(shù)據(jù)的索引
                l++; //左邊原始數(shù)組的索引移動(dòng)
            }
            // 否則則將右邊的移動(dòng)到 temp 中
            else {
                temp[t] = arr[r];
                t++;//移動(dòng) temp 臨時(shí)數(shù)組中當(dāng)前最后一個(gè)有效數(shù)據(jù)的索引
                r++;//右邊原始數(shù)組的索引移動(dòng)
            }
        }
        // 2. 如果有任意一邊的數(shù)組還有值,則依序?qū)⑹S鄶?shù)據(jù)填充到 temp 中
        // 如果左側(cè)還有值
        while (l <= mid) {
            temp[t] = arr[l];
            t++;
            l++;
        }
        // 如果右側(cè)還有值
        while (r <= right) {
            temp[t] = arr[r];
            t++;
            r++;
        }

        // 3. 將 temp 數(shù)組,拷貝到原始數(shù)組
        // 注意:只拷貝當(dāng)前temp有效數(shù)據(jù)到對(duì)應(yīng)的原始數(shù)據(jù)中,通俗點(diǎn)說(shuō),就是原始數(shù)組中要排序的數(shù)據(jù),通過(guò)temp排成了有序的,然后將temp中的有序數(shù)據(jù)將原始數(shù)組中原來(lái)要排序的那部分覆蓋了就行了
        int tempL = left; // 從左邊開(kāi)始拷貝,左邊第一個(gè)值的索引
        t = 0;  // temp 中的有效值索引,有效值邊界可以通過(guò) right 判定,因?yàn)楹喜蓚€(gè)數(shù)組到 temp 中,邊界就是 right ,這里自己好好想想
        /*
         * 對(duì)于 8,4,5,7,1,3,6,2 這個(gè)數(shù)組,
         * 從棧頂開(kāi)始合并:8,4 | 5,7       1,3 | 6,2
         * 先左遞歸的話:
         * 第一次:8,4 合并:tempL=0,right=1
         * 第二次:5,7 合并:tempL=2,right=3
         * 第三次:4,8 | 5,7 進(jìn)行合并,tempL=0,right=3
         * 直到左遞歸完成,得到左側(cè)一個(gè)有序的序列:4,5,7,8 然后再開(kāi)始遞歸右邊那個(gè)無(wú)序的
         * 最后回到棧底分解成兩個(gè)數(shù)組的地方,將兩個(gè)數(shù)組合并成一個(gè)有序數(shù)組
         * 這里真的得自己想了,我只能這么說(shuō)了。
         */
        System.out.println("tempL=" + tempL + "; right=" + right);
        while (tempL <= right) {
            arr[tempL] = temp[t];
            tempL++;
            t++;
        }
    }

需要注意的是:這個(gè)圖一定要看明白:

  • 1.一直分解,到棧頂首次合并時(shí),是兩個(gè)數(shù)字,也就是說(shuō),左側(cè)數(shù)組只有一個(gè)數(shù)字,右側(cè)數(shù)組只有一個(gè)數(shù)字
  • 2.左側(cè)數(shù)組只有一個(gè)數(shù)字時(shí),l = 0,r = 1,那么 mid = 0,邊界判定時(shí)要用 l <= mid && r <= right ,否則就會(huì)跳過(guò)對(duì)比合并了

完整代碼如下

    @Test
    public void sortTest() {
        int[] arr = new int[]{8, 4, 5, 7, 1, 3, 6, 2};
        int[] temp = new int[arr.length];
        mergeSort(arr, 0, arr.length - 1, temp);
        System.out.println("排序后:" + Arrays.toString(arr));
    }

    /**
     * 分 和 合并
     */
    public void mergeSort(int[] arr, int left, int right, int[] temp) {
        //確保兩個(gè)數(shù)組中分別都存在至少一個(gè)數(shù)字
        if (left < right) {
            int mid = (left + right) / 2;
            // 先分解左側(cè)
            mergeSort(arr, left, mid, temp);
            // 再分解右側(cè)
            mergeSort(arr, mid + 1, right, temp);
            // 最后合并
            // 由于是遞歸,合并這里一定是棧頂?shù)南葓?zhí)行(兩邊數(shù)組各只有一個(gè)數(shù)時(shí))
            // 第一次:left = 0,right=1
            // 第二次:left = 2,right=3
            // 第三次:left = 0,right=3
//            System.out.println("left=" + left + ";right=" + right);
            merge(arr, left, mid, right, temp);
        }
    }

     /**
     * 
     *  最難的是合并,所以可以先完成合并的方法,此方法請(qǐng)參考 基本思想 和 思路分析中的圖解來(lái)完成
     *  動(dòng)腦筋
     *
     * 
     *
     * @param arr   要排序的原始數(shù)組
     * @param left  因?yàn)槭呛喜ⅲ砸玫阶笥覂蛇叺牡臄?shù)組信息,這個(gè)是左側(cè)數(shù)組的第一個(gè)索引值
     * @param mid   因?yàn)槭且粋€(gè)數(shù)組,標(biāo)識(shí)是第一個(gè)數(shù)組的最后一個(gè)索引,即 mid+1 是右側(cè)數(shù)組的第一個(gè)索引,即中間索引
     * @param right 右側(cè)數(shù)組的結(jié)束索引,右邊數(shù)組的最后一個(gè)數(shù)
     * @param temp  臨時(shí)空間,臨時(shí)數(shù)組
     */
    public void merge(int[] arr, int left, int mid, int right, int[] temp) {
        // 定時(shí)臨時(shí)變量,用來(lái)遍歷數(shù)組比較
        int l = left;  // 左邊有序數(shù)組的初始索引
        int r = mid + 1; // 右邊有序數(shù)組的初始索引
        int t = 0; // temp 數(shù)組中當(dāng)前最后一個(gè)有效數(shù)據(jù)的索引
        
        // 1. 按思路先將兩個(gè)數(shù)組(有序的)有序的合并到 temp 中
        // 因?yàn)槭呛喜蓚€(gè)數(shù)組,所以需要兩邊的數(shù)組都還有值的時(shí)候才能進(jìn)行 比較合并
        // 若其中一個(gè)數(shù)組的值遍歷完了(取完了),那么就跳出該循環(huán),把另一個(gè)數(shù)組所剩的值,直接copy進(jìn)臨時(shí)數(shù)組即可
        while (l <= mid && r <= right) {
            // 如果左邊的比右邊的小,則將左邊的該元素填充到 temp 中
            // 并移動(dòng) t++,l++,好繼續(xù)下一個(gè)
            if (arr[l] < arr[r]) {
                temp[t] = arr[l];
                t++;//移動(dòng) temp 臨時(shí)數(shù)組中當(dāng)前最后一個(gè)有效數(shù)據(jù)的索引
                l++; //左邊原始數(shù)組的索引移動(dòng)
            }
            // 否則則將右邊的移動(dòng)到 temp 中
            else {
                temp[t] = arr[r];
                t++;//移動(dòng) temp 臨時(shí)數(shù)組中當(dāng)前最后一個(gè)有效數(shù)據(jù)的索引
                r++;//右邊原始數(shù)組的索引移動(dòng)
            }
        }
        // 2. 如果有任意一邊的數(shù)組還有值,則依序?qū)⑹S鄶?shù)據(jù)填充到 temp 中
        // 如果左側(cè)還有值
        while (l <= mid) {
            temp[t] = arr[l];
            t++;
            l++;
        }
        // 如果右側(cè)還有值
        while (r <= right) {
            temp[t] = arr[r];
            t++;
            r++;
        }

        // 3. 將 temp 數(shù)組,拷貝到原始數(shù)組
        // 注意:只拷貝當(dāng)前temp有效數(shù)據(jù)到對(duì)應(yīng)的原始數(shù)據(jù)中,通俗點(diǎn)說(shuō),就是原始數(shù)組中要排序的數(shù)據(jù),通過(guò)temp排成了有序的,然后將temp中的有序數(shù)據(jù)將原始數(shù)組中原來(lái)要排序的那部分覆蓋了就行了
        int tempL = left; // 從左邊開(kāi)始拷貝,左邊第一個(gè)值的索引
        t = 0;  // temp 中的有效值索引,有效值邊界可以通過(guò) right 判定,因?yàn)楹喜蓚€(gè)數(shù)組到 temp 中,邊界就是 right ,這里自己好好想想
        /*
         * 對(duì)于 8,4,5,7,1,3,6,2 這個(gè)數(shù)組,
         * 從棧頂開(kāi)始合并:8,4 | 5,7       1,3 | 6,2
         * 先左遞歸的話:
         * 第一次:8,4 合并:tempL=0,right=1
         * 第二次:5,7 合并:tempL=2,right=3
         * 第三次:4,8 | 5,7 進(jìn)行合并,tempL=0,right=3
         * 直到左遞歸完成,得到左側(cè)一個(gè)有序的序列:4,5,7,8 然后再開(kāi)始遞歸右邊那個(gè)無(wú)序的
         * 最后回到棧底分解成兩個(gè)數(shù)組的地方,將兩個(gè)數(shù)組合并成一個(gè)有序數(shù)組
         * 這里真的得自己想了,我只能這么說(shuō)了。
         */
        System.out.println("tempL=" + tempL + "; right=" + right);
        while (tempL <= right) {
            arr[tempL] = temp[t];
            tempL++;
            t++;
        }
    }

測(cè)試輸出

tempL=0; right=1
tempL=2; right=3
tempL=0; right=3
tempL=4; right=5
tempL=6; right=7
tempL=4; right=7
tempL=0; right=7
排序后:[1, 2, 3, 4, 5, 6, 7, 8]

從這里也可以看到,先左遞歸的話,可以看到最開(kāi)始合并的索引是 0,1 也就是在棧頂開(kāi)始首次遞歸時(shí):兩個(gè)數(shù)組中分別只有一個(gè)數(shù)字。

最后一次合并:則是回到了最初棧底開(kāi)始分解的方法,將兩個(gè)數(shù)組 0到7 進(jìn)行排序到臨時(shí)數(shù)組 temp ,最后將temp中的數(shù)據(jù)再?gòu)?code> 0到7 覆蓋到原始數(shù)組中。完成了排序 。

8 個(gè)數(shù)字,會(huì)進(jìn)行 7 次 合并

結(jié)合上面動(dòng)圖進(jìn)行思考。

對(duì)代碼的一些改進(jìn)

根據(jù)上述所講的基本思想和思路分析,對(duì)代碼進(jìn)行了一些改進(jìn)修改,減小代碼的臃腫。

public class MyMergeSortTest {
    @Test
    public void sortTest() {
        int[] arr = new int[]{8, 4, 5, 7, 1, 3, 6, 2};
        mergeSort(arr);
        System.out.println("排序后:" + Arrays.toString(arr));
    }

    public void mergeSort(int arr[]) {
        int[] temp = new int[arr.length];
        doMergeSort(arr, 0, arr.length - 1, temp);
    }

    /**
     * 分治 與 合并
     *
     * @param arr
     * @param left
     * @param right
     * @param temp
     */
    private void doMergeSort(int[] arr, int left, int right, int[] temp) {
        // 當(dāng)還可以分解時(shí),就做分解操作
        if (left < right) {
            int mid = (left + right) / 2;
            // 先左遞歸分解
            doMergeSort(arr, left, mid, temp);
            // 再右遞歸分解
            doMergeSort(arr, mid + 1, right, temp);
            // 左遞歸分解到棧頂時(shí),其實(shí)也是分為左右數(shù)組
            // 左右都到棧頂時(shí),開(kāi)始合并:
            // 第一次:合并的是 0,1 的索引,分解到最后的時(shí)候,其實(shí)只有一個(gè)數(shù)為一組,所以第一次合并是合并兩個(gè)數(shù)字
            merge(arr, left, mid, right, temp);
        }
    }

    /**
     * 開(kāi)始合并,每次合并都是兩組,第一次合并是兩個(gè)數(shù)字,左右一組都只有一個(gè)數(shù)字
     *
     * @param arr
     * @param left
     * @param mid
     * @param right
     * @param temp
     */
    private void merge(int[] arr, int left, int mid, int right, int[] temp) {
        // 1. 按照規(guī)則,將 temp 數(shù)組填充
        // 2. 當(dāng)任意一邊填充完成后,剩余未填充的依次填充到 temp 數(shù)組中
        // 3. 將 temp 數(shù)組的有效內(nèi)容,拷貝會(huì)原數(shù)組,也就是將這次排序好的數(shù)組覆蓋回原來(lái)排序的原數(shù)組中

        int l = left; // 左側(cè)數(shù)組初始索引
        int r = mid + 1; // 右側(cè)數(shù)組初始索引
        int t = 0; // 當(dāng)前 temp 中有效數(shù)據(jù)的最后一個(gè)元素索引
        
        // 1. 按照規(guī)則,將 temp 數(shù)組填充
        // 當(dāng)兩邊都還有數(shù)字可比較的時(shí)候,進(jìn)行比較,然后填充 temp 數(shù)組
        // 只要任意一邊沒(méi)有數(shù)值可用時(shí),就僅需到下一步驟
        while (l <= mid && r <= right) {
            // 當(dāng)左邊比右邊小時(shí),則填充到 temp 數(shù)組中
            if (arr[l] < arr[r]) {
                // 賦值完成后,t 和 l 都需要 +1,往后移動(dòng)一個(gè)位置
                // t++ 是先把 t 進(jìn)行賦值,再進(jìn)行 t+1 操作
                temp[t++] = arr[l++];
            } else {
                // 當(dāng)不滿足時(shí),則說(shuō)明 右側(cè)數(shù)字比左側(cè)的小,進(jìn)行右側(cè)的填充
                temp[t++] = arr[r++];
            }
        }

        // 2. 有可能有其中一邊會(huì)有剩余數(shù)字未填充到 temp 中,進(jìn)行收尾處理
        while (l <= mid) {
            temp[t++] = arr[l++];
        }
        while (r <= right) {
            temp[t++] = arr[r++];
        }

        // 3. 將這個(gè)有序數(shù)組,覆蓋會(huì)原始排序的數(shù)組中
        t = 0;
        int tempL = left; // 從左側(cè)開(kāi)始,到右側(cè)結(jié)束,就是這一次要合并的兩組數(shù)據(jù)
        while (tempL <= right) {
            arr[tempL++] = temp[t++];
        }
    }
}

大數(shù)據(jù)量耗時(shí)測(cè)試

    /**
     * 大量數(shù)據(jù)排序時(shí)間測(cè)試
     */
    @Test
    public void bulkDataSort() {
        int max = 80000;
//        max = 8;
        int[] arr = new int[max];
        for (int i = 0; i < max; i++) {
            arr[i] = (int) (Math.random() * 80000);
        }
        if (arr.length < 10) {
            System.out.println("原始數(shù)組:" + Arrays.toString(arr));
        }
        Instant startTime = Instant.now();
        int[] temp = new int[arr.length];
        mergeSort(arr, 0, arr.length - 1, temp);
        if (arr.length < 10) {
            System.out.println("排序后:" + Arrays.toString(arr));
        }
        Instant endTime = Instant.now();
        System.out.println("共耗時(shí):" + Duration.between(startTime, endTime).toMillis() + " 毫秒");
    }

多次測(cè)試輸出

共耗時(shí):26 毫秒
共耗時(shí):37 毫秒
共耗時(shí):30 毫秒
共耗時(shí):30 毫秒

復(fù)雜度

歸并排序比較占用內(nèi)存,但卻是一種效率高且穩(wěn)定的算法。

改進(jìn)歸并排序在歸并時(shí)先判斷前段序列的最大值與后段序列最小值的關(guān)系再確定是否進(jìn)行復(fù)制比較。如果前段序列的最大值小于等于后段序列最小值,則說(shuō)明序列可以直接形成一段有序序列不需要再歸并,反之則需要。所以在序列本身有序的情況下時(shí)間復(fù)雜度可以降至O(n)。

TimSort可以說(shuō)是歸并排序的終極優(yōu)化版本,主要思想就是檢測(cè)序列中的天然有序子段(若檢測(cè)到嚴(yán)格降序子段則翻轉(zhuǎn)序列為升序子段)。在最好情況下無(wú)論升序還是降序都可以使時(shí)間復(fù)雜度降至為O(n),具有很強(qiáng)的自適應(yīng)性。

最好時(shí)間復(fù)雜度 最壞時(shí)間復(fù)雜度 平均時(shí)間復(fù)雜度 空間復(fù)雜度 穩(wěn)定性
傳統(tǒng)歸并排序 O(nlogn) O(nlogn) O(nlogn) T(n) 穩(wěn)定
改進(jìn)歸并排序 [1] O(n) O(nlogn) O(nlogn) T(n) 穩(wěn)定
TimSort O(n) O(nlogn) O(nlogn) T(n) 穩(wěn)定

我個(gè)人感覺(jué)歸并排序的邏輯相比快速排序來(lái)說(shuō)更為容易理解,而且時(shí)間復(fù)雜度和快排一樣。關(guān)于快排的有關(guān)講解請(qǐng)看java 排序算法之快速排序

到此這篇關(guān)于java 排序算法之歸并排序的文章就介紹到這了,更多相關(guān)java 歸并排序內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot中l(wèi)ogback日志保存到mongoDB的方法

    SpringBoot中l(wèi)ogback日志保存到mongoDB的方法

    這篇文章主要介紹了SpringBoot中l(wèi)ogback日志保存到mongoDB的方法,
    2017-11-11
  • SpringBoot使用PropertiesLauncher加載外部jar包

    SpringBoot使用PropertiesLauncher加載外部jar包

    這篇文章主要介紹了SpringBoot使用PropertiesLauncher加載外部jar包,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-07-07
  • SpringBoot項(xiàng)目使用MDC給日志增加唯一標(biāo)識(shí)的實(shí)現(xiàn)步驟

    SpringBoot項(xiàng)目使用MDC給日志增加唯一標(biāo)識(shí)的實(shí)現(xiàn)步驟

    本文介紹了如何在SpringBoot項(xiàng)目中使用MDC(Mapped?Diagnostic?Context)為日志增加唯一標(biāo)識(shí),以便于日志追蹤,通過(guò)創(chuàng)建日志攔截器、配置攔截器以及修改日志配置文件,可以實(shí)現(xiàn)這一功能,文章還提供了源碼地址,方便讀者學(xué)習(xí)和參考,感興趣的朋友一起看看吧
    2025-03-03
  • Spring中事務(wù)用法示例及實(shí)現(xiàn)原理詳解

    Spring中事務(wù)用法示例及實(shí)現(xiàn)原理詳解

    這篇文章主要給大家介紹了關(guān)于Spring中事務(wù)用法示例及實(shí)現(xiàn)原理的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2018-11-11
  • JavaWeb實(shí)現(xiàn)上傳文件功能

    JavaWeb實(shí)現(xiàn)上傳文件功能

    這篇文章主要為大家詳細(xì)介紹了JavaWeb實(shí)現(xiàn)上傳文件功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • MyBatis-Plus Sequence主鍵的實(shí)現(xiàn)

    MyBatis-Plus Sequence主鍵的實(shí)現(xiàn)

    這篇文章主要介紹了MyBatis-Plus Sequence主鍵的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • druid配置數(shù)據(jù)庫(kù)連接使用密文密碼方式

    druid配置數(shù)據(jù)庫(kù)連接使用密文密碼方式

    這篇文章主要介紹了druid配置數(shù)據(jù)庫(kù)連接使用密文密碼方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,
    2023-12-12
  • 詳解Spring簡(jiǎn)單容器中的Bean基本加載過(guò)程

    詳解Spring簡(jiǎn)單容器中的Bean基本加載過(guò)程

    本篇將對(duì)定義在 XMl 文件中的 bean,從靜態(tài)的的定義到變成可以使用的對(duì)象的過(guò)程,即 bean 的加載和獲取的過(guò)程進(jìn)行一個(gè)整體的了解
    2017-05-05
  • Java并發(fā)Lock接口實(shí)現(xiàn)示例詳解

    Java并發(fā)Lock接口實(shí)現(xiàn)示例詳解

    這篇文章主要為大家介紹了Java并發(fā)Lock接口,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • Java中的FileWriter用法詳解與實(shí)戰(zhàn)記錄

    Java中的FileWriter用法詳解與實(shí)戰(zhàn)記錄

    這篇文章主要給大家介紹了關(guān)于Java中FileWriter用法的相關(guān)資料,包括寫(xiě)入字符數(shù)據(jù)到文件、字符數(shù)組和部分字符寫(xiě)入、配合BufferedWriter使用等方法,同時(shí)也解釋了其與OutputStreamWriter,BufferedWriter的異同特性,適合簡(jiǎn)單的文件寫(xiě)入操作,需要的朋友可以參考下
    2024-10-10

最新評(píng)論