web-dev-qa-db-ja.com

PriorityQueueをどうやって使うのですか?

PriorityQueue に並べ替えるにはどうすればよいですか。

また、 offeradd メソッドに違いはありますか?

348
Svish

Comparator<? super E> comparatorを取るコンストラクタオーバーロードを使用して、ソート順に適した方法で比較するコンパレータを渡します。並べ替え方法の例を挙げれば、よくわからない場合はコンパレータを実装するためのサンプルコードを提供できます。 (それはかなり簡単です。)

他のところで言われたように:offeraddはちょうど異なるインターフェースメソッド実装です。私が持っているJDKのソースでは、addofferを呼び出します。 addofferは、サイズの制限により値を追加できないことを示す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;
    }
}

これが出力です。

ショート

とても長い

423
Jon Skeet

Java 8ソリューション

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);
}

offer()とadd()

doc に従って

Offerメソッドは可能な場合は要素を挿入し、それ以外の場合はfalseを返します。これは、未チェックの例外をスローすることによってのみ要素を追加できないCollection.addメソッドとは異なります。オファーメソッドは、障害が例外的な発生ではなく通常の状態である場合、たとえば固定容量(または「制限付き」)キューで使用するように設計されています。

容量制限のあるキューを使用するときは、例外をスローすることによってのみ要素の挿入に失敗する可能性があるadd()よりもoffer()の方が一般的には望ましいです。そして PriorityQueue はプライオリティヒープに基づく無制限のプライオリティキューです。

43
i_am_zero

適切な Comparatorコンストラクタ に渡すだけです。

PriorityQueue(int initialCapacity, Comparator<? super E> comparator)

offeradd の唯一の違いは、それらが属するインタフェースです。 offerQueue<E> に属しますが、addは元々 Collection<E> インターフェースにあります。それとは別に、両方のメソッドはまったく同じことをします - 指定された要素を優先度キューに挿入します。

24
dragonfly

from キューAPI

Offerメソッドは可能な場合は要素を挿入し、それ以外の場合はfalseを返します。これは、未チェックの例外をスローすることによってのみ要素を追加できないCollection.addメソッドとは異なります。オファーメソッドは、障害が例外的な発生ではなく通常の状態である場合、たとえば固定容量(または「制限付き」)キューで使用するように設計されています。

18
Peter

javadocで宣言されているように、違いはありません。

public boolean add(E e) {
    return offer(e);
}
12
d1ck50n

add() vs offer()の質問に答えるだけです(もう1つの質問はimoと完全に答えられていますが、そうではないかもしれません)。

JavaDoc onインタフェースQueue によると、可能な場合、offerメソッドは要素を挿入し、それ以外の場合はfalseを返します。これはCollection.addメソッドとは異なり、未確認の例外をスローすることによってのみ要素を追加できません。このメソッドは、たとえば固定容量(または「制限付き」)キューで、例外が発生するのではなく、障害が正常な場合に使用するように設計されています。」

つまり、要素を追加できる場合(PriorityQueueでは常にそうであるはずです)、それらはまったく同じように機能します。しかし、要素を追加できない場合、offer()は素敵できれいなfalseの戻り値を返しますが、add()はコードに不要な厄介な未チェックの例外をスローします。追加に失敗したことがコードが意図したとおりに機能していることを意味している、またはそれが通常チェックするものである場合、offer()を使用してください。追加に失敗して何かが壊れたことを意味する場合は、add()を使用し、 Collectionインタフェースの仕様 )に従ってスローされた結果の例外を処理します。

どちらも、offer()を指定するQueueインターフェース上のfalse_(容量制限キューで推奨される方式 )を優先して、 常にadd()を指定する)コントラクトを維持するという契約を満たすために実装されています。例外 をスローして失敗します。

とにかく、それが質問の少なくともその部分を明確にすることを願っています。

5
Blueriver

ここでは、ユーザー定義のコンパレータを定義できます。

以下のコード:

 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

5
rashedcs

印刷注文についても疑問に思いました。たとえば、次のような場合を考えてください。

優先度キューの場合

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()メソッドは要素をキューに挿入するだけです。これはキューの先頭を返します。」

3
joserey

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
2
Dukeling

優先度キューには各要素に優先度が割り当てられています。優先度が最も高い要素がキューの一番上に表示されます。今、それはあなたがどのようにあなたが優先順位をどのように各要素に割り当てることを望むかにあなた次第です。そうでなければ、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
    }
}
1
devDeejay

これが初期学習に使用できる簡単な例です。

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());
        }
    }

}
1
KayV

それを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を入れ替えます。

1
James Wierzba