最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java中比較器Comparable和Comparator超詳細(xì)解析

 更新時(shí)間:2025年06月18日 10:45:33   作者:小釗.  
Java中在進(jìn)行數(shù)據(jù)排序時(shí),Comparable和Comparator必不可少會(huì)遇得到,這篇文章主要給大家介紹了關(guān)于Java中比較器Comparable和Comparator的相關(guān)資料,需要的朋友可以參考下

前言

在 Java 中,Comparable 和 Comparator 是用于對(duì)象排序的重要接口。它們提供了不同的排序方式,適用于不同的需求,同時(shí)在 Java 底層排序算法中發(fā)揮著關(guān)鍵作用。本文將從基礎(chǔ)概念、使用方法、排序?qū)崿F(xiàn)(包括升序、降序)、底層實(shí)現(xiàn)原理以及適用場(chǎng)景等方面進(jìn)行詳細(xì)解析。

一、 Comparable 和 Comparator 的基本概念

在 Java 中,排序通常用于 數(shù)組 和 集合(List),兩者的排序分別由 Arrays.sort() 和 Collections.sort() 進(jìn)行,而這兩個(gè)方法都依賴于 Comparable 和 Comparator。

1.1 Comparable 接口(自然排序)

  • Comparable 是一個(gè) 內(nèi)部比較器,表示對(duì)象本身支持排序規(guī)則。

  • 需要在類(lèi)中實(shí)現(xiàn) compareTo() 方法,定義默認(rèn)的排序方式。

  • 適用于對(duì)象有唯一的自然排序方式,如 Integer、StringDouble 等。

代碼示例(按照 age 升序排序):

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

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

    @Override
    public int compareTo(Person other) {
        return Integer.compare(this.age, other.age); // 按年齡升序
    }

    @Override
    public String toString() {
        return name + " (" + age + ")";
    }
}

public class ComparableExample {
    public static void main(String[] args) {
        Person[] people = {
            new Person("Alice", 25),
            new Person("Bob", 22),
            new Person("Charlie", 30)
        };

        Arrays.sort(people); // 按 `Comparable` 規(guī)則排序
        System.out.println(Arrays.toString(people));
    }
}

輸出結(jié)果:

[Bob (22), Alice (25), Charlie (30)]

Comparable 的排序方式是 類(lèi)內(nèi)部固定的,所有調(diào)用 sort() 的地方都使用同樣的規(guī)則。

1.2 Comparator 接口(自定義排序)

  • Comparator 是一個(gè) 外部比較器,可以用于自定義排序規(guī)則。

  • 需要實(shí)現(xiàn) compare() 方法,可以在不同場(chǎng)景使用不同的比較邏輯。

  • 適用于對(duì)象有 多種排序需求,如按年齡、姓名、ID 等。

代碼示例(按 name 進(jìn)行字母升序排序):

class NameComparator implements Comparator<Person> {
    @Override
    public int compare(Person p1, Person p2) {
        return p1.name.compareTo(p2.name); // 按名稱(chēng)字母升序
    }
}

public class ComparatorExample {
    public static void main(String[] args) {
        List<Person> people = new ArrayList<>();
        people.add(new Person("Alice", 25));
        people.add(new Person("Bob", 22));
        people.add(new Person("Charlie", 30));

        people.sort(new NameComparator()); // 使用外部比較器進(jìn)行排序
        System.out.println(people);
    }
}

輸出結(jié)果:

[Alice (25), Bob (22), Charlie (30)]

使用 Comparator 可以定義多種排序規(guī)則,不同的需求可以使用不同的比較器,非常靈活。

二、升序和降序排序?qū)崿F(xiàn)

2.1 Comparable 的升序和降序

在 Comparable 中,只能通過(guò)修改 compareTo() 方法來(lái)改變排序順序:

@Override
public int compareTo(Person other) {
    return Integer.compare(other.age, this.age); // 降序排序
}

2.2 Comparator 的升序和降序

使用 Comparator 可以輕松實(shí)現(xiàn) 不同排序方式

Comparator<Person> ageAscending = Comparator.comparingInt(p -> p.age); // 按年齡升序
Comparator<Person> ageDescending = (p1, p2) -> Integer.compare(p2.age, p1.age); // 按年齡降序

代碼示例:

people.sort(ageAscending);  // 升序排序
people.sort(ageDescending); // 降序排序

使用 Java 8 的 Lambda 表達(dá)式: 

people.sort((p1, p2) -> p1.name.compareTo(p2.name)); // 按姓名排序

三. 底層排序?qū)崿F(xiàn)

在 Java 中,Arrays.sort() 和 Collections.sort() 在不同數(shù)據(jù)類(lèi)型下采用不同的排序算法:

3.1 Arrays.sort()(適用于數(shù)組)

  • Arrays.sort() 主要用于 數(shù)組排序,其底層實(shí)現(xiàn)因數(shù)據(jù)類(lèi)型不同而有所不同:

  • 基本類(lèi)型(int[]、double[] 等):使用 Dual-Pivot Quicksort(雙軸快速排序),這是 Quicksort 的一種優(yōu)化版本。

  • 對(duì)象類(lèi)型(Integer[]String[] 等):使用 TimSort(歸并排序 + 插入排序的優(yōu)化組合)。

3.1.1 基本類(lèi)型:雙軸快速排序

對(duì)于 int[]double[] 等基本數(shù)據(jù)類(lèi)型的數(shù)組排序,Arrays.sort() 使用的是 雙軸快速排序(Dual-Pivot Quicksort),它是由 Vladimir Yaroslavskiy 在 2009 年提出的改進(jìn)版 快速排序,其核心思想是:

  • 選取兩個(gè)基準(zhǔn)點(diǎn)(pivot),將數(shù)組劃分為 三個(gè)部分

    • 小于第一個(gè) pivot 的部分

    • 介于兩個(gè) pivot 之間的部分

    • 大于第二個(gè) pivot 的部分

  • 遞歸對(duì)三個(gè)子數(shù)組進(jìn)行排序。

這種優(yōu)化相比于傳統(tǒng)的單軸快速排序,減少了遞歸調(diào)用的次數(shù),提高了排序效率。

源碼分析

在 Arrays.sort(int[] a) 的源碼中:

public static void sort(int[] a) {
    DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
}

它會(huì)調(diào)用 DualPivotQuicksort.sort(),具體實(shí)現(xiàn)如下:

static void sort(int[] a, int left, int right, int[] work, int workBase, int workLen) {
    if (right - left < QUICKSORT_THRESHOLD) {
        insertionSort(a, left, right); // 小數(shù)組使用插入排序
        return;
    }

    int pivot1 = a[left], pivot2 = a[right];
    if (pivot1 > pivot2) {
        swap(a, left, right);
        pivot1 = a[left];
        pivot2 = a[right];
    }

    int less = left + 1;
    int great = right - 1;

    for (int k = less; k <= great; k++) {
        if (a[k] < pivot1) {
            swap(a, k, less++);
        } else if (a[k] > pivot2) {
            swap(a, k, great--);
        }
    }

    sort(a, left, less - 1, work, workBase, workLen);
    sort(a, less, great, work, workBase, workLen);
    sort(a, great + 1, right, work, workBase, workLen);
}

可以看出,Dual-Pivot Quicksort 主要優(yōu)化點(diǎn)

  • 雙軸劃分:比傳統(tǒng)快速排序減少遞歸層數(shù),提高效率。

  • 小數(shù)據(jù)量時(shí)使用插入排序,減少不必要的遞歸。

3.1.2對(duì)象類(lèi)型:TimSort(改進(jìn)版歸并排序)

對(duì)于對(duì)象數(shù)組(如 Integer[]、String[]),Java 采用的是 TimSort,它結(jié)合了 歸并排序(MergeSort)+ 插入排序(InsertionSort),并做了一些優(yōu)化:

  • 數(shù)據(jù)預(yù)處理:TimSort 先尋找 已經(jīng)排序的子序列(run),如果數(shù)據(jù)本身有部分有序,它可以減少比較次數(shù)。

  • 小規(guī)模數(shù)據(jù)使用插入排序:避免小規(guī)模數(shù)據(jù)使用歸并排序?qū)е麻_(kāi)銷(xiāo)大。

  • 智能歸并:選擇合適的子序列進(jìn)行合并,避免不必要的合并操作,提高效率。

源碼分析:

public static <T> void sort(T[] a, Comparator<? super T> c) {
    if (c == null) {
        Arrays.sort(a); // 調(diào)用默認(rèn)的 Comparable 方式排序
    } else {
        TimSort.sort(a, c); // 使用 Comparator 進(jìn)行排序
    }
}

核心代碼:

static <T> void sort(T[] a, Comparator<? super T> c) {
    int lo = 0, hi = a.length;
    if (hi - lo < INSERTION_SORT_THRESHOLD) {
        insertionSort(a, lo, hi, c); // 小數(shù)據(jù)量使用插入排序
        return;
    }
    int mid = (lo + hi) >>> 1;
    sort(a, lo, mid, c);
    sort(a, mid, hi, c);
    merge(a, lo, mid, hi, c); // 歸并兩個(gè)有序數(shù)組
}

TimSort 的優(yōu)點(diǎn):

  • 適用于部分有序的數(shù)據(jù),比傳統(tǒng)歸并排序更快。

  • 避免不必要的合并,提高效率。

3.2. Collections.sort() 的底層實(shí)現(xiàn)

Collections.sort() 主要用于 List 進(jìn)行排序,它本質(zhì)上是 List 的 Arrays.sort(),所以它的底層也是 TimSort。

public static <T extends Comparable<? super T>> void sort(List<T> list) {
    Object[] array = list.toArray();
    Arrays.sort(array);
    for (int i = 0; i < list.size(); i++)
        list.set(i, (T) array[i]);
}

它的執(zhí)行過(guò)程

  • 將 List 轉(zhuǎn)換成數(shù)組

  • 調(diào)用 Arrays.sort() 進(jìn)行排序

  • 再把排好序的數(shù)組元素賦值回 List

這意味著 Collections.sort() 的底層仍然是 TimSort

排序方法適用范圍底層實(shí)現(xiàn)
Arrays.sort(int[])基本類(lèi)型數(shù)組Dual-Pivot Quicksort(雙軸快速排序)
Arrays.sort(T[])對(duì)象數(shù)組TimSort(歸并排序 + 插入排序優(yōu)化)
Collections.sort(List<T>)List 容器TimSort(底層調(diào)用 Arrays.sort())
Arrays.sort(arr, Comparator)自定義對(duì)象排序TimSort(支持 Comparator)

四、結(jié)論與總結(jié)

  • Comparable 適用于對(duì)象有固定的排序方式,如 String、Integer,實(shí)現(xiàn) compareTo() 進(jìn)行排序。

  • Comparator 適用于需要多個(gè)排序規(guī)則的情況,可以使用 compare() 進(jìn)行定制排序。

  • 底層排序算法

    • 基本類(lèi)型使用 Dual-Pivot QuickSort(雙軸快排)。

    • 對(duì)象類(lèi)型和 List 使用 TimSort(歸并排序 + 插入排序優(yōu)化)

  • Comparator 更靈活,可以動(dòng)態(tài)傳遞不同的比較器,適用于多種排序需求。

掌握 Comparable 和 Comparator,可以幫助你在開(kāi)發(fā)中實(shí)現(xiàn)更高效的排序邏輯!

到此這篇關(guān)于Java中比較器Comparable和Comparator的文章就介紹到這了,更多相關(guān)Java比較器Comparable和Comparator內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 關(guān)于maven打包時(shí)的報(bào)錯(cuò): Return code is: 501 , ReasonPhrase:HTTPS Required

    關(guān)于maven打包時(shí)的報(bào)錯(cuò): Return code is: 501 , ReasonPhrase:HTTPS Requ

    這篇文章主要介紹了關(guān)于maven打包時(shí)的報(bào)錯(cuò): Return code is: 501 , ReasonPhrase:HTTPS Required,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • Java線程的并發(fā)工具類(lèi)實(shí)現(xiàn)原理解析

    Java線程的并發(fā)工具類(lèi)實(shí)現(xiàn)原理解析

    本文給大家講解Java線程的并發(fā)工具類(lèi)的一些知識(shí),通過(guò)適用場(chǎng)景分析大數(shù)據(jù)量統(tǒng)計(jì)類(lèi)任務(wù)的實(shí)現(xiàn)原理和封裝,多個(gè)示例代碼講解的非常詳細(xì),對(duì)java線程并發(fā)工具類(lèi)相關(guān)知識(shí)感興趣的朋友一起學(xué)習(xí)下吧
    2021-06-06
  • 一文掌握J(rèn)ava中List和Set接口的基本使用

    一文掌握J(rèn)ava中List和Set接口的基本使用

    這篇文章主要為大家詳細(xì)介紹Java中List和Set接口,文中通過(guò)示例代碼讓大家能夠輕松掌握List和Set接口的基本使用,感興趣的可以跟隨小編一起學(xué)習(xí)一下
    2022-07-07
  • SpringCloud gateway request的body驗(yàn)證或修改方式

    SpringCloud gateway request的body驗(yàn)證或修改方式

    這篇文章主要介紹了SpringCloud gateway request的body驗(yàn)證或修改方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • SpringBoot利用jackson格式化時(shí)間的三種方法

    SpringBoot利用jackson格式化時(shí)間的三種方法

    日常開(kāi)發(fā)過(guò)程中經(jīng)常會(huì)使用json進(jìn)行數(shù)據(jù)的傳輸,這就涉及到了對(duì)象和json的相互轉(zhuǎn)化,常用的解決方案有:Jackson(推薦)、谷歌的Gson、阿里的Fastjson,這篇文章主要給大家介紹了關(guān)于SpringBoot如何利用jackson格式化時(shí)間的相關(guān)資料,需要的朋友可以參考下
    2021-06-06
  • Java中的線程安全問(wèn)題詳細(xì)解析

    Java中的線程安全問(wèn)題詳細(xì)解析

    這篇文章主要介紹了Java中的線程安全問(wèn)題詳細(xì)解析,線程安全是如果有多個(gè)線程在同時(shí)運(yùn)行,而這些線程可能會(huì)同時(shí)運(yùn)行這段代碼,程序每次運(yùn)行結(jié)果和單線程運(yùn)行的結(jié)果是一樣的,而且其他的變量的值也和預(yù)期的是一樣的,此時(shí)我們就稱(chēng)之為是線程安全的,需要的朋友可以參考下
    2023-11-11
  • SpringBoot項(xiàng)目中filter的兩種使用詳解

    SpringBoot項(xiàng)目中filter的兩種使用詳解

    文章介紹了兩種方式在Spring Boot中創(chuàng)建和配置過(guò)濾器:使用`@WebFilter`注解和`@ServletComponentScan`注解,以及通過(guò)`@Bean`注解自定義過(guò)濾器并加載到IOC容器,通過(guò)測(cè)試啟動(dòng)項(xiàng)目并訪問(wèn)指定URL,可以查看控制臺(tái)打印的過(guò)濾器執(zhí)行順序結(jié)果
    2025-10-10
  • Java中的內(nèi)存泄露問(wèn)題和解決辦法

    Java中的內(nèi)存泄露問(wèn)題和解決辦法

    大家好,本篇文章主要講的是Java中的內(nèi)存泄露問(wèn)題和解決辦法,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下
    2022-01-01
  • Spring中的Eureka服務(wù)過(guò)期詳細(xì)解析

    Spring中的Eureka服務(wù)過(guò)期詳細(xì)解析

    這篇文章主要介紹了Spring中的Eureka服務(wù)過(guò)期詳細(xì)解析,如果有一些服務(wù)過(guò)期了,或者宕機(jī)了,就不會(huì)調(diào)用shutdown()方法,也不會(huì)去發(fā)送請(qǐng)求下線服務(wù)實(shí)例,需要的朋友可以參考下
    2023-11-11
  • Android中比較常見(jiàn)的Java super關(guān)鍵字

    Android中比較常見(jiàn)的Java super關(guān)鍵字

    這篇文章主要為大家介紹了Android中比較常見(jiàn)的Java super關(guān)鍵字,具有一定的學(xué)習(xí)參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-01-01

最新評(píng)論

湟中县| 故城县| 景德镇市| 湘西| 桦川县| 大竹县| 泰和县| 勐海县| 保德县| 大埔区| 蒙阴县| 郴州市| 邓州市| 南皮县| 白河县| 濉溪县| 嘉定区| 高陵县| 望谟县| 耿马| 江阴市| 宾阳县| 沾化县| 哈密市| 西乌珠穆沁旗| 淮安市| 土默特右旗| 遵化市| 香河县| 屏东市| 青田县| 广宗县| 哈巴河县| 乌拉特前旗| 噶尔县| 定结县| 拉孜县| 马边| 乌兰县| 许昌县| 石台县|