Bagaimana cara mengurutkan HashSet?

106

Untuk daftar, kami menggunakan Collections.sort(List)metode. Bagaimana jika kita ingin mengurutkan HashSet?

Diana
sumber
20
A HashSetadalah koleksi yang tidak diurutkan.
Alexis C.
2
Anda tidak bisa, karena a Settidak memiliki metode akses acak (yaitu, .get()elemen pada indeks tertentu), yang pada dasarnya diperlukan untuk algoritme sortir;)
fge
3
Anda dapat mengonversinya menjadi daftar terlebih dahulu lalu mengurutkan jika Anda perlu mengurutkan
demongolem
Anda tidak bisa karena HashSettidak memiliki urutan yang ditentukan. Pertanyaan Anda mengandung kontradiksi dalam istilah.
Marquis dari Lorne
1
gunakan TreeSet dan jika Anda tidak dapat mengontrol sumber, lihat konversi penggunaan di sini stackoverflow.com/a/52987487/5153955
Tenflex

Jawaban:

114

HashSet tidak menjamin urutan elemen apa pun. Jika Anda membutuhkan jaminan ini, pertimbangkan untuk menggunakan TreeSet untuk menampung elemen Anda.

Namun jika Anda hanya ingin elemen Anda disortir untuk kejadian yang satu ini, maka buat sementara saja Daftar dan urutkan:

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

...

List<?> sortedList = new ArrayList<>(yourHashSet);
Collections.sort(sortedList);
isak gilbert
sumber
1
Juga, jika Anda menggunakan koleksi Strings, makaList<String> sortedList = new ArrayList<String>(yourHashSet);
wisbucky
65

Tambahkan semua objek Anda ke TreeSet, Anda akan mendapatkan Set yang diurutkan. Di bawah ini adalah contoh mentahnya.

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]
Abdullah Khan
sumber
2
Dengan menggunakan TreeSet myTreeSet = new TreeSet(myHashSet);Anda dapat menghindari menambahkan semua elemen ke Treeset lagi.
Mounika
17

Anda dapat menggunakan TreeSet sebagai gantinya.

jcarvalho.dll
sumber
1
Menempatkan elemen saja tidak akan memberikan fleksibilitas pengurutan pada urutan apa pun dengan elemen apa pun di dalamnya. Solusi di atas bisa.
Jess
16

Cara Java 8 untuk mengurutkannya adalah:

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::getSizeIni adalah contoh bagaimana mengurutkan HashSet dari YourItem secara alami berdasarkan ukuran.

* Collectors.toList()akan mengumpulkan hasil pengurutan ke dalam Daftar yang akan Anda perlukan untuk menangkapnyaList<Foo> sortedListOfFoo =

LazerPisang
sumber
Bisakah Anda, Tambahkan logika untuk mengurutkannya dalam urutan tertentu?
Jess
@Jess saya tidak tahu apa urutan khusus untuk Anda Jess, Anda dapat mengurutkan sesuai keinginan menggunakan komparator.
LazerBanana
Maksud saya, bagaimana mendefinisikan Ascending atau Descending
Jess
14

Gunakan java.util.TreeSetsebagai objek sebenarnya. Saat Anda mengulang koleksi ini, nilainya kembali dalam urutan yang ditentukan dengan baik.

Jika Anda menggunakan java.util.HashSetmaka urutannya tergantung pada fungsi hash internal yang hampir pasti bukan leksikografik (berdasarkan konten).

P45 Segera
sumber
Mengapa Anda berasumsi bahwa mereka menyimpan Stringnilai?
Sotirios Delimanolis
Saya tidak berpikir, mungkin penggunaan leksografik saya tidak tepat ;-)
P45 Imminent
3
Itu sangat salah. Itu tidak menyimpan kunci dalam urutan leksografik (sp?). Ia menggunakan pengurutan alami mereka (yang bergantung pada Comparableantarmuka yang diimplementasikan oleh tombol) atau menggunakan yang disediakan Comparator.
Sotirios Delimanolis
Saya sudah mengedit. Lebih baik menurut Anda, atau haruskah saya menghapus jawabannya?
P45 Segera
1
Jika Anda memindahkan HashSetke TreeSet, kelas Anda harus mengimplementasikan Comparableantarmuka atau menyediakan kustom Comparator. Jika tidak, karena Anda tidak dapat mengurutkan HashSet, cukup ubah menjadi Listdan urutkan.
Luiggi Mendoza
5

Anda dapat menggunakan kolektor Java 8 dan TreeSet

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

Ninja
sumber
new TreeSet<>(hashSet)lebih ringkas dan mungkin lebih efisien.
devconsole
4

Anda dapat menggunakan TreeSet seperti yang disebutkan dalam jawaban lain.

Berikut sedikit penjelasan tentang cara menggunakannya:

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

Keluaran:

[a1, a2, a3, a4, a5]
a1
a2
b1
b2
b3
Alisa
sumber
4

Elemen di HashSet tidak dapat diurutkan. Setiap kali Anda memasukkan elemen ke dalam HashSet, itu dapat mengacaukan urutan keseluruhan set. Memang sengaja didesain seperti itu untuk performa. Jika Anda tidak peduli dengan pesanan, HashSet akan menjadi perangkat yang paling efisien untuk penyisipan dan pencarian cepat.

TreeSet akan mengurutkan semua elemen secara otomatis setiap kali Anda memasukkan elemen.

Mungkin, yang Anda coba lakukan adalah menyortir sekali saja. Dalam hal ini, TreeSet bukanlah pilihan terbaik karena ia perlu menentukan penempatan elemen yang baru ditambahkan setiap saat.

Solusi paling efisien adalah dengan menggunakan ArrayList. Buat daftar baru dan tambahkan semua elemen lalu urutkan sekali. Jika Anda hanya ingin mempertahankan elemen unik (hapus semua duplikat seperti yang dilakukan set, kemudian masukkan daftar ke dalam LinkedHashSet, itu akan mempertahankan urutan yang telah Anda urutkan)

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.

Sekarang, Anda telah mendapatkan kumpulan yang diurutkan jika Anda menginginkannya dalam bentuk daftar lalu mengubahnya menjadi daftar.

off99555
sumber
3

Berdasarkan jawaban yang diberikan oleh @LazerBanana saya akan memberikan contoh Set saya sendiri yang diurutkan berdasarkan Id Objek:

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)
Leandro S
sumber
3

Untuk berjaga-jaga jika Anda tidak ingin menggunakan, TreeSetAnda dapat mencoba ini.

set = set.stream().sorted().collect(Collectors.toCollection(LinkedHashSet::new));
Ankit Sharma
sumber
2

Menurut pendapat saya, jawaban LazerBanana haruslah jawaban teratas & diterima karena semua jawaban lain yang menunjuk ke java.util.TreeSet(atau pertama-tama konversikan ke daftar lalu panggil Collections.sort(...)di daftar yang dikonversi) tidak repot-repot bertanya OP sebagai objek apa yang Anda HashSetmiliki yaitu jika elemen-elemen tersebut memiliki tatanan alami yang telah ditentukan sebelumnya atau tidak & itu bukan pertanyaan opsional tetapi pertanyaan wajib.

Anda tidak bisa masuk & mulai memasukkan HashSetelemen Anda ke dalam TreeSettipe elemen jika belum mengimplementasikan Comparableantarmuka atau jika Anda tidak secara eksplisit meneruskan Comparatorke TreeSetkonstruktor.

Dari TreeSetJavaDoc,

Membuat kumpulan pohon baru yang kosong, diurutkan menurut urutan alami elemennya. Semua elemen yang dimasukkan ke dalam himpunan harus mengimplementasikan antarmuka Comparable. Lebih lanjut, semua elemen tersebut harus saling sebanding: e1.compareTo (e2) tidak boleh menampilkan ClassCastException untuk elemen e1 dan e2 dalam himpunan. Jika pengguna mencoba menambahkan elemen ke set yang melanggar batasan ini (misalnya, pengguna mencoba menambahkan elemen string ke set yang elemennya bilangan bulat), panggilan add akan memunculkan ClassCastException.

Itulah mengapa hanya semua jawaban berbasis aliran Java8 - di mana Anda menentukan pembanding Anda di tempat - hanya masuk akal karena menerapkan perbandingan di POJO menjadi opsional. Programmer mendefinisikan pembanding jika diperlukan. Mencoba mengumpulkan TreeSettanpa menanyakan pertanyaan mendasar ini juga salah (jawaban Ninja). Mengasumsikan tipe objek menjadi Stringatau Integerjuga salah.

Karena itu, masalah lain seperti,

  1. Kinerja Penyortiran
  2. Memory Foot Print (mempertahankan set asli dan membuat set baru yang disortir setiap kali penyortiran selesai atau ingin mengurutkan set di - tempat dll)

harus menjadi poin relevan lainnya juga. Hanya menunjuk ke API seharusnya bukan hanya niat.

Karena set Asli sudah berisi hanya elemen unik & batasan itu juga dipertahankan oleh set yang diurutkan sehingga set asli perlu dihapus dari memori karena data diduplikasi.

Sabir Khan
sumber
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);
    }
  }
 }

masukan - ved prakash sharma apple ved banana

Hasil - pisang apel prakash sharma ved

Ved Prakash
sumber
1

Jika Anda ingin bagian akhir Collectiondalam bentuk Setdan jika Anda ingin menentukan sendiri natural orderdaripada yang TreeSetmaka -

1. Ubah HashSetmenjadi List
2. Urutkan sesuai keinginan Listmenggunakan Comparator
3. Ubah kembali Listmenjadi LinkedHashSetuntuk mempertahankan urutan
4. Tampilkan LinkedHashSet

Program sampel -

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

Keluaran -

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

Di sini koleksi telah diurutkan sebagai -

Pertama - Urutan Stringpanjang
menurun Kedua - Urutan Stringhierarki abjad menurun

Payel Senapati
sumber
0

Anda dapat melakukannya dengan cara berikut:

Metode 1:

  1. Buat daftar dan simpan semua nilai hash ke dalamnya
  2. urutkan daftar menggunakan Collections.sort ()
  3. Simpan daftar kembali ke LinkedHashSet karena ini mempertahankan urutan penyisipan

Metode 2:

  • Buat treeSet dan simpan semua nilai ke dalamnya.

Metode 2 lebih disukai karena metode lain menghabiskan banyak waktu untuk mentransfer data bolak-balik antara hashset dan daftar.

Sujit
sumber
0

Kami tidak dapat memutuskan bahwa elemen dari sebuah HashSet akan diurutkan secara otomatis. Tapi kita bisa mengurutkannya dengan mengubahnya menjadi TreeSet atau List seperti ArrayList atau LinkedList dll.

// 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");
alexvipul.dll
sumber
0

Anda dapat menggunakan perpustakaan jambu biji untuk hal yang sama

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

Anda dapat membungkusnya dalam TreeSet seperti ini:

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

keluaran:
item mySet [1, 3, 4, 5]
item 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);

keluaran:
item mySet [enam, empat, lima, dua, elf]
item treeSet [elf, lima, empat, enam, dua]

persyaratan untuk metode ini adalah bahwa objek set / list harus sebanding (mengimplementasikan antarmuka Comparable)

kecepatan
sumber
-4

Perintah sederhana ini melakukan trik untuk saya:

myHashSet.toList.sorted

Saya menggunakan ini dalam pernyataan cetak, jadi jika Anda perlu benar-benar mempertahankan pemesanan, Anda mungkin perlu menggunakan TreeSets atau struktur lain yang diusulkan di utas ini.

Glenn Strycker
sumber
1
Saya tidak melihat di mana HashSet atau Set memiliki metode toList.
Thomas Eizinger
1
Sepertinya Scala bagi saya, yang sayangnya tidak menyelesaikan masalah di Java.
Roberto
Metode toList, Bagaimana mungkin?
Ved Prakash