Wie sortiere ich ein HashSet?


105

Für Listen verwenden wir die Collections.sort(List)Methode. Was ist, wenn wir eine sortieren wollen HashSet?


20
A HashSetist eine ungeordnete Sammlung.
Alexis C.

2
Sie können nicht, da a Setkeine Direktzugriffsmethoden hat (dh .get()ein Element an einem bestimmten Index), die grundsätzlich für Sortieralgorithmen erforderlich sind;)
fge

3
Sie könnten es zuerst in eine Liste konvertieren und dann sortieren, wenn Sie sortieren müssen
demongolem

Sie können nicht, da a HashSetkeine definierte Reihenfolge hat. Ihre Frage verkörpert einen Widerspruch.
Marquis von Lorne

1
Verwenden Sie ein TreeSet und wenn Sie die Quelle nicht steuern können, sehen Sie die Konvertierung und Verwendung hier stackoverflow.com/a/52987487/5153955
Tenflex

Antworten:


113

Ein HashSet garantiert keine Reihenfolge seiner Elemente. Wenn Sie diese Garantie benötigen, sollten Sie ein TreeSet verwenden, um Ihre Elemente zu speichern.

Wenn Sie jedoch nur Ihre Elemente für dieses eine Vorkommen sortieren müssen, erstellen Sie vorübergehend eine Liste und sortieren Sie diese:

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

...

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

1
Auch wenn Sie eine Sammlung von Strings verwenden, dannList<String> sortedList = new ArrayList<String>(yourHashSet);
wisbucky

65

Wenn Sie alle Ihre Objekte zum hinzufügen TreeSet, erhalten Sie ein sortiertes Set. Unten ist ein rohes Beispiel.

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
Durch die Verwendung können TreeSet myTreeSet = new TreeSet(myHashSet);Sie vermeiden, dass alle Elemente erneut zu Treeset hinzugefügt werden.
Mounika

17

Sie können stattdessen ein TreeSet verwenden.


1
Nur die Elemente zu platzieren, gibt nicht die Flexibilität, nach einer Bestellung mit einem Element darin zu sortieren. Die obige Lösung tut es.
Jess

15

Java 8 Weg, um es zu sortieren wäre:

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::getSizeEs ist ein Beispiel, wie das HashSet von YourItem natürlich nach Größe sortiert wird.

* Collectors.toList()sammelt das Ergebnis der Sortierung in einer Liste, mit der Sie es erfassen müssenList<Foo> sortedListOfFoo =


Können Sie bitte die Logik hinzufügen, um sie in einer bestimmten Reihenfolge zu sortieren?
Jess

@ Jess Ich weiß nicht, was die spezifische Reihenfolge für Sie Jess ist, Sie können es nach Ihren Wünschen mit dem Komparator sortieren.
LazerBanana

Ich meinte, wie man den Aufsteigenden oder Absteigenden definiert
Jess

14

Verwenden Sie java.util.TreeSetals das eigentliche Objekt. Wenn Sie diese Sammlung durchlaufen, werden die Werte in einer genau definierten Reihenfolge zurückgegeben.

Wenn Sie verwenden java.util.HashSet, hängt die Reihenfolge von einer internen Hash-Funktion ab, die mit ziemlicher Sicherheit nicht lexikografisch ist (basierend auf dem Inhalt).


Warum nehmen Sie an, dass sie StringWerte speichern ?
Sotirios Delimanolis

Ich bin nicht, obwohl meine Verwendung von Lexografie vielleicht ungenau ist ;-)
P45

3
Es ist sehr falsch. Es werden keine Schlüssel in lexografischer (sp?) Reihenfolge gespeichert. Es verwendet entweder ihre natürliche Reihenfolge (die von der ComparableSchnittstelle abhängt , die die Schlüssel implementieren) oder verwendet die bereitgestellte Comparator.
Sotirios Delimanolis

Ich habe bearbeitet. Besser denkst du, oder soll ich die Antwort löschen?
P45 am

1
Wenn Sie ein HashSetnach verschieben TreeSet, muss Ihre Klasse eine ComparableSchnittstelle implementieren oder eine benutzerdefinierte Schnittstelle bereitstellen Comparator. Andernfalls, da Sie a nicht sortieren können HashSet, konvertieren Sie es einfach in a Listund sortieren Sie es.
Luiggi Mendoza

5

Sie können Java 8-Kollektoren und TreeSet verwenden

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


new TreeSet<>(hashSet)ist prägnanter und wahrscheinlich effizienter.
Devconsole

4

Sie können TreeSet wie in anderen Antworten erwähnt verwenden.

Hier ist eine etwas ausführlichere Beschreibung der Verwendung:

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

Ausgabe:

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

4

Elemente in HashSet können nicht sortiert werden. Immer wenn Sie Elemente in HashSet einfügen, kann dies die Reihenfolge des gesamten Satzes durcheinander bringen. Es ist bewusst so für die Leistung ausgelegt. Wenn Sie sich nicht für die Bestellung interessieren, ist HashSet das effizienteste Set für schnelles Einfügen und Suchen.

TreeSet sortiert alle Elemente automatisch jedes Mal, wenn Sie ein Element einfügen.

Vielleicht versuchen Sie nur einmal zu sortieren. In diesem Fall ist TreeSet nicht die beste Option, da ständig die Platzierung neu hinzugefügter Elemente bestimmt werden muss.

Die effizienteste Lösung ist die Verwendung von ArrayList. Erstellen Sie eine neue Liste, fügen Sie alle Elemente hinzu und sortieren Sie sie einmal. Wenn Sie nur eindeutige Elemente beibehalten möchten (entfernen Sie alle Duplikate wie bei set und fügen Sie die Liste in ein LinkedHashSet ein. Die Reihenfolge, die Sie bereits sortiert haben, wird beibehalten.)

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.

Jetzt haben Sie einen sortierten Satz erhalten, wenn Sie ihn in einer Listenform haben möchten, und konvertieren ihn dann in eine Liste.


3

Basierend auf der Antwort von @LazerBanana werde ich mein eigenes Beispiel für ein Set geben, das nach der ID des Objekts sortiert ist:

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

Nur für den Fall, dass Sie keine verwenden möchten, können TreeSetSie dies versuchen.

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

2

Meiner bescheidenen Meinung nach sollte die Antwort von LazerBanana die am besten bewertete Antwort sein und akzeptiert werden, da alle anderen Antworten, die auf java.util.TreeSet(oder zuerst in eine Liste konvertieren, dann Collections.sort(...)die konvertierte Liste aufrufen ) verweisen , OP nicht gefragt haben, welche Art von Objekten Sie HashSethaben, d. H. ob diese Elemente eine vordefinierte natürliche Reihenfolge haben oder nicht & das ist keine optionale Frage, sondern eine obligatorische Frage.

Sie können einfach nicht hineingehen und Ihre HashSetElemente in eine Schnittstelle einfügen, TreeSetwenn der Elementtyp noch keine ComparableSchnittstelle implementiert oder wenn Sie nicht explizit an Comparatorden TreeSetKonstruktor übergeben.

Von TreeSetJavaDoc,

Erstellt eine neue, leere Baumgruppe, die nach der natürlichen Reihenfolge ihrer Elemente sortiert ist. Alle in die Menge eingefügten Elemente müssen die Schnittstelle Comparable implementieren. Darüber hinaus müssen alle diese Elemente miteinander vergleichbar sein: e1.compareTo (e2) darf keine ClassCastException für Elemente e1 und e2 in der Menge auslösen. Wenn der Benutzer versucht, der Menge ein Element hinzuzufügen, das gegen diese Einschränkung verstößt (z. B. versucht der Benutzer, einer Menge, deren Elemente Ganzzahlen sind, ein Zeichenfolgenelement hinzuzufügen), löst der Aufruf add eine ClassCastException aus.

Aus diesem Grund sind nur alle auf Java8-Streams basierenden Antworten - bei denen Sie Ihren Komparator vor Ort definieren - nur sinnvoll, da die Implementierung von vergleichbaren Antworten in POJO optional wird. Der Programmierer definiert den Komparator nach Bedarf. Der Versuch, TreeSetohne diese grundlegende Frage zu sammeln , ist ebenfalls falsch (Ninjas Antwort). Angenommen, Objekttypen sind Stringoder Integersind auch falsch.

Allerdings sind andere Bedenken wie:

  1. Sortierleistung
  2. Speicher-Fußabdruck (Beibehalten des ursprünglichen Satzes und Erstellen neuer sortierter Sätze jedes Mal, wenn die Sortierung durchgeführt wird oder wenn der Satz an Ort und Stelle sortiert werden soll usw. usw.)

sollten auch die anderen relevanten Punkte sein. Nur auf API zu zeigen, sollte nicht nur Absicht sein.

Da der Originalsatz bereits nur eindeutige Elemente enthält und diese Einschränkung auch durch den sortierten Satz beibehalten wird, muss der Originalsatz aus dem Speicher gelöscht werden, da Daten dupliziert werden.


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

Eingabe - Prakash Sharma Apfel Ved Banane

Ausgabe - Apfel Banane Prakash Sharma Ved


1

Wenn Sie möchten, dass das Ende Collectionin der Form von vorliegt Setund wenn Sie Ihr eigenes natural orderund nicht das von TreeSetdann definieren möchten -

1. Konvertieren Sie das HashSetin List
2. Benutzerdefinierte Sortierung Listmit Comparator
3. Konvertieren Sie das Listin zurück LinkedHashSet, um die Reihenfolge aufrechtzuerhalten.
4. Zeigen Sie das an LinkedHashSet

Beispielprogramm -

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

Ausgabe -

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

Hier wurde die Sammlung sortiert nach -

Erste - Absteigende Reihenfolge der StringLänge
Zweitens - Absteigende Reihenfolge der Stringalphabetischen Hierarchie


0

Sie können dies auf folgende Arten tun:

Methode 1:

  1. Erstellen Sie eine Liste und speichern Sie alle Hashset-Werte darin
  2. Sortieren Sie die Liste mit Collections.sort ()
  3. Speichern Sie die Liste wieder in LinkedHashSet, da die Einfügereihenfolge beibehalten wird

Methode 2:

  • Erstellen Sie ein treeSet und speichern Sie alle Werte darin.

Methode 2 ist vorzuziehen, da die andere Methode viel Zeit benötigt, um Daten zwischen Hashset und Liste hin und her zu übertragen.


0

Wir können nicht entscheiden, dass die Elemente eines HashSet automatisch sortiert werden. Wir können sie jedoch sortieren, indem wir sie in TreeSet oder eine beliebige Liste wie ArrayList oder LinkedList usw. konvertieren.

// 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

Sie können die Guavenbibliothek für dasselbe verwenden

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

Sie können es wie folgt in ein TreeSet einwickeln:

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

Ausgabe:
mySet-Elemente [1, 3, 4, 5]
treeSet-Elemente [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);

Ausgabe:
mySet-Elemente [sechs, vier, fünf, zwei, Elfen]
treeSet-Elemente [Elfen, fünf, vier, sechs, zwei]

Voraussetzung für diese Methode ist, dass die Objekte der Menge / Liste vergleichbar sind (implementieren Sie die Schnittstelle Comparable).


-4

Dieser einfache Befehl hat den Trick für mich getan:

myHashSet.toList.sorted

Ich habe dies in einer print-Anweisung verwendet. Wenn Sie also die Reihenfolge beibehalten möchten, müssen Sie möglicherweise TreeSets oder andere in diesem Thread vorgeschlagene Strukturen verwenden.


1
Ich sehe nicht, wo HashSet oder Set eine Methode hat toList.
Thomas Eizinger

1
Das sieht für mich nach Scala aus, was das Problem in Java leider nicht löst.
Roberto

toList Methode, wie ist möglich?
Ved Prakash
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.