PriorityQueue
に並べ替えるにはどうすればよいですか。
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で導入されたlambda expression
またはmethod reference
を使用することができます。優先度キューに格納されている文字列値(容量5)がある場合は、(Stringの長さに基づいて)インラインコンパレータを提供できます。
ラムダ式を使用する
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);
}
doc に従って
Offerメソッドは可能な場合は要素を挿入し、それ以外の場合はfalseを返します。これは、未チェックの例外をスローすることによってのみ要素を追加できないCollection.addメソッドとは異なります。オファーメソッドは、障害が例外的な発生ではなく通常の状態である場合、たとえば固定容量(または「制限付き」)キューで使用するように設計されています。
容量制限のあるキューを使用するときは、例外をスローすることによってのみ要素の挿入に失敗する可能性があるadd()よりもoffer()の方が一般的には望ましいです。そして PriorityQueue はプライオリティヒープに基づく無制限のプライオリティキューです。
適切な Comparator
を コンストラクタ に渡すだけです。
PriorityQueue(int initialCapacity, Comparator<? super E> comparator)
offer
と add
の唯一の違いは、それらが属するインタフェースです。 offer
は Queue<E>
に属しますが、add
は元々 Collection<E>
インターフェースにあります。それとは別に、両方のメソッドはまったく同じことをします - 指定された要素を優先度キューに挿入します。
from キューAPI :
Offerメソッドは可能な場合は要素を挿入し、それ以外の場合はfalseを返します。これは、未チェックの例外をスローすることによってのみ要素を追加できないCollection.addメソッドとは異なります。オファーメソッドは、障害が例外的な発生ではなく通常の状態である場合、たとえば固定容量(または「制限付き」)キューで使用するように設計されています。
javadocで宣言されているように、違いはありません。
public boolean add(E e) {
return offer(e);
}
add()
vs offer()
の質問に答えるだけです(もう1つの質問はimoと完全に答えられていますが、そうではないかもしれません)。
JavaDoc onインタフェースQueue によると、可能な場合、offerメソッドは要素を挿入し、それ以外の場合はfalseを返します。これはCollection.addメソッドとは異なり、未確認の例外をスローすることによってのみ要素を追加できません。このメソッドは、たとえば固定容量(または「制限付き」)キューで、例外が発生するのではなく、障害が正常な場合に使用するように設計されています。」
つまり、要素を追加できる場合(PriorityQueueでは常にそうであるはずです)、それらはまったく同じように機能します。しかし、要素を追加できない場合、offer()
は素敵できれいなfalse
の戻り値を返しますが、add()
はコードに不要な厄介な未チェックの例外をスローします。追加に失敗したことがコードが意図したとおりに機能していることを意味している、またはそれが通常チェックするものである場合、offer()
を使用してください。追加に失敗して何かが壊れたことを意味する場合は、add()
を使用し、 Collectionインタフェースの仕様 )に従ってスローされた結果の例外を処理します。
どちらも、offer()
を指定するQueueインターフェース上のfalse
_(容量制限キューで推奨される方式 )を優先して、 常にadd()
を指定する)コントラクトを維持するという契約を満たすために実装されています。例外 をスローして失敗します。
とにかく、それが質問の少なくともその部分を明確にすることを願っています。
ここでは、ユーザー定義のコンパレータを定義できます。
以下のコード:
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メソッドの違い: link
印刷注文についても疑問に思いました。たとえば、次のような場合を考えてください。
優先度キューの場合
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()メソッドは要素をキューに挿入するだけです。これはキューの先頭を返します。」
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がデフォルトの方法でそれを行います。最小の値を持つ要素に最も高い優先順位が割り当てられているため、最初にキューから削除されます。同じ最高優先順位を持つ要素が複数ある場合、同点は任意に破られます。コンストラクタでComparatorを使用して順序を指定することもできます 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());
}
}
}
それを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を入れ替えます。