HashSet nasıl sıralanır?


106

Listeler için Collections.sort(List)yöntemi kullanıyoruz. Ya sıralamak istersek HashSet?


20
A HashSet, sırasız bir koleksiyondur.
Alexis C.

2
Bir yana, olamaz Setrasgele erişim yöntemi yok (yani .get()belirli bir dizinde bir öğe) temelde sıralama algoritmaları için gereklidir;)
FGE

3
Önce bir listeye dönüştürebilir, ardından sıralamanız gerekirse sıralayabilirsiniz
demongolem

A'nın HashSettanımlanmış bir sırası olmadığı için olamaz. Sorunuz bir çelişki içeriyor.
Marquis of Lorne

1
bir TreeSet kullanın ve kaynağı kontrol edemiyorsanız, dönüşümü burada görün stackoverflow.com/a/52987487/5153955
Tenflex

Yanıtlar:


114

Bir HashSet, öğelerinin herhangi bir sırasını garanti etmez. Bu garantiye ihtiyacınız varsa, öğelerinizi tutmak için bir TreeSet kullanmayı düşünün.

Bununla birlikte, bu olay için yalnızca öğelerinizin sıralanmasına ihtiyacınız varsa, geçici olarak bir Liste oluşturun ve bunu sıralayın:

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

...

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

1
Ayrıca, List<String> sortedList = new ArrayList<String>(yourHashSet);
Dizelerden

65

Tüm nesnelerinizi ekleyin TreeSet, sıralı bir Set alacaksınız. Aşağıda ham bir örnek var.

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
Kullanarak TreeSet myTreeSet = new TreeSet(myHashSet);tüm öğeleri tekrar Treeset'e eklemekten kaçınabilirsiniz.
Mounika

17

Bunun yerine bir TreeSet kullanabilirsiniz .


1
Sadece öğeleri koymak, içindeki herhangi bir öğe ile herhangi bir sıraya göre sıralama esnekliği sağlamaz. Yukarıdaki çözüm yapar.
Jess

16

Java 8 sıralama yöntemi şöyle olacaktır:

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 Öğenizin HashSet'ini doğal olarak boyuta göre nasıl sıralayacağınıza bir örnek.

* Collectors.toList(), onu yakalamanız gereken bir Listeye ayırmanın sonucunu toplayacakList<Foo> sortedListOfFoo =


Lütfen belirli bir sıraya göre sıralamak için mantığı ekleyebilir misiniz?
Jess

@Jess, sizin için özel sıranın ne olduğunu bilmiyorum Jess, karşılaştırıcıyı kullanarak istediğiniz gibi sıralayabilirsiniz.
LazerBanana

Artan veya
Jess

14

java.util.TreeSetGerçek nesne olarak kullanın . Bu koleksiyonu yinelediğinizde, değerler iyi tanımlanmış bir sırayla geri gelir.

Eğer kullanırsanız java.util.HashSet, sıra, neredeyse kesinlikle sözlükbilimsel olmayan (içeriğe bağlı olarak) dahili bir hash fonksiyonuna bağlıdır.


Neden Stringdeğerleri sakladıklarını varsayıyorsunuz ?
Sotirios Delimanolis

Belki de sözcük bilgisini kullanmam kesin değildir ;-)
P45 Yakında

3
Bu çok yanlış. Anahtarları sözlük (sp?) Sırasına göre saklamaz. Ya kendi doğal sırasını kullanır ( Comparablebu, anahtarların uyguladığı arayüze bağlıdır ) veya sağlananları kullanır Comparator.
Sotirios Delimanolis

Ben düzenledim. Sence daha mı iyi yoksa cevabı silmeli miyim?
P45 Yakında

1
Eğer bir hareket HashSetiçin TreeSet, sınıf uygulamalıdır Comparablearabirimini veya özel sağlamak Comparator. Aksi takdirde, a'yı sıralayamayacağınız için HashSet, onu a'ya dönüştürün Listve sıralayın.
Luiggi Mendoza

5

Java 8 toplayıcılarını ve TreeSet'i kullanabilirsiniz

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


new TreeSet<>(hashSet)daha özlü ve muhtemelen daha etkilidir.
devconsole

4

Diğer cevaplarda belirtildiği gibi TreeSet'i kullanabilirsiniz.

İşte nasıl kullanılacağına dair biraz daha detay:

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

Çıktı:

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

4

HashSet'teki öğeler sıralanamaz. Öğeleri HashSet'e her koyduğunuzda, tüm setin sırasını bozabilir. Performans için bilinçli olarak bu şekilde tasarlanmıştır. Siparişi önemsemediğinizde, HashSet hızlı ekleme ve arama için en verimli set olacaktır.

TreeSet, her öğe eklediğinizde tüm öğeleri otomatik olarak sıralayacaktır.

Belki de yapmaya çalıştığınız şey sadece bir kez sıralamaktır. Bu durumda, TreeSet en iyi seçenek değildir çünkü her zaman yeni eklenen elemanların yerleştirilmesini belirlemesi gerekir.

En verimli çözüm ArrayList kullanmaktır. Yeni bir liste oluşturun ve tüm öğeleri ekleyin ve ardından bir kez sıralayın. Yalnızca benzersiz öğeleri korumak istiyorsanız (setin yaptığı gibi tüm kopyaları kaldırın, ardından listeyi bir LinkedHashSet'e koyun, önceden sıraladığınız sıralamayı koruyacaktır)

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.

Şimdi, bir liste biçiminde istiyorsanız sıralı bir küme elde edersiniz ve sonra onu listeye dönüştürün.


3

@LazerBanana tarafından verilen cevaba göre, Nesnenin Kimliğine göre sıralanmış bir Küme örneğimi koyacağım:

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

Sadece, kullanmak istemiyorsan TreeSetbunu deneyebilirsin.

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

2

Benim düşünceme göre, LazerBanana cevabı tüm diğer cevaplar işaret çünkü kabul üst dereceli yanıt & olmalıdır java.util.TreeSet(veya listeye ilk dönüştürme sonra çağrı Collections.sort(...)dönüştürülen listesinde) tür senin hangi nesne olarak OP sormak için rahatsız etmedi HashSetvardır yani bu elemanların önceden tanımlanmış bir doğal düzeni varsa olmadığı ve bu isteğe bağlı bir soru değil, zorunlu bir sorudur.

Sadece gitmek & senin koyarak başlayamaz HashSetbir içine unsurları TreeSetzaten uygulamaması halinde öğe türü Comparableaçıkça geçen değilse arayüzü veya Comparatorhiç TreeSetyapıcısı.

Gönderen TreeSetJavaDoc'u,

Öğelerinin doğal sırasına göre sıralanmış yeni, boş bir ağaç kümesi oluşturur. Sete eklenen tüm öğeler, Karşılaştırılabilir arayüzü uygulamalıdır. Ayrıca, tüm bu tür öğeler karşılıklı olarak karşılaştırılabilir olmalıdır: e1.compareTo (e2), kümedeki herhangi bir e1 ve e2 öğesi için bir ClassCastException oluşturmamalıdır. Kullanıcı kümeye bu kısıtlamayı ihlal eden bir öğe eklemeye çalışırsa (örneğin, kullanıcı, öğeleri tam sayı olan bir kümeye bir dize öğesi eklemeye çalışırsa), add çağrısı bir ClassCastException oluşturur.

Bu nedenle, yalnızca karşılaştırıcınızı yerinde tanımladığınız tüm Java8 akış tabanlı yanıtlar yalnızca anlamlıdır, çünkü POJO'da karşılaştırılabilir uygulama isteğe bağlı hale gelir. Programcı, karşılaştırıcıyı gerektiği gibi ve gerektiğinde tanımlar. TreeSetBu temel soruyu sormadan toplamaya çalışmak da yanlıştır (Ninja'nın cevabı). Nesne türlerinin yanlış olduğunu Stringveya Integeryanlış olduğunu varsaymak.

Bunu söyledikten sonra, diğer endişeler,

  1. Sıralama Performansı
  2. Bellek Ayak Baskısı (orijinal seti korumak ve her sıralama yapıldığında veya seti yerinde sıralamak, vb.)

diğer ilgili noktalar da olmalıdır. Sadece API'ye işaret etmek sadece niyet olmamalı.

Orijinal küme zaten yalnızca benzersiz öğeler içerdiğinden ve bu kısıtlama sıralı küme tarafından da korunduğundan, veriler çoğaltıldığından orijinal kümenin bellekten temizlenmesi gerekir.


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

girdi - ved prakash sharma apple ved muz

Çıktı - elma muz prakash sharma ved


1

İstediğiniz istediğiniz takdirde sonu Collectionşeklinde olması Setve kendi tanımlamak istiyorsanız natural orderdaha ziyade TreeSetsonra -

1. dönüştürme HashSetiçine List
sıralama 2. Custom Listkullanarak Comparator
3. dönüştürme geri Listiçine LinkedHashSetdüzeni sürdürmek için
4. Ekran LinkedHashSet

Örnek program -

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

Çıktı -

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

Burada koleksiyon şu şekilde sıralanmıştır: -

Birinci - Azalan Stringuzunluk sırası
İkinci - StringAlfabetik hiyerarşinin azalan sırası


0

bunu aşağıdaki şekillerde yapabilirsiniz:

Yöntem 1:

  1. Bir liste oluşturun ve tüm hashset değerlerini içine kaydedin
  2. Listeyi Collections.sort () kullanarak sıralayın
  3. Ekleme siparişini koruduğu için listeyi LinkedHashSet'e geri kaydedin

Yöntem 2:

  • Bir ağaç kümesi oluşturun ve tüm değerleri onun içinde saklayın.

Yöntem 2 daha çok tercih edilir çünkü diğer yöntem, hashset ve liste arasında ileri ve geri veri aktarmak için çok zaman tüketir.


0

Bir HashSet'in öğelerinin otomatik olarak sıralanacağına karar veremeyiz. Ancak bunları TreeSet'e veya ArrayList veya LinkedList gibi herhangi bir Listeye dönüştürerek sıralayabiliriz.

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

Aynı şekilde guava kitaplığını kullanabilirsiniz

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

Bunu bir TreeSet'e şu şekilde sarabilirsiniz:

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

çıktı:
mySet öğeleri [1, 3, 4, 5]
treeSet öğeleri [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);

çıktı:
mySet öğeleri [altı, dört, beş, iki, elf]
treeSet öğeleri [elf, beş, dört, altı, iki]

bu yöntemin gerekliliği, kümenin / listenin nesnelerinin karşılaştırılabilir olmasıdır (Karşılaştırılabilir arabirimi uygulayın)


-4

Bu basit komut benim için hile yaptı:

myHashSet.toList.sorted

Bunu bir print deyiminde kullandım, bu yüzden sıralamayı gerçekten sürdürmeniz gerekiyorsa, TreeSets veya bu iş parçacığında önerilen diğer yapıları kullanmanız gerekebilir.


1
HashSet veya Set'in bir metodunun nerede olduğunu göremiyorum toList.
Thomas Eizinger

1
Bu bana Scala gibi görünüyor, maalesef Java'daki sorunu çözmüyor.
Roberto

toList yöntemi nasıl mümkündür?
Ved Prakash
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.