ฉันจะเรียงลำดับชุดเป็นรายการใน Java ได้อย่างไร


169

ใน Java ฉันมีและฉันต้องการที่จะทำให้มันกลายเป็นที่เรียงลำดับSet Listมีวิธีในjava.util.Collectionsแพ็คเกจที่จะทำสิ่งนี้ให้ฉันหรือไม่?

คำตอบ:


214

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

ให้ใช้บางสิ่งเช่นนี้แทน:

public static
<T extends Comparable<? super T>> List<T> asSortedList(Collection<T> c) {
  List<T> list = new ArrayList<T>(c);
  java.util.Collections.sort(list);
  return list;
}

นี่คือตัวอย่างการใช้งาน:

Map<Integer, String> map = new HashMap<Integer, String>();
/* Add entries to the map. */
...
/* Now get a sorted list of the *values* in the map. */
Collection<String> unsorted = map.values();
List<String> sorted = Util.asSortedList(unsorted);

3
ขอบคุณ! SuppressWarnings นั้นรบกวนฉันอยู่เสมอ
Jeremy Stein

4
@sunleo Utilคลาสนี้เป็นคลาสที่มีasSortedList()วิธีการที่ฉันเขียน คุณเขียนUtilชั้นเรียนด้วยตัวเองแล้วใส่รหัสนั้นลงไป
erickson

1
ฮ่าฮ่าฉันคิดว่ามันมาจากชุดเริ่มต้นเช่น java.util ok ขอบคุณ
sunleo

3
นี่อาจเป็นฟังก์ชั่นยูทิลิตี้ทั่วไปที่ดี แต่ความจริงก็คือมันยังไม่มีประสิทธิภาพ พิจารณาการจัดเรียงในสถานที่โดยทำให้แน่ใจว่าคุณมีชุดของคุณในภาชนะที่เหมาะสมที่จะเริ่มต้นด้วย พิจารณาการใช้ TreeSet เป็นที่เก็บข้อมูลโดยตรงของคุณ หากข้อมูลของคุณต้องไม่ซ้ำกัน แต่อย่างใดและคุณจำเป็นต้องมีชุดจากนั้นใช้ชุดต้นไม้จับแมลงวันสองตัวในหน่วยเดียว
YoYo

1
ในฐานะที่เป็นข้อความถึงผู้คนเท่านั้นที่อ่านคำตอบยอดนิยม: ดูคำตอบของ nschum ด้านล่างซึ่งใช้สตรีมของ Java 8 หากคุณสามารถใช้ Java 8 ไปได้เลย พวกมันยืดหยุ่นและมีประสิทธิภาพมากขึ้น
Felk

74

ชุดเรียง:

return new TreeSet(setIWantSorted);

หรือ:

return new ArrayList(new TreeSet(setIWantSorted));

นี่เป็นความคิดแรกของฉัน แต่ผู้ถามต้องการรายการ
อเล็กซ์ B

@Alex: วิธีการนี้ยังคงสามารถใช้งานได้ คืน ArrayList ใหม่ (TreeSet ใหม่ (setIWantSorted))
Jonik

1
ฉันใช้วิธีนี้จริง ๆ แต่ฉันจะไม่แนะนำสิ่งนี้ ในฐานะที่เป็นเอกสารเกี่ยวกับสถานะของ TreeSet (ดูdownload.oracle.com/javase/1.4.2/docs/api/java/util/ … ) จะใช้วิธีการ comparTo () แทนวิธี equals () อย่างมีประสิทธิภาพ - ดังนั้นหากคุณ มีวัตถุสองชุดในชุดที่มีผลลัพธ์เท่ากัน () พวกเขาจะถูกมองว่าซ้ำซ้อนและจะไม่ถูกเพิ่มลงใน TreeSet ระวัง.
fwielstra

24
@fwielstra: คุณจะมีวัตถุที่เท่ากันในการป้อนข้อมูลตั้งแต่การป้อนข้อมูลยังเป็นSetอย่างไร
ryanprayogo

2
@ryanprayogo เป็นมูลค่าการกล่าวขวัญnew TreeSetยอมรับCollectionว่าไม่ใช่แค่Sets ไม่ใช่ทุกคนที่อ่านคำตอบนี้จะใช้ a Setถึงแม้ว่านั่นคือสิ่งที่คำถามเดิมถาม
Chris

44
List myList = new ArrayList(collection);
Collections.sort(myList);

... ควรทำอย่างไร เพิ่มรสชาติด้วย Generics ถ้ามี


ฉันมีตัวอย่างที่มีประโยชน์ที่ฉันต้องการบริจาคให้กับชุมชน เมื่อฉันค้นหาข้อมูลฉันไม่พบมัน ฉันพยายามทำให้งานของคนต่อไปง่ายขึ้น stackoverflow.com/questions/18557/…
Jeremy Stein

1
ใช่แน่นอน แต่ลิงค์ที่คุณให้ไว้นั้นกำลังพูดถึงคำถามจริง (เช่นคำถามที่ไม่มีคำตอบจากนั้นหาได้) คำถามของคุณที่นี่เพียงเพื่อให้คำตอบ ... ฉันสามารถป้อนคำถามได้หลายร้อยคำถามและตอบตัวเอง; นั่นไม่ใช่ประเด็น!
Seb

5
@Seb: ฉันไม่เห็นด้วย ฉันไม่เห็นอะไรผิดปกติกับคำถามนี้ เห็นได้ชัดว่าไม่ใช่คำถามที่ง่ายมากและตอนนี้เขารู้วิธีที่ดีกว่าที่เขาเคยทำมาก่อน!
Michael Myers

3
มันเป็นคำถามจริง แต่ฉันพบคำตอบด้วยตัวเองหลังจากที่ Google ออกมาสั้น ๆ Stackoverflow ไม่มีอยู่ในเวลานั้น ฉันโพสต์ไว้บนเว็บไซต์ของฉันและช่วยเหลือคนอื่นดังนั้นฉันคิดว่ามันอาจมีประโยชน์ที่นี่
Jeremy Stein

โบนัส: และหากคุณเกิดการเรียงลำดับประเภทวัตถุของคุณเองคุณสามารถใช้Comparableและแทนที่compareToเมธอดได้เสมอ
nabster

42

นี่คือวิธีที่คุณสามารถทำได้ด้วย Streams ของ Java 8:

mySet.stream().sorted().collect(Collectors.toList());

หรือด้วยเครื่องมือเปรียบเทียบที่กำหนดเอง:

mySet.stream().sorted(myComparator).collect(Collectors.toList());

9

ปลอดภัยเสมอที่จะใช้ตัวเปรียบเทียบหรืออินเทอร์เฟซที่เปรียบเทียบได้เพื่อจัดให้มีการดำเนินการเรียงลำดับ (ถ้าวัตถุไม่ใช่คลาส String หรือ Wrapper สำหรับชนิดข้อมูลดั้งเดิม) เป็นตัวอย่างสำหรับการใช้งานเครื่องมือเปรียบเทียบเพื่อเรียงลำดับพนักงานตามชื่อ

    List<Employees> empList = new LinkedList<Employees>(EmpSet);

    class EmployeeComparator implements Comparator<Employee> {

            public int compare(Employee e1, Employee e2) {
                return e1.getName().compareTo(e2.getName());
            }

        }

   Collections.sort(empList , new EmployeeComparator ());

เครื่องมือเปรียบเทียบมีประโยชน์เมื่อคุณจำเป็นต้องมีอัลกอริทึมการเรียงลำดับที่แตกต่างกันในวัตถุเดียวกัน (พูดชื่อ EMP เงินเดือน EMP ฯลฯ ) การเรียงลำดับโหมดเดียวสามารถทำได้โดยใช้อินเตอร์เฟสที่สามารถเปรียบเทียบได้กับวัตถุที่ต้องการ


5

ไม่มีวิธีการเดียวที่จะทำเช่นนั้นได้ ใช้สิ่งนี้:

@SuppressWarnings("unchecked")
public static <T extends Comparable> List<T> asSortedList(Collection<T> collection) {
  T[] array = collection.toArray(
    (T[])new Comparable[collection.size()]);
  Arrays.sort(array);
  return Arrays.asList(array);
}

นอกจากนี้ยังมีฟังก์ชั่น Collections.sort แต่ฉันคิดว่ามันทำในสิ่งเดียวกัน +1 ต่อไป
CookieOfFortune

1
Collections.sort รับรายการเป็นพารามิเตอร์
Jeremy Stein

3

คุณสามารถแปลงชุดเป็นArrayListที่ที่คุณสามารถจัดเรียงโดยใช้ArrayListCollections.sort(List)

นี่คือรหัส:

keySet = (Set) map.keySet();
ArrayList list = new ArrayList(keySet);     
Collections.sort(list);

3
TreeSet sortedset = new TreeSet();
sortedset.addAll(originalset);

list.addAll(sortedset);

โดย originalset = ชุดที่ไม่เรียงลำดับและ list = รายการที่จะส่งคืน


TreeSet ยังแยกรายการซึ่งอาจส่งผลให้เกิดผลลัพธ์ที่ผิดถ้าคุณไม่คิดเช่นนั้น
anthonymonori

2

@ Jeremy Stein ฉันต้องการใช้รหัสเดียวกัน เช่นกันฉันต้องการเรียงลำดับ set เป็น list ดังนั้นแทนที่จะใช้ Set I แปลงค่า set เป็น List และเรียงลำดับรายการโดยเป็นตัวแปรตัวเดียว รหัสนี้ช่วยฉัน

set.stream().sorted(Comparator.comparing(ModelClassName::sortingVariableName)).collect(Collectors.toList());

0

ฉันใช้รหัสนี้ซึ่งฉันพบว่ามีประโยชน์มากกว่าคำตอบที่ยอมรับด้านบน:

List<Thing> thingList = new ArrayList<>(thingSet);
thingList.sort((thing1, thing2) -> thing1.getName().compareToIgnoreCase(thing2.getName()));
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.