Inhaltsverzeichnis
Quellcode-Analyse
Heim Java javaLernprogramm Vergleichende Einführung in Comparable und Comparator in Java (Codebeispiel)

Vergleichende Einführung in Comparable und Comparator in Java (Codebeispiel)

Feb 19, 2019 pm 03:56 PM
java


Dieser Artikel bietet Ihnen eine vergleichende Einführung (Codebeispiel) zwischen Comparable und Comparator. Er hat einen gewissen Referenzwert.

1. Übersicht

Die Sortierung in Java erfolgt über die beiden Schnittstellen Comparable und Comparator.

Vergleichbar bedeutet, dass es sortiert werden kann und Objekte von Klassen, die diese Schnittstelle implementieren, automatisch über die Sortierfunktion verfügen.

Komparator stellt einen Komparator dar, der für das Objekt der Zielklasse definiert ist. Im Allgemeinen wird dieser Komparator als Parameter übergeben.

2. Vergleichbar

Die chinesische Bedeutung von Vergleichbar ist, dass es sortiert werden kann, was bedeutet, dass es die Sortierfunktion unterstützt. Solange unsere Klasse diese Schnittstelle implementiert, können Objekte dieser Klasse automatisch sortiert werden. Und diese Ordnung nennt man die natürliche Ordnung der Klassen. Listen von Objekten dieser Klasse können nach Collections.sort und Arrays.sort sortiert werden. Gleichzeitig sind Instanzen dieser Klasse als Schlüssel einer sortierten Karte und Elemente einer sortierten Menge qualifiziert.

Wenn a und b beide Instanzen der Klasse C sind, die die Comparable-Schnittstelle implementiert, wird sie nur dann aufgerufen, wenn das Ergebnis von a.compareTo(b) mit dem Ergebnis von a.equals(b) übereinstimmt Klasse C. Die natürliche Ordnung steht im Einklang mit Gleichen. Es wird dringend empfohlen, die natürliche Reihenfolge der Klasse mit dem Ergebnis von equal in Einklang zu halten, denn wenn sie inkonsistent sind, ändert sich das Verhalten einer sortierten Karte mit Objekten dieser Klasse als Schlüssel und einer sortierten Menge mit Objekten dieser Klasse als Elementen benimm dich seltsam.

Wenn beispielsweise für eine sortierte Menge, die die Comparable-Schnittstelle implementiert, das Ergebnis von a.equals(b) falsch ist und a.compareTo(b)==0, dann ist die zweite die Additionsoperation von Elementen wird fehlschlagen, weil aus Sicht der sortierten Menge die beiden in der Sortierung konsistent sind und keine doppelten Elemente gespeichert werden.

Tatsächlich stimmt die natürliche Reihenfolge der Klassen in Java grundsätzlich mit Gleichen überein, mit Ausnahme von BigDecimal, da die natürliche Reihenfolge in BigDecimal mit den Gleichen von Elementen mit demselben Wert, aber unterschiedlicher Genauigkeit (z. B. 4) übereinstimmt und 4,00) .

Quellcode-Analyse

public interface Comparable<T> {
    public int compareTo(T o);
}
Nach dem Login kopieren

Sie können dem Quellcode entnehmen, dass die Schnittstelle nur eine abstrakte Methode „compareTo“ hat. Diese Methode dient hauptsächlich dazu, die Art und Weise zu definieren, wie unsere Klassen sortiert werden. Die Methode „compareTo“ wird verwendet, um das aktuelle Element a mit dem angegebenen Element b zu vergleichen. Wenn a > int <

3. Komparator

Komparator wird auf Chinesisch als Komparator übersetzt. Er kann als Parameter an die Methoden Collections.sort und Arrays.sort übergeben werden, um einen bestimmten Wert anzugeben Klassenobjekt. Sortieren nach. Gleichzeitig kann auch die Sortiermethode für sortierte Sätze und sortierte Karten angegeben werden.

Ähnlich wie bei Comparable muss bei der Angabe eines Komparators im Allgemeinen sichergestellt werden, dass das Vergleichsergebnis mit dem Gleichheitsergebnis übereinstimmt. Wenn sie inkonsistent sind, ändert sich auch das Verhalten des entsprechenden sortierten Satzes und der sortierten Karte seltsam.

Es wird empfohlen, dass die implementierte Komparatorklasse auch die Schnittstelle java.io.Serializable implementiert, um über Serialisierungsfunktionen zu verfügen, da sie als Sortiermethode für serialisierte Datenstrukturen (TreeSet, TreeMap) verwendet werden kann.

Quellcode-Analyse

@FunctionalInterface
public interface Comparator<T> {
    // 唯一的抽象方法,用于定义比较方式(即排序方式)
    // o1>o2,返回1;o1=o2,返回0;o1<o2,返回-1
    int compare(T o1, T o2);
    boolean equals(Object obj);
    // 1.8新增的默认方法:用于反序排列
    default Comparator<T> reversed() {
        return Collections.reverseOrder(this);
    }
    // 1.8新增的默认方法:用于构建一个次级比较器,当前比较器比较结果为0,则使用次级比较器比较
    default Comparator<T> thenComparing(Comparator<? super T> other) {
        Objects.requireNonNull(other);
        return (Comparator<T> & Serializable) (c1, c2) -> {
            int res = compare(c1, c2);
            return (res != 0) ? res : other.compare(c1, c2);
        };
    }
    // 1.8新增默认方法:指定次级比较器的
    // keyExtractor表示键提取器,定义提取方式
    // keyComparator表示键比较器,定义比较方式
    default <U> Comparator<T> thenComparing(
            Function<? super T, ? extends U> keyExtractor,
            Comparator<? super U> keyComparator)
    {
        return thenComparing(comparing(keyExtractor, keyComparator));
    }
    // 1.8新增默认方法:用于执行键的比较,采用的是由键对象内置的比较方式
    default <U extends Comparable<? super U>> Comparator<T> thenComparing(
            Function<? super T, ? extends U> keyExtractor)
    {
        return thenComparing(comparing(keyExtractor));
    }
    // 1.8新增默认方法:用于比较执行int类型的键的比较
    default Comparator<T> thenComparingInt(ToIntFunction<? super T> keyExtractor) {
        return thenComparing(comparingInt(keyExtractor));
    }
    // 1.8新增默认方法:用于比较执行long类型的键的比较
    default Comparator<T> thenComparingLong(ToLongFunction<? super T> keyExtractor) {
        return thenComparing(comparingLong(keyExtractor));
    }
    // 1.8新增默认方法:用于比较执行double类型的键的比较
    default Comparator<T> thenComparingDouble(ToDoubleFunction<? super T> keyExtractor) {
        return thenComparing(comparingDouble(keyExtractor));
    }
    // 1.8新增静态方法:用于得到一个相反的排序的比较器,这里针对的是内置的排序方式(即继承Comparable)
    public static <T extends Comparable<? super T>> Comparator<T> reverseOrder() {
        return Collections.reverseOrder();
    }
    // 1.8新增静态方法:用于得到一个实现了Comparable接口的类的比较方式的比较器
    // 简言之就是将Comparable定义的比较方式使用Comparator实现
    @SuppressWarnings("unchecked")
    public static <T extends Comparable<? super T>> Comparator<T> naturalOrder() {
        return (Comparator<T>) Comparators.NaturalOrderComparator.INSTANCE;
    }
    // 1.8新增静态方法:得到一个null亲和的比较器,null小于非null,两个null相等,如果全不是null,
    // 则使用指定的比较器比较,若未指定比较器,则非null全部相等返回0
    public static <T> Comparator<T> nullsFirst(Comparator<? super T> comparator) {
        return new Comparators.NullComparator<>(true, comparator);
    }
    // 1.8新增静态方法:得到一个null亲和的比较器,null大于非null,两个null相等,如果全不是null,
    // 则使用指定的比较器比较,若未指定比较器,则非null全部相等返回0
    public static <T> Comparator<T> nullsLast(Comparator<? super T> comparator) {
        return new Comparators.NullComparator<>(false, comparator);
    }
    // 1.8新增静态方法:使用指定的键比较器用于执行键的比较
    public static <T, U> Comparator<T> comparing(
            Function<? super T, ? extends U> keyExtractor,
            Comparator<? super U> keyComparator)
    {
        Objects.requireNonNull(keyExtractor);
        Objects.requireNonNull(keyComparator);
        return (Comparator<T> & Serializable)
            (c1, c2) -> keyComparator.compare(keyExtractor.apply(c1),
                                              keyExtractor.apply(c2));
    }
    // 1.8新增静态方法:执行键比较,采用内置比较方式,key的类必须实现Comparable
    public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
            Function<? super T, ? extends U> keyExtractor)
    {
        Objects.requireNonNull(keyExtractor);
        return (Comparator<T> & Serializable)
            (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
    }
    // 1.8新增静态方法:用于int类型键的比较
    public static <T> Comparator<T> comparingInt(ToIntFunction<? super T> keyExtractor) {
        Objects.requireNonNull(keyExtractor);
        return (Comparator<T> & Serializable)
            (c1, c2) -> Integer.compare(keyExtractor.applyAsInt(c1), keyExtractor.applyAsInt(c2));
    }
    // 1.8新增静态方法:用于long类型键的比较
    public static <T> Comparator<T> comparingLong(ToLongFunction<? super T> keyExtractor) {
        Objects.requireNonNull(keyExtractor);
        return (Comparator<T> & Serializable)
            (c1, c2) -> Long.compare(keyExtractor.applyAsLong(c1), keyExtractor.applyAsLong(c2));
    }
    // 1.8新增静态方法:用于double类型键的比较
    public static<T> Comparator<T> comparingDouble(ToDoubleFunction<? super T> keyExtractor) {
        Objects.requireNonNull(keyExtractor);
        return (Comparator<T> & Serializable)
            (c1, c2) -> Double.compare(keyExtractor.applyAsDouble(c1), keyExtractor.applyAsDouble(c2));
    }
}
Nach dem Login kopieren

Es gibt nur zwei Methoden in der alten Version von Comparator, nämlich die ersten beiden Methoden. Alle nachfolgenden Standardmethoden sind die neuen Methoden, die in 1.8 hinzugefügt wurden Schnittstelle kann Standardmethoden hinzufügen. Selbst bei so vielen Methoden ist die Schnittstelle immer noch eine funktionale Schnittstelle, und Compare wird zum Definieren der Vergleichsmethode verwendet.

4. Vergleich zwischen den beiden

Comparable kann als interner Komparator und Comparator als externer Komparator betrachtet werden.

Eine Klasse kann Ordnung schaffen, indem sie die Comparable-Schnittstelle implementiert, oder sie kann Ordnung schaffen, indem sie einen zusätzlichen Komparator angibt.

Die Funktionen der beiden sind eigentlich die gleichen, also vermischen Sie sie nicht.

Sehen wir uns ein Beispiel an:

Definieren Sie zunächst ein Modell: Benutzer

public class User implements Serializable, Comparable<User> {
    private static final long serialVersionUID = 1L;
    private int age;
    private String name;
    public User (){}
    public User (int age, String name){
        this.age = age;
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public int compareTo(User o) {
        return this.age - o.age;
    }
    @Override
    public String toString() {
        return "[user={age=" + age + ",name=" + name + "}]";
    }
}
Nach dem Login kopieren

Definieren Sie dann eine Comparator-Implementierungsklasse MyComparator

public class MyComparator implements Comparator<User> {
    @Override
    public int compare(User o1, User o2) {
        return o1.getName().charAt(0)-o2.getName().charAt(0);
    }
}
Nach dem Login kopieren

Zuletzt die Testklasse : Main

public class Main {
    public static void main(String[] args) {
        User u1 = new User(12, "xiaohua");
        User u2 = new User(10, "abc");
        User u3 = new User(15,"ccc");
        User[] users = {u1,u2,u3};
        System.out.print("数组排序前:");
        printArray(users);
        System.out.println();
        Arrays.sort(users);
        System.out.print("数组排序1后:");
        printArray(users);
        System.out.println();
        Arrays.sort(users, new MyComparator());
        System.out.print("数组排序2后:");
        printArray(users);
        System.out.println();
        Arrays.sort(users, Comparator.reverseOrder());// 针对内置的排序进行倒置
        System.out.print("数组排序3后:");
        printArray(users);
    }
    public static void printArray (User[] users) {
        for (User user:users) {
            System.out.print(user.toString());
        }
    }
}
Nach dem Login kopieren

Das laufende Ergebnis ist:

数组排序前:[user={age=12,name=xiaohua}][user={age=10,name=abc}][user={age=15,name=ccc}]
数组排序1后:[user={age=10,name=abc}][user={age=12,name=xiaohua}][user={age=15,name=ccc}]
数组排序2后:[user={age=10,name=abc}][user={age=15,name=ccc}][user={age=12,name=xiaohua}]
数组排序3后:[user={age=15,name=ccc}][user={age=12,name=xiaohua}][user={age=10,name=abc}]
Nach dem Login kopieren

Durch das obige Beispiel haben wir eine Schlussfolgerung, das heißt, es gibt zwei Möglichkeiten, die Priorität der Sortierung zu definieren, den Comparator-Komparator hat Vorrang vor der internen Sortierung Vergleichbar.

5. Zusammenfassung

Comparable ist sortierbar, und Objekte von Klassen, die diese Schnittstelle implementieren, verfügen automatisch über die sortierbare Funktion.

Comparator ist ein Komparator. Durch die Implementierung dieser Schnittstelle kann eine Sortiermethode für eine bestimmte Klasse definiert werden.

Wenn Comparator und Comparable gleichzeitig vorhanden sind, hat ersteres eine höhere Priorität.

Das obige ist der detaillierte Inhalt vonVergleichende Einführung in Comparable und Comparator in Java (Codebeispiel). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

Video Face Swap

Video Face Swap

Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Smith-Nummer in Java Smith-Nummer in Java Aug 30, 2024 pm 04:28 PM

Leitfaden zur Smith-Zahl in Java. Hier besprechen wir die Definition: Wie überprüft man die Smith-Nummer in Java? Beispiel mit Code-Implementierung.

Fragen zum Java Spring-Interview Fragen zum Java Spring-Interview Aug 30, 2024 pm 04:29 PM

In diesem Artikel haben wir die am häufigsten gestellten Fragen zu Java Spring-Interviews mit ihren detaillierten Antworten zusammengestellt. Damit Sie das Interview knacken können.

Brechen oder aus Java 8 Stream foreach zurückkehren? Brechen oder aus Java 8 Stream foreach zurückkehren? Feb 07, 2025 pm 12:09 PM

Java 8 führt die Stream -API ein und bietet eine leistungsstarke und ausdrucksstarke Möglichkeit, Datensammlungen zu verarbeiten. Eine häufige Frage bei der Verwendung von Stream lautet jedoch: Wie kann man von einem Foreach -Betrieb brechen oder zurückkehren? Herkömmliche Schleifen ermöglichen eine frühzeitige Unterbrechung oder Rückkehr, aber die Stream's foreach -Methode unterstützt diese Methode nicht direkt. In diesem Artikel werden die Gründe erläutert und alternative Methoden zur Implementierung vorzeitiger Beendigung in Strahlverarbeitungssystemen erforscht. Weitere Lektüre: Java Stream API -Verbesserungen Stream foreach verstehen Die Foreach -Methode ist ein Terminalbetrieb, der einen Vorgang für jedes Element im Stream ausführt. Seine Designabsicht ist

Zeitstempel für Datum in Java Zeitstempel für Datum in Java Aug 30, 2024 pm 04:28 PM

Anleitung zum TimeStamp to Date in Java. Hier diskutieren wir auch die Einführung und wie man Zeitstempel in Java in ein Datum konvertiert, zusammen mit Beispielen.

Java -Programm, um das Kapselvolumen zu finden Java -Programm, um das Kapselvolumen zu finden Feb 07, 2025 am 11:37 AM

Kapseln sind dreidimensionale geometrische Figuren, die aus einem Zylinder und einer Hemisphäre an beiden Enden bestehen. Das Volumen der Kapsel kann berechnet werden, indem das Volumen des Zylinders und das Volumen der Hemisphäre an beiden Enden hinzugefügt werden. In diesem Tutorial wird erörtert, wie das Volumen einer bestimmten Kapsel in Java mit verschiedenen Methoden berechnet wird. Kapselvolumenformel Die Formel für das Kapselvolumen lautet wie folgt: Kapselvolumen = zylindrisches Volumenvolumen Zwei Hemisphäre Volumen In, R: Der Radius der Hemisphäre. H: Die Höhe des Zylinders (ohne die Hemisphäre). Beispiel 1 eingeben Radius = 5 Einheiten Höhe = 10 Einheiten Ausgabe Volumen = 1570,8 Kubikeinheiten erklären Berechnen Sie das Volumen mithilfe der Formel: Volumen = π × R2 × H (4

PHP vs. Python: Verständnis der Unterschiede PHP vs. Python: Verständnis der Unterschiede Apr 11, 2025 am 12:15 AM

PHP und Python haben jeweils ihre eigenen Vorteile, und die Wahl sollte auf Projektanforderungen beruhen. 1.PHP eignet sich für die Webentwicklung mit einfacher Syntax und hoher Ausführungseffizienz. 2. Python eignet sich für Datenwissenschaft und maschinelles Lernen mit präziser Syntax und reichhaltigen Bibliotheken.

PHP: Eine Schlüsselsprache für die Webentwicklung PHP: Eine Schlüsselsprache für die Webentwicklung Apr 13, 2025 am 12:08 AM

PHP ist eine Skriptsprache, die auf der Serverseite weit verbreitet ist und insbesondere für die Webentwicklung geeignet ist. 1.PHP kann HTML einbetten, HTTP -Anforderungen und Antworten verarbeiten und eine Vielzahl von Datenbanken unterstützt. 2.PHP wird verwendet, um dynamische Webinhalte, Prozessformdaten, Zugriffsdatenbanken usw. mit starker Community -Unterstützung und Open -Source -Ressourcen zu generieren. 3. PHP ist eine interpretierte Sprache, und der Ausführungsprozess umfasst lexikalische Analyse, grammatikalische Analyse, Zusammenstellung und Ausführung. 4.PHP kann mit MySQL für erweiterte Anwendungen wie Benutzerregistrierungssysteme kombiniert werden. 5. Beim Debuggen von PHP können Sie Funktionen wie error_reporting () und var_dump () verwenden. 6. Optimieren Sie den PHP-Code, um Caching-Mechanismen zu verwenden, Datenbankabfragen zu optimieren und integrierte Funktionen zu verwenden. 7

Gestalten Sie die Zukunft: Java-Programmierung für absolute Anfänger Gestalten Sie die Zukunft: Java-Programmierung für absolute Anfänger Oct 13, 2024 pm 01:32 PM

Java ist eine beliebte Programmiersprache, die sowohl von Anfängern als auch von erfahrenen Entwicklern erlernt werden kann. Dieses Tutorial beginnt mit grundlegenden Konzepten und geht dann weiter zu fortgeschrittenen Themen. Nach der Installation des Java Development Kit können Sie das Programmieren üben, indem Sie ein einfaches „Hello, World!“-Programm erstellen. Nachdem Sie den Code verstanden haben, verwenden Sie die Eingabeaufforderung, um das Programm zu kompilieren und auszuführen. Auf der Konsole wird „Hello, World!“ ausgegeben. Mit dem Erlernen von Java beginnt Ihre Programmierreise, und wenn Sie Ihre Kenntnisse vertiefen, können Sie komplexere Anwendungen erstellen.

See all articles