PriorityQueue
並べ替えたいものを並べ替えるにはどうすればよいですか?
12 に答える
コンストラクターのオーバーロードを使用してComparator<? super E> comparator
、並べ替え順序に適した方法で比較するコンパレーターを渡します。並べ替え方法の例を挙げれば、よくわからない場合はコンパレータを実装するためのサンプル コードを提供できます。(かなり単純ですが。)
他の場所で述べたように:offer
とadd
は単に異なるインターフェイス メソッドの実装です。私が持っているJDKソースではadd
、offer
. サイズ制限のために値を追加できないことを が示すことができるため、 と は一般的に異なる動作をする可能性がありますが、この違いは、 が無制限でadd
あるoffer
ことには関係ありません。offer
PriorityQueue
文字列の長さでソートする優先度キューの例を次に示します。
// Test.java
import java.util.Comparator;
import java.util.PriorityQueue;
public class Test {
public static void main(String[] args) {
Comparator<String> comparator = new StringLengthComparator();
PriorityQueue<String> queue = new PriorityQueue<String>(10, comparator);
queue.add("short");
queue.add("very long indeed");
queue.add("medium");
while (queue.size() != 0) {
System.out.println(queue.remove());
}
}
}
// StringLengthComparator.java
import java.util.Comparator;
public class StringLengthComparator implements Comparator<String> {
@Override
public int compare(String x, String y) {
// Assume neither string is null. Real code should
// probably be more robust
// You could also just return x.length() - y.length(),
// which would be more efficient.
if (x.length() < y.length()) {
return -1;
}
if (x.length() > y.length()) {
return 1;
}
return 0;
}
}
出力は次のとおりです。
短い
中くらい
非常に長い
Java 8 ソリューション
Java 8 で使用lambda expression
またはmethod reference
導入できます。プライオリティ キュー (容量 5) にいくつかの文字列値が格納されている場合、インライン コンパレータ (文字列の長さに基づく) を提供できます。
ラムダ式の使用
PriorityQueue<String> pq=
new PriorityQueue<String>(5,(a,b) -> a.length() - b.length());
メソッド参照の使用
PriorityQueue<String> pq=
new PriorityQueue<String>(5, Comparator.comparing(String::length));
次に、それらのいずれかを次のように使用できます。
public static void main(String[] args) {
PriorityQueue<String> pq=
new PriorityQueue<String>(5, (a,b) -> a.length() - b.length());
// or pq = new PriorityQueue<String>(5, Comparator.comparing(String::length));
pq.add("Apple");
pq.add("PineApple");
pq.add("Custard Apple");
while (pq.size() != 0)
{
System.out.println(pq.remove());
}
}
これは印刷されます:
Apple
PineApple
Custard Apple
順序を逆にする (最大優先度キューに変更する) には、単にインライン コンパレータで順序を変更するか、次のように使用reversed
します。
PriorityQueue<String> pq = new PriorityQueue<String>(5,
Comparator.comparing(String::length).reversed());
も使用できますCollections.reverseOrder
:
PriorityQueue<Integer> pqInt = new PriorityQueue<>(10, Collections.reverseOrder());
PriorityQueue<String> pq = new PriorityQueue<String>(5,
Collections.reverseOrder(Comparator.comparing(String::length))
Collections.reverseOrder
そのため、カスタム オブジェクトに役立つコンパレータを取得するためにオーバーロードされていることがわかります。はreversed
実際に使用しますCollections.reverseOrder
:
default Comparator<T> reversed() {
return Collections.reverseOrder(this);
}
offer() と add()
ドキュメントによると
offer メソッドは、可能な場合は要素を挿入し、そうでない場合は false を返します。これは、未チェックの例外をスローすることによってのみ要素の追加に失敗する可能性がある Collection.add メソッドとは異なります。offer メソッドは、障害が例外的な発生ではなく通常の場合に使用するように設計されています。たとえば、固定容量 (または「制限付き」) のキューなどです。
容量が制限されたキューを使用する場合、一般に、offer() は add() よりも推奨されます。add() は、例外をスローすることによってのみ要素の挿入に失敗する可能性があります。また、PriorityQueueは、優先度ヒープに基づく無制限の優先度キューです。
コンストラクターComparator
に適切に渡すだけです:
PriorityQueue(int initialCapacity, Comparator<? super E> comparator)
との唯一の違いはoffer
、add
それらが属するインターフェースです。offer
に属しますがQueue<E>
、add
元々はCollection<E>
インターフェイスで見られます。それを除けば、どちらの方法もまったく同じことを行います。指定された要素を優先キューに挿入します。
キュー APIから:
offer メソッドは、可能な場合は要素を挿入し、そうでない場合は false を返します。これは、未チェックの例外をスローすることによってのみ要素の追加に失敗する可能性がある Collection.add メソッドとは異なります。offer メソッドは、障害が例外的な発生ではなく通常の場合に使用するように設計されています。たとえば、固定容量 (または「制限付き」) のキューなどです。
javadoc で宣言されているように、違いはありません。
public boolean add(E e) {
return offer(e);
}
を渡しますComparator
。の代わりに希望のタイプを記入してくださいT
ラムダの使用 (Java 8+):
int initialCapacity = 10;
PriorityQueue<T> pq = new PriorityQueue<>(initialCapacity, (e1, e2) -> { return e1.compareTo(e2); });
匿名クラスを使用した古典的な方法:
int initialCapacity = 10;
PriorityQueue<T> pq = new PriorityQueue<>(initialCapacity, new Comparator<T> () {
@Override
public int compare(T e1, T e2) {
return e1.compareTo(e2);
}
});
逆順にソートするには、単純に e1、e2 を入れ替えます。
add()
vsの質問に答えるだけoffer()
です(もう1つは完全に答えられているので、これはそうではないかもしれません):
インターフェイス Queue に関する JavaDoc によると、「offer メソッドは、可能な場合は要素を挿入し、そうでない場合は false を返します。これは、チェックされていない例外をスローすることによってのみ要素の追加に失敗する可能性がある Collection.add メソッドとは異なります。 offer メソッドは、次の目的で設計されています。障害が例外的な発生ではなく、通常の場合に使用します。たとえば、固定容量 (または「制限付き」) のキューなどです。
つまり、要素を追加できる場合 (PriorityQueue では常にそうである必要があります)、それらはまったく同じように機能します。しかし、要素を追加できない場合はoffer()
、素敵できれいなfalse
戻り値が返さadd()
れますが、コードに不要な厄介なチェックされていない例外がスローされます。追加に失敗しても、コードが意図したとおりに機能している、および/または通常どおりチェックするものである場合は、 を使用しますoffer()
。追加に失敗したために何かが壊れていることを意味する場合は、Collection インターフェイスの仕様add()
に従ってスローされた結果の例外を使用および処理します。
どちらもこの方法で実装され、offer()
を返すことによって失敗を指定する Queue インターフェースのコントラクトを満たしfalse
(容量制限のあるキューで推奨されるメソッド) 、例外をスローすることによって常に失敗することを指定add()
する Collection インターフェースのコントラクトを維持します。
とにかく、少なくとも質問のその部分が明確になることを願っています。
ここで、ユーザー定義のコンパレーターを定義できます。
以下のコード:
import java.util.*;
import java.util.Collections;
import java.util.Comparator;
class Checker implements Comparator<String>
{
public int compare(String str1, String str2)
{
if (str1.length() < str2.length()) return -1;
else return 1;
}
}
class Main
{
public static void main(String args[])
{
PriorityQueue<String> queue=new PriorityQueue<String>(5, new Checker());
queue.add("india");
queue.add("bangladesh");
queue.add("pakistan");
while (queue.size() != 0)
{
System.out.printf("%s\n",queue.remove());
}
}
}
出力:
india pakistan bangladesh
offer メソッドと add メソッドの違い:リンク
印刷物の注文についても疑問に思いました。この場合を考えてみましょう。たとえば、次のようになります。
優先キューの場合:
PriorityQueue<String> pq3 = new PriorityQueue<String>();
このコード:
pq3.offer("a");
pq3.offer("A");
印刷方法が異なる場合があります:
String[] sa = {"a", "A"};
for(String s : sa)
pq3.offer(s);
別のフォーラムでのディスカッションから答えを見つけました。ユーザーは「offer()/ add()メソッドは要素をキューに挿入するだけです。予測可能な順序が必要な場合は、先頭を返すpeek/pollを使用する必要があります。キューの。」