วิธีจัดเรียง HashSet


106

สำหรับรายการเราใช้Collections.sort(List)วิธี ถ้าเราต้องการเรียงลำดับ a HashSet?


20
A HashSetคือคอลเล็กชันที่ไม่มีการเรียงลำดับ
Alexis C.

2
คุณทำไม่ได้เนื่องจาก a Setไม่มีวิธีการเข้าถึงแบบสุ่ม (เช่น.get()องค์ประกอบที่ดัชนีที่กำหนด) ซึ่งโดยพื้นฐานแล้วจำเป็นสำหรับอัลกอริทึมการเรียงลำดับ)
fge

3
คุณสามารถแปลงเป็นรายการก่อนจากนั้นจัดเรียงหากคุณต้องการจัดเรียง
demongolem

คุณทำไม่ได้เนื่องจาก a HashSetไม่มีคำสั่งซื้อที่กำหนดไว้ คำถามของคุณแสดงถึงความขัดแย้งในแง่
Marquis of Lorne

1
ใช้ TreeSet และหากคุณไม่สามารถควบคุมแหล่งที่มาได้ให้ดูการแปลงการใช้งานที่นี่ stackoverflow.com/a/52987487/5153955
Tenflex

คำตอบ:


114

HashSet ไม่รับประกันลำดับองค์ประกอบใด ๆ หากคุณต้องการการรับประกันนี้ให้พิจารณาใช้ TreeSet เพื่อเก็บองค์ประกอบของคุณ

อย่างไรก็ตามหากคุณต้องการจัดเรียงองค์ประกอบของคุณสำหรับเหตุการณ์นี้ให้สร้างรายการชั่วคราวและจัดเรียงว่า:

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

...

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

1
นอกจากนี้หากคุณใช้คอลเลคชัน StringsList<String> sortedList = new ArrayList<String>(yourHashSet);
wisbucky

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);คุณสามารถหลีกเลี่ยงการเพิ่มองค์ประกอบทั้งหมดในชุดต้นไม้อีกครั้ง
Mounika

17

คุณสามารถใช้TreeSetแทนได้


1
เพียงแค่ใส่องค์ประกอบจะไม่ให้ความยืดหยุ่นในการจัดเรียงลำดับใด ๆ โดยมีองค์ประกอบใด ๆ อยู่ภายใน วิธีแก้ปัญหาข้างต้นทำ
Jess

16

วิธีการจัดเรียง 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เป็นตัวอย่างวิธีการจัดเรียง HashSet ของ YourItem ตามขนาดตามธรรมชาติ

* Collectors.toList()กำลังจะรวบรวมผลลัพธ์ของการเรียงลำดับลงใน List ที่คุณจะต้องจับมันด้วยList<Foo> sortedListOfFoo =


กรุณาเพิ่มตรรกะเพื่อจัดเรียงตามลำดับที่ระบุได้ไหม
เจส

@ เจสฉันไม่รู้ว่าคำสั่งเฉพาะสำหรับคุณเจสคืออะไรคุณสามารถจัดเรียงได้ตามที่คุณต้องการโดยใช้ตัวเปรียบเทียบ
LazerBanana

ฉันหมายถึงวิธีการกำหนด Ascending หรือ Descending
Jess

14

ใช้java.util.TreeSetเป็นวัตถุจริง เมื่อคุณวนซ้ำคอลเลกชันนี้ค่าจะกลับมาตามลำดับที่กำหนดไว้อย่างดี

หากคุณใช้java.util.HashSetคำสั่งจะขึ้นอยู่กับฟังก์ชันแฮชภายในซึ่งแทบจะไม่ใช่ศัพท์ (ตามเนื้อหา)


ทำไมคุณถึงคิดว่าพวกเขาเก็บStringค่า?
Sotirios Delimanolis

ฉันไม่ได้ว่าบางทีการใช้คำศัพท์ของฉันไม่ชัดเจน ;-)
P45 ใกล้จะถึง

3
มันผิดมาก ไม่เก็บคีย์ในคำสั่ง lexographic (sp?) มันใช้การเรียงลำดับตามธรรมชาติ (ซึ่งขึ้นอยู่กับComparableอินเทอร์เฟซที่ใช้คีย์) หรือใช้ที่ให้Comparatorมา
Sotirios Delimanolis

ฉันแก้ไขแล้ว คุณคิดว่าดีกว่าหรือฉันควรลบคำตอบ
P45 ใกล้จะถึง

1
ในกรณีที่คุณย้ายHashSetไปยังTreeSetชั้นของคุณจะต้องใช้อินเตอร์เฟซหรือให้กำหนดเองComparable Comparatorมิฉะนั้นเนื่องจากคุณไม่สามารถจัดเรียง a ได้HashSetให้แปลงเป็น a Listและจัดเรียง
Luiggi Mendoza

5

คุณสามารถใช้ Java 8 collectors และ 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 สร้างรายการใหม่และเพิ่มองค์ประกอบทั้งหมดจากนั้นจัดเรียงครั้งเดียว หากคุณต้องการเก็บเฉพาะองค์ประกอบที่ไม่ซ้ำกัน (ลบรายการที่ซ้ำกันทั้งหมดเช่น set does จากนั้นใส่รายการลงใน 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(...)ในรายการที่แปลง) ไม่ได้ใส่ใจที่จะถาม OP เป็นสิ่งที่ชนิดของวัตถุของคุณHashSetมีคือ หากองค์ประกอบเหล่านั้นมีลำดับตามธรรมชาติที่กำหนดไว้ล่วงหน้าหรือไม่ & นั่นไม่ใช่คำถามเสริม แต่เป็นคำถามบังคับ

คุณไม่สามารถเข้าไปและเริ่มใส่HashSetองค์ประกอบของคุณลงในประเภทTreeSetif element ยังไม่ได้ติดตั้งComparableอินเทอร์เฟซหรือหากคุณไม่ได้ส่งผ่านComparatorไปยังตัวTreeSetสร้าง อย่างชัดเจน

จากTreeSetJavaDoc

สร้างชุดต้นไม้ใหม่ที่ว่างเปล่าโดยจัดเรียงตามลำดับตามธรรมชาติขององค์ประกอบ องค์ประกอบทั้งหมดที่ใส่เข้าไปในชุดต้องใช้อินเทอร์เฟซที่เปรียบเทียบได้ นอกจากนี้องค์ประกอบทั้งหมดดังกล่าวต้องสามารถเปรียบเทียบกันได้: e1.compareTo (e2) ต้องไม่โยน ClassCastException สำหรับองค์ประกอบ e1 และ e2 ใด ๆ ในชุด หากผู้ใช้พยายามเพิ่มองค์ประกอบให้กับชุดที่ละเมิดข้อ จำกัด นี้ (ตัวอย่างเช่นผู้ใช้พยายามเพิ่มองค์ประกอบสตริงให้กับชุดที่องค์ประกอบเป็นจำนวนเต็ม) การเรียกเพิ่มจะส่ง ClassCastException

นั่นคือเหตุผลที่มีเพียงคำตอบที่ใช้สตรีม Java8 ทั้งหมด - ที่คุณกำหนดตัวเปรียบเทียบของคุณในจุดที่เหมาะสมเท่านั้นเนื่องจากการใช้งานที่เทียบเคียงใน POJO กลายเป็นทางเลือก โปรแกรมเมอร์กำหนดตัวเปรียบเทียบตามและเมื่อจำเป็น การพยายามรวบรวมTreeSetโดยไม่ถามคำถามพื้นฐานนี้ก็ไม่ถูกต้องเช่นกัน (คำตอบของนินจา) สมมติว่าประเภทวัตถุเป็นStringหรือIntegerไม่ถูกต้อง

ต้องบอกว่าข้อกังวลอื่น ๆ เช่น

  1. การเรียงลำดับประสิทธิภาพ
  2. Memory Foot Print (รักษาชุดเดิมและสร้างชุดที่เรียงใหม่ทุกครั้งที่จัดเรียงเสร็จหรือต้องการจัดเรียงชุดในสถานที่ ฯลฯ ฯลฯ )

ควรเป็นประเด็นอื่น ๆ ที่เกี่ยวข้องด้วย เพียงแค่ชี้ไปที่ 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 apple ved banana

ผลผลิต - กล้วยแอปเปิ้ลประกาชชาร์มาเวช


1

ถ้าคุณต้องการให้จุดสิ้นสุดCollectionอยู่ในรูปแบบของSetและถ้าคุณต้องการกำหนดของคุณเองnatural orderแทนที่จะเป็นแบบTreeSetนั้น -

1. แปลงHashSetเป็นList
2. กำหนดเองเรียงลำดับListโดยใช้Comparator
3. แปลงกลับListเข้าไปLinkedHashSetเพื่อรักษาลำดับ
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ความยาว
สอง - เรียงลำดับลงของStringลำดับชั้นตามลำดับตัวอักษร


0

คุณสามารถทำได้ด้วยวิธีต่อไปนี้:

วิธีที่ 1:

  1. สร้างรายการและเก็บค่าแฮชเซ็ตทั้งหมดไว้ในนั้น
  2. จัดเรียงรายการโดยใช้ Collections.sort ()
  3. จัดเก็บรายการกลับไปที่ LinkedHashSet เนื่องจากจะรักษาลำดับการแทรก

วิธีที่ 2:

  • สร้าง treeSet และเก็บค่าทั้งหมดไว้ในนั้น

วิธีที่ 2 เป็นวิธีที่ดีกว่าเนื่องจากวิธีอื่นใช้เวลามากในการถ่ายโอนข้อมูลไปมาระหว่างแฮชเซ็ตและรายการ


0

เราไม่สามารถตัดสินใจได้ว่าองค์ประกอบของ HashSet จะถูกจัดเรียงโดยอัตโนมัติ แต่เราสามารถจัดเรียงได้โดยการแปลงเป็น TreeSet หรือ List ใด ๆ เช่น 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

คุณสามารถใช้ guava library เหมือนกัน

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 [หกสี่ห้าสองเอลฟ์]
treeSet รายการ [เอลฟ์ห้าสี่หกสอง]

ข้อกำหนดสำหรับวิธีนี้คืออ็อบเจ็กต์ของชุด / รายการควรเทียบเคียงได้ (ใช้อินเทอร์เฟซที่เปรียบเทียบได้)


-4

คำสั่งง่ายๆนี้ใช้เคล็ดลับสำหรับฉัน:

myHashSet.toList.sorted

ฉันใช้สิ่งนี้ภายในคำสั่งการพิมพ์ดังนั้นหากคุณต้องการคงการสั่งซื้อจริงคุณอาจต้องใช้ TreeSets หรือโครงสร้างอื่น ๆ ที่เสนอในเธรดนี้


1
ไม่เห็นว่า HashSet หรือ Set มีวิธีการตรงtoListไหน
Thomas Eizinger

1
ดูเหมือนว่า Scala สำหรับฉันซึ่งน่าเสียดายที่ไม่สามารถแก้ปัญหาใน Java ได้
Roberto

toList method เป็นไปได้อย่างไร?
Ved Prakash
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.