この記事では、Java の Comparable と Comparator についての比較紹介 (コード例) を紹介します。必要な方は参考にしてください。
1. 概要
Java での並べ替えは、Comparable と Comparator の 2 つのインターフェイスによって提供されます。
Comparable とはソートできることを意味し、このインターフェースを実装したクラスのオブジェクトは自動的にソート機能を持ちます。
Comparator はコンパレータを表します。このインターフェイスを実装するクラスのオブジェクトは、ターゲット クラスのオブジェクトに対して定義されたコンパレータです。通常、このコンパレータはパラメータとして渡されます。
2. Comparable
Comparable の中国語の意味は「並べ替えられる」、つまり並べ替え機能をサポートしていることを意味します。私たちのクラスがこのインターフェイスを実装している限り、このクラスのオブジェクトは自動的に並べ替えられるようになります。そして、この順序はクラスの自然順序と呼ばれます。このクラスのオブジェクトのリストは、Collections.sort および Arrays.sort によって並べ替えることができます。同時に、このクラスのインスタンスは、ソートされたマップのキーおよびソートされたセットの要素として修飾されます。
a と b が両方とも Comparable インターフェイスを実装するクラス C のインスタンスである場合、a.compareTo(b) の結果が a.equals(b) の結果と一致する場合にのみ呼び出されます。クラス C。自然順序は等しいと一致します。クラスの自然な順序と、equals の結果の一貫性を保つことを強くお勧めします。一貫性がない場合、このクラスのオブジェクトをキーとして持つソートされたマップと、このクラスのオブジェクトを要素として持つソートされたセットの動作が不安定になるためです。奇妙に振る舞う。
たとえば、Comparable インターフェイスを実装するソート セットの場合、a.equals(b) の結果が false で、a.compareTo(b)==0 の場合、2 番目の要素の追加操作が実行されます。ソートセットの観点からは、この 2 つはソートにおいて一貫しており、重複した要素は保存されないため、失敗します。
実際、Java のクラスの自然な順序は、BigDecimal を除いて基本的に等しいと一致します。これは、BigDecimal の自然な順序は、値は同じだが精度が異なる要素 (4 など) の等しいと一致するためです。および 4.00) 。
ソース コード分析
public interface Comparable<T> { public int compareTo(T o); }
ソース コードから、インターフェイスには、compareTo という抽象メソッドが 1 つだけあることがわかります。このメソッドは、主にクラスの並べ替え方法を定義するためのものです。 CompareTo メソッドは、現在の要素 a と指定された要素 b を比較するために使用されます。 int
3. Comparator
Comparator は中国語ではコンパレータとして翻訳され、特定の内容を指定するために Collections.sort メソッドと Arrays.sort メソッドに渡すことができます。クラスオブジェクトで並べ替えます。同時に、ソートセットおよびソートマップのソート方法も指定できます。
Comparable と同様に、コンパレータを指定する場合、通常、比較結果が等しい結果と一致していることを確認する必要があります。一致しない場合、対応するソート セットおよびソート マップの動作も変わります。奇妙な。
シリアル化されたデータ構造 (TreeSet、TreeMap) の並べ替えメソッドとして使用される可能性があるため、実装されたコンパレーター クラスには、シリアル化機能を持たせるために java.io.Serializable インターフェイスも実装することをお勧めします。
ソース コード分析
@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)); } }
Comparator の古いバージョンには 2 つのメソッドしかなく、最初の 2 つのメソッドはすべて 1.8 で追加された新しいメソッドであり、新しいメソッドを使用します。 1.8 で追加されました。 機能: インターフェイスにデフォルトのメソッドを追加できます。メソッドが非常に多くても、インターフェイスは依然として機能インターフェイスであり、比較メソッドを定義するために Compare が使用されます。
4. 2 つの比較
Comparable は内部コンパレータ、Comparator は外部コンパレータとみなすことができます。
Comparable インターフェイスを実装することによってクラスに順序性を持たせることも、追加の Comparator を指定することによって順序性を追加することもできます。
この 2 つの機能は実際には同じなので、混同しないでください。
例を見てみましょう:
最初にモデルを定義します: User
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 + "}]"; } }
次に、Comparator 実装クラス MyComparator
public class MyComparator implements Comparator<User> { @Override public int compare(User o1, User o2) { return o1.getName().charAt(0)-o2.getName().charAt(0); } }
を定義します。最後に、テスト クラス: 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()); } } }
実行結果は次のとおりです:
数组排序前:[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}]
上記の例から、ソートの優先順位を定義するには 2 つの方法があるという結論が得られます。明らかに、Comparator コンパレーターです。内部ソート Comparable よりも優先されます。
5. 概要
Comparable はソート可能であり、このインターフェイスを実装するクラスのオブジェクトは自動的にソート可能機能を持ちます。
Comparator はコンパレータであり、このインターフェイスを実装すると、特定のクラスの並べ替えメソッドを定義できます。
Comparator と Comparable が同時に存在する場合、前者が優先されます。
以上がJava での Comparable と Comparator の比較入門 (コード例)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

javaispopularforsoss-platformdesktopapplicationsduetoits "writeonce、runaynay" philosophy.1)itusesbytecodatiTatrunnanyjvm-adipplatform.2)ライブラリリケンディンガンドジャヴァフククレアティック - ルルクリス

Javaでプラットフォーム固有のコードを作成する理由には、特定のオペレーティングシステム機能へのアクセス、特定のハードウェアとの対話、パフォーマンスの最適化が含まれます。 1)JNAまたはJNIを使用して、Windowsレジストリにアクセスします。 2)JNIを介してLinux固有のハードウェアドライバーと対話します。 3)金属を使用して、JNIを介してMacOSのゲームパフォーマンスを最適化します。それにもかかわらず、プラットフォーム固有のコードを書くことは、コードの移植性に影響を与え、複雑さを高め、パフォーマンスのオーバーヘッドとセキュリティのリスクをもたらす可能性があります。

Javaは、クラウドネイティブアプリケーション、マルチプラットフォームの展開、および言語間の相互運用性を通じて、プラットフォームの独立性をさらに強化します。 1)クラウドネイティブアプリケーションは、GraalvmとQuarkusを使用してスタートアップ速度を向上させます。 2)Javaは、埋め込みデバイス、モバイルデバイス、量子コンピューターに拡張されます。 3)Graalvmを通じて、JavaはPythonやJavaScriptなどの言語とシームレスに統合して、言語間の相互運用性を高めます。

Javaの強力なタイプ化されたシステムは、タイプの安全性、統一タイプの変換、多型を通じてプラットフォームの独立性を保証します。 1)タイプの安全性は、コンパイル時間でタイプチェックを実行して、ランタイムエラーを回避します。 2)統一された型変換ルールは、すべてのプラットフォームで一貫しています。 3)多型とインターフェイスメカニズムにより、コードはさまざまなプラットフォームで一貫して動作します。

JNIはJavaのプラットフォームの独立を破壊します。 1)JNIは特定のプラットフォームにローカルライブラリを必要とします。2)ローカルコードをターゲットプラットフォームにコンパイルおよびリンクする必要があります。3)異なるバージョンのオペレーティングシステムまたはJVMは、異なるローカルライブラリバージョンを必要とする場合があります。

新しいテクノロジーは、両方の脅威をもたらし、Javaのプラットフォームの独立性を高めます。 1)Dockerなどのクラウドコンピューティングとコンテナ化テクノロジーは、Javaのプラットフォームの独立性を強化しますが、さまざまなクラウド環境に適応するために最適化する必要があります。 2)WebAssemblyは、Graalvmを介してJavaコードをコンパイルし、プラットフォームの独立性を拡張しますが、パフォーマンスのために他の言語と競合する必要があります。

JVMの実装が異なると、プラットフォームの独立性が得られますが、パフォーマンスはわずかに異なります。 1。OracleHotspotとOpenJDKJVMは、プラットフォームの独立性で同様に機能しますが、OpenJDKは追加の構成が必要になる場合があります。 2。IBMJ9JVMは、特定のオペレーティングシステムで最適化を実行します。 3. Graalvmは複数の言語をサポートし、追加の構成が必要です。 4。AzulzingJVMには、特定のプラットフォーム調整が必要です。

プラットフォームの独立性により、開発コストが削減され、複数のオペレーティングシステムで同じコードセットを実行することで開発時間を短縮します。具体的には、次のように表示されます。1。開発時間を短縮すると、1セットのコードのみが必要です。 2。メンテナンスコストを削減し、テストプロセスを統合します。 3.展開プロセスを簡素化するための迅速な反復とチームコラボレーション。


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

ZendStudio 13.5.1 Mac
強力な PHP 統合開発環境

SublimeText3 英語版
推奨: Win バージョン、コードプロンプトをサポート!

メモ帳++7.3.1
使いやすく無料のコードエディター

SAP NetWeaver Server Adapter for Eclipse
Eclipse を SAP NetWeaver アプリケーション サーバーと統合します。

WebStorm Mac版
便利なJavaScript開発ツール

ホットトピック









