HashSetをソートする方法は?


106

リストにはCollections.sort(List)メソッドを使用します。ソートしたい場合HashSetますか?


20
A HashSetは順不同のコレクションです。
Alexis C.

2
aにSetはランダムアクセスメソッド(つまり、.get()特定のインデックスの要素)がないため、これはできません。これは、基本的にソートアルゴリズムに必要です;)
fge

3
並べ替える必要がある場合は、最初にリストに変換してから並べ替えることができます
demongolem

HashSetは定義された順序がないため、できません。あなたの質問は矛盾を体現しています。
ローン侯爵

1
TreeSetのを使用して、ソースを制御できない場合は、ここでの変換に使用方法を参照してください stackoverflow.com/a/52987487/5153955
Tenflex

回答:


114

HashSetはその要素の順序を保証しません。この保証が必要な場合は、TreeSetを使用して要素を保持することを検討してください。

ただし、この1つの発生に対して要素を並べ替えるだけの場合は、一時的にリストを作成してそれを並べ替えます。

Set<?> yourHashSet = new HashSet<>();

...

List<?> sortedList = new ArrayList<>(yourHashSet);
Collections.sort(sortedList);

1
また、文字List<String> sortedList = new ArrayList<String>(yourHashSet);
列の

65

すべてのオブジェクトをに追加TreeSetすると、並べ替えられたセットが得られます。以下は生の例です。

HashSet myHashSet = new HashSet();
myHashSet.add(1);
myHashSet.add(23);
myHashSet.add(45);
myHashSet.add(12);

TreeSet myTreeSet = new TreeSet();
myTreeSet.addAll(myHashSet);
System.out.println(myTreeSet); // Prints [1, 12, 23, 45]

2
を使用TreeSet myTreeSet = new TreeSet(myHashSet);すると、すべての要素をTreesetに再度追加する必要がなくなります。
Mounika

17

代わりにTreeSetを使用できます。


1
要素を配置するだけでは、その中にある要素を使用して任意の順序で柔軟に並べ替えることはできません。上記の解決策はありません。
ジェス

15

それをソートするJava 8の方法は次のようになります:

fooHashSet.stream()
  .sorted(Comparator.comparing(Foo::getSize)) //comparator - how you want to sort it
  .collect(Collectors.toList()); //collector - what you want to collect it to

*Foo::getSizeこれは、YourItemのHashSetをサイズで自然にソートする方法の例です。

* Collectors.toList()ソートの結果をリストに収集します。リストをキャプチャする必要があります。List<Foo> sortedListOfFoo =


特定の順序で並べ替えるロジックを追加してください。
ジェス

@ジェス私はあなたのジェスの具体的な順序が何であるかわからない、あなたはコンパレータを使用してあなたが望むようにそれをソートすることができます。
LazerBanana

つまり、昇順または降順を定義する方法
Jess

14

java.util.TreeSet実際のオブジェクトとして使用します。このコレクションを反復処理すると、値は明確に定義された順序で返されます。

使用するjava.util.HashSet場合、順序は内部ハッシュ関数に依存しますが、これはほぼ確実に辞書式ではありません(コンテンツに基づく)。


なぜString値を格納すると想定しているのですか?
Sotirios Delimanolis 2014年

多分私のレキソグラフィックの使用は不正確ですが、私はそうではありません;-)
P45差し迫った

3
それは非常に間違っています。キーを辞書式(sp?)の順序で格納しません。自然な順序付け(Comparableキーが実装するインターフェースに依存)を使用するか、提供されComparatorたを使用します。
Sotirios Delimanolis 2014年

編集しました。良いと思いますか、それとも答えを削除しますか?
P45 2014年

1
ケースでは、移動HashSetしてTreeSet、あなたのクラスが実装しなければならないComparableインタフェースをするか、カスタムを提供しますComparator。そうでない場合は、aをソートできないためHashSet、a に変換してソートするだけListです。
Luiggi Mendoza

5

Java 8コレクターとTreeSetを使用できます

list.stream().collect(Collectors.toCollection(TreeSet::new))


new TreeSet<>(hashSet)より簡潔で、おそらくより効率的です。
devconsole

4

他の回答で述べたように、TreeSetを使用できます。

これを使用する方法についてもう少し詳しく説明します。

TreeSet<String> ts = new TreeSet<String>();
ts.add("b1");
ts.add("b3");
ts.add("b2");
ts.add("a1");
ts.add("a2");
System.out.println(ts);
for (String s: ts)
    System.out.println(s);

出力:

[a1, a2, a3, a4, a5]
a1
a2
b1
b2
b3

4

HashSetの要素はソートできません。要素をHashSetに入れると、セット全体の順序が混乱する可能性があります。それはパフォーマンスのためにそのように意図的に設計されています。順序を気にしない場合、HashSetは高速挿入と検索のための最も効率的なセットになります。

TreeSetは、要素を挿入するたびにすべての要素を自動的にソートします。

たぶん、あなたがしようとしていることは、一度だけソートすることです。その場合、TreeSetは、新しく追加された要素の配置を常に決定する必要があるため、最適なオプションではありません。

最も効率的な解決策は、ArrayListを使用することです。新しいリストを作成してすべての要素を追加し、それを1回ソートします。一意の要素のみを保持したい場合(setのようにすべての重複を削除してから、リストをLinkedHashSetに入れると、既にソートした順序が保持されます)

List<Integer> list = new ArrayList<>();
list.add(6);
list.add(4);
list.add(4);
list.add(5);
Collections.sort(list);
Set<Integer> unique = new LinkedHashSet<>(list); // 4 5 6
// The above line is not copying the objects! It only copies references.

これで、リスト形式にしたい場合はソートされたセットを取得し、それをリストに変換します。


3

@LazerBananaの回答に基づいて、オブジェクトのIDでソートされたセットの独自の例を示します。

Set<Clazz> yourSet = [...];

yourSet.stream().sorted(new Comparator<Clazz>() {
    @Override
    public int compare(Clazz o1, Clazz o2) {
        return o1.getId().compareTo(o2.getId());
    }
}).collect(Collectors.toList()); // Returns the sorted List (using toSet() wont work)

3

使用したくない場合に備えて、TreeSetこれを試すことができます。

set = set.stream().sorted().collect(Collectors.toCollection(LinkedHashSet::new));

2

私の控えめな意見では、LazerBananaの回答は最高評価の回答であり、受け入れられるはずです。これは、他のすべての回答java.util.TreeSet(または最初にリストに変換してからCollections.sort(...)、変換されたリストを呼び出す)が、自分のHashSet持っているオブジェクトの種類としてOPに質問する必要がなかったためです。これらの要素に事前定義された自然順序付けがある場合はオプションの質問ではなく必須の質問です。

あなたはちょうど入ることができず、要素タイプをまだ実装していない場合や、明示的に渡していない場合にHashSet要素を入れ始めることができますTreeSetComparableComparatorTreeSetコンストラクター。

TreeSetJavaDoc から、

要素の自然順序付けに従ってソートされた、新しい空のツリーセットを作成します。セットに挿入されるすべての要素は、Comparableインターフェースを実装する必要があります。さらに、そのような要素はすべて相互に比較可能である必要があります。e1.compareTo(e2)は、セット内の要素e1およびe2に対してClassCastExceptionをスローしてはなりません。ユーザーがこの制約に違反する要素をセットに追加しようとした場合(たとえば、ユーザーが要素が整数であるセットに文字列要素を追加しようとした場合)、add呼び出しはClassCastExceptionをスローします。

そのため、すべてのJava8ストリームベースの回答(その場でコンパレータを定義する場所)だけが意味をなすのは、POJOでのCOMPAMABLEの実装がオプションになるためです。プログラマはコンパレータを必要に応じて定義します。TreeSetこの基本的な質問をせずに集まろうとするのも正しくありません(忍者の答え)。オブジェクトタイプをStringまたはInteger正しい間違っ。

そうは言っても、のような他の懸念は、

  1. 選別性能
  2. メモリフットプリント(元のセットを保持し、並べ替えが行われるたびに、またはセットをインプレースで並べ替えるたびに、新しい並べ替えセットを作成するなど)

他の関連するポイントになるはずです。APIを指すだけでは、意図はありません。

元のセットには既に一意の要素しか含まれておらず、その制約もソートされたセットによって維持されるため、データが複製されるため、元のセットをメモリからクリアする必要があります。


1
1. Add all set element in list -> al.addAll(s);
2. Sort all the elements in list using -> Collections.sort(al);


 public class SortSetProblem {
 public static void main(String[] args) {
    ArrayList<String> al = new ArrayList();
    Set<String> s = new HashSet<>();
    s.add("ved");
    s.add("prakash");
    s.add("sharma");
    s.add("apple");
    s.add("ved");
    s.add("banana");
    System.out.println("Before Sorting");
    for (String s1 : s) {
        System.out.print("  " + s1);
    }

    System.out.println("After Sorting");
    al.addAll(s);
    Collections.sort(al);
    for (String set : al) {
        System.out.print(" " + set);
    }
  }
 }

入力-ved prakash sharmaアップルvedバナナ

出力-アップルバナナプラカシュシャルマヴェド


1

あなたが希望する場合、エンドはCollectionの形であることをSet、あなたはあなた自身を定義する場合natural orderのものではなくTreeSet、その後-

1.変換HashSetList
ソート2.カスタムList使っComparator
3.変換背面ListLinkedHashSet順番に維持する
4.表示LinkedHashSet

サンプルプログラム-

package demo31;

import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

public class App26 {
    public static void main(String[] args) {
        Set<String> set = new HashSet<>();
        addElements(set);
        List<String> list = new LinkedList<>();
        list = convertToList(set);
        Collections.sort(list, new Comparator<String>() {
            @Override
            public int compare(String s1, String s2) {
                int flag = s2.length() - s1.length();
                if(flag != 0) {
                    return flag;
                } else {
                    return -s1.compareTo(s2);
                }
            }
        });
        Set<String> set2 = new LinkedHashSet<>();
        set2 = convertToSet(list);
        displayElements(set2);
    }
    public static void addElements(Set<String> set) {
        set.add("Hippopotamus");
        set.add("Rhinocerous");
        set.add("Zebra");
        set.add("Tiger");
        set.add("Giraffe");
        set.add("Cheetah");
        set.add("Wolf");
        set.add("Fox");
        set.add("Dog");
        set.add("Cat");
    }
    public static List<String> convertToList(Set<String> set) {
        List<String> list = new LinkedList<>();
        for(String element: set) {
            list.add(element);
        }
        return list;
    }
    public static Set<String> convertToSet(List<String> list) {
        Set<String> set = new LinkedHashSet<>();
        for(String element: list) {
            set.add(element);
        }
        return set;
    }
    public static void displayElements(Set<String> set) {
        System.out.println(set);
    }
}

出力-

[Hippopotamus, Rhinocerous, Giraffe, Cheetah, Zebra, Tiger, Wolf, Fox, Dog, Cat]

ここでは、コレクションは次のようにソートされています-

最初- String長さの
降順2番目- Stringアルファベット順の降順


0

次の方法でこれを行うことができます。

方法1:

  1. リストを作成し、すべてのハッシュセット値をリストに保存します
  2. Collections.sort()を使用してリストをソートします
  3. 挿入順序を保持するため、リストをLinkedHashSetに戻します。

方法2:

  • treeSetを作成し、それにすべての値を格納します。

方法2は、他の方法がハッシュセットとリストの間でデータをやり取りするために多くの時間を費やすため、より望ましい方法です。


0

HashSetの要素が自動的にソートされるかどうかを決定することはできません。しかし、TreeSetまたはArrayListやLinkedListなどの任意のリストに変換することで、それらを並べ替えることができます。

// Create a TreeSet object of class E
TreeSet<E> ts = new TreeSet<E> ();

// Convert your HashSet into TreeSet
ts.addAll(yourHashSet);

System.out.println(ts.toString() + "\t Sorted Automatically");

0

あなたは同じためにグアバライブラリを使用することができます

Set<String> sortedSet = FluentIterable.from(myHashSet).toSortedSet(new Comparator<String>() {
    @Override
    public int compare(String s1, String s2) {
        // descending order of relevance
        //required code
    }
});


0

次のようにTreeSetでラップできます。

Set mySet = new HashSet();
mySet.add(4);
mySet.add(5);
mySet.add(3);
mySet.add(1);
System.out.println("mySet items "+ mySet);   

TreeSet treeSet = new TreeSet(mySet);   
System.out.println("treeSet items "+ treeSet);   

出力:
mySetアイテム[
1、3、4、5 ] treeSetアイテム[1、3、4、5]

Set mySet = new HashSet();
mySet.add("five");
mySet.add("elf");
mySet.add("four");
mySet.add("six");
mySet.add("two");
System.out.println("mySet items "+ mySet);

TreeSet treeSet = new TreeSet(mySet);
System.out.println("treeSet items "+ treeSet);

出力:
mySetアイテム[
6、4、5、2 、elf] treeSetアイテム[elf、5、4、6、2]

このメソッドの要件は、セット/リストのオブジェクトが比較可能であることです(Comparableインターフェースを実装)。


-4

次の簡単なコマンドでうまくいきました。

myHashSet.toList.sorted

私はこれをprintステートメント内で使用したので、実際に順序を維持する必要がある場合は、このスレッドで提案されているTreeSetまたはその他の構造を使用する必要がある場合があります。


1
HashSetまたはSetにメソッドがある場所がわかりませんtoList
Thomas Eizinger、2015

1
私にはScalaのように見えますが、残念ながらJavaの問題は解決されません。
Roberto

toListメソッド、どのように可能ですか?
Ved Prakash 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.