PriorityQueue
並べ替えたいものを並べ替えるにはどうすればよいですか?
PriorityQueue
並べ替えたいものを並べ替えるにはどうすればよいですか?
回答:
aを取り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;
}
}
出力は次のとおりです。
ショート
中
本当に長い
compare
実装は正しくありませんreturn x.length() - y.length()
か?(分岐予測を回避する)
add()
追加操作に使用している場合は、remove()
理にかなっていると思います。私が使用している場合offer()
は、おそらくpoll()
...を使用しますが、それは単なる個人的な好みです。
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メソッドは、可能であれば要素を挿入し、そうでない場合はfalseを返します。これは、チェックされていない例外をスローすることによってのみ要素の追加に失敗する可能性があるCollection.addメソッドとは異なります。offerメソッドは、たとえば、固定容量(または「制限付き」)のキューで、例外が例外的な発生ではなく通常の発生である場合に使用するように設計されています。
容量制限のあるキューを使用する場合、通常、add()よりもoffer()の方が適しています。add()は、例外をスローすることによってのみ要素の挿入に失敗する可能性があります。また、PriorityQueueは、優先ヒープに基づく無制限の優先キューです。
5
がキューの開始容量を示していると思いますか?
適切に渡すだけ Comparator
をコンストラクタに:
PriorityQueue(int initialCapacity, Comparator<? super E> comparator)
唯一の違いoffer
とはadd
、彼らが属するインターフェースです。offer
に属しますがQueue<E>
、add
もともとはCollection<E>
インターフェイスに表示されていました。それを除いて、両方のメソッドはまったく同じことを行います-指定された要素を優先度キューに挿入します。
add()
vsのoffer()
質問に答えるだけです(もう1つは完全にimoと答えられるため、これは当てはまらない可能性があります):
インターフェースQueueのJavaDocによると、「offerメソッドは可能であれば要素を挿入し、そうでない場合はfalseを返します。これは、チェックされていない例外をスローすることによってのみ要素の追加に失敗する可能性があるCollection.addメソッドとは異なります。offerメソッドは、障害が例外的な発生ではなく通常の発生である場合に使用します。たとえば、固定容量(または「制限付き」)キューで発生します。」
つまり、要素を追加できる場合(これは常にPriorityQueueの場合に該当します)、まったく同じように機能します。しかし、要素を追加できない場合は、コードに必要ない厄介な未チェックの例外をスローする一方でoffer()
、見栄えがよくきれいなfalse
戻りを提供add()
します。追加に失敗した場合、コードが意図したとおりに機能しているか、通常チェックするコードである場合は、を使用しますoffer()
。追加の失敗が何かが壊れていることを意味する場合、Collectionインターフェースの仕様add()
に従ってスローされた結果の例外を使用して処理します。
これらは両方とも、このように実装さoffer()
れて、false
(容量制限されたキューで推奨されるメソッド)を返すことによって失敗を指定するQueueインターフェイスでコントラクトをフルフィルし、例外をスローすることで常に失敗を指定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
オファーと追加メソッドの違い:リンク
それを渡し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を入れ替えます。
プリント注文についても気になっていた。たとえば、次の場合を考えます。
優先キューの場合:
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を使用する必要があります。キューの。」
を使用する代わりComparator
に、PriorityQueue
実装でComparable
使用しているクラスを持つこともできます(それに応じてcompareTo
メソッドをオーバーライドします)。
一般Comparable
にComparator
、その順序がオブジェクトの直感的な順序である場合にのみ使用するのが最善であることに注意してください。たとえば、Person
年齢でオブジェクトをソートするユースケースがある場合は、Comparator
代わりに使用するのがおそらく最善です。
import java.lang.Comparable;
import java.util.PriorityQueue;
class Test
{
public static void main(String[] args)
{
PriorityQueue<MyClass> queue = new PriorityQueue<MyClass>();
queue.add(new MyClass(2, "short"));
queue.add(new MyClass(2, "very long indeed"));
queue.add(new MyClass(1, "medium"));
queue.add(new MyClass(1, "very long indeed"));
queue.add(new MyClass(2, "medium"));
queue.add(new MyClass(1, "short"));
while (queue.size() != 0)
System.out.println(queue.remove());
}
}
class MyClass implements Comparable<MyClass>
{
int sortFirst;
String sortByLength;
public MyClass(int sortFirst, String sortByLength)
{
this.sortFirst = sortFirst;
this.sortByLength = sortByLength;
}
@Override
public int compareTo(MyClass other)
{
if (sortFirst != other.sortFirst)
return Integer.compare(sortFirst, other.sortFirst);
else
return Integer.compare(sortByLength.length(), other.sortByLength.length());
}
public String toString()
{
return sortFirst + ", " + sortByLength;
}
}
出力:
1, short
1, medium
1, very long indeed
2, short
2, medium
2, very long indeed
優先度キューには、各要素にいくつかの優先度が割り当てられています。優先度が最も高い要素がキューの先頭に表示されます。ここで、各要素に優先度をどのように割り当てたいかによって異なります。そうしない場合、Javaはデフォルトの方法でそれを行います。最小値の要素には最高の優先順位が割り当てられるため、最初にキューから削除されます。同じ優先度の要素が複数ある場合、結合は任意に解除されます。コンストラクタでコンパレータを使用して順序を指定することもできます PriorityQueue(initialCapacity, comparator)
コード例:
PriorityQueue<String> queue1 = new PriorityQueue<>();
queue1.offer("Oklahoma");
queue1.offer("Indiana");
queue1.offer("Georgia");
queue1.offer("Texas");
System.out.println("Priority queue using Comparable:");
while (queue1.size() > 0) {
System.out.print(queue1.remove() + " ");
}
PriorityQueue<String> queue2 = new PriorityQueue(4, Collections.reverseOrder());
queue2.offer("Oklahoma");
queue2.offer("Indiana");
queue2.offer("Georgia");
queue2.offer("Texas");
System.out.println("\nPriority queue using Comparator:");
while (queue2.size() > 0) {
System.out.print(queue2.remove() + " ");
}
出力:
Priority queue using Comparable:
Georgia Indiana Oklahoma Texas
Priority queue using Comparator:
Texas Oklahoma Indiana Georgia
または、カスタムコンパレータを定義することもできます。
import java.util.Comparator;
public class StringLengthComparator implements Comparator<String>
{
@Override
public int compare(String x, String y)
{
//Your Own Logic
}
}
以下は、初期学習に使用できる簡単な例です。
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Random;
public class PQExample {
public static void main(String[] args) {
//PriorityQueue with Comparator
Queue<Customer> cpq = new PriorityQueue<>(7, idComp);
addToQueue(cpq);
pollFromQueue(cpq);
}
public static Comparator<Customer> idComp = new Comparator<Customer>(){
@Override
public int compare(Customer o1, Customer o2) {
return (int) (o1.getId() - o2.getId());
}
};
//utility method to add random data to Queue
private static void addToQueue(Queue<Customer> cq){
Random rand = new Random();
for(int i=0;i<7;i++){
int id = rand.nextInt(100);
cq.add(new Customer(id, "KV"+id));
}
}
private static void pollFromQueue(Queue<Customer> cq){
while(true){
Customer c = cq.poll();
if(c == null) break;
System.out.println("Customer Polled : "+c.getId() + " "+ c.getName());
}
}
}