วิธีการแปลงชุดเป็นรายการ?


294

ฉันใช้TreeBidiMapจากห้องสมุดApache Collections doublesฉันต้องการที่จะจัดเรียงนี้กับค่าที่มี

วิธีการของฉันคือการดึงCollectionค่าใดค่าหนึ่งโดยใช้:

Collection coll = themap.values();

ซึ่งใช้งานได้ดีตามธรรมชาติ

คำถามหลัก:ตอนนี้ฉันต้องการทราบว่าฉันสามารถแปลง / ส่ง (ไม่แน่ใจว่าสิ่งใดถูกต้อง) collลงในรายการListเพื่อให้สามารถเรียงลำดับได้หรือไม่

จากนั้นผมก็ตั้งใจจะย้ำกว่าเรียงListวัตถุที่ควรจะเป็นในการสั่งซื้อและได้รับกุญแจที่เหมาะสมจากTreeBidiMap( themap) โดยใช้themap.getKey(iterator.next())ที่ iterator doublesจะถูกกว่ารายชื่อของ


4
คุณอาจต้องการหลีกเลี่ยงขั้นตอนนี้โดยใช้ SortedMap บางชนิดโดยตรงดังนั้นรายการจึงเป็นไปตามธรรมชาติของคีย์ที่ใช้ TreeMap ของ Java เองนั้นใช้ SortedMap
Axel Knauf

TreeBidiMapคือการOrderedMapสั่งซื้อควรจะโอเค การเรียงลำดับที่ต้องการในคำถามนั้นขึ้นอยู่กับค่าไม่ใช่กุญแจ
Vlasec

คำตอบ:


470
List list = new ArrayList(coll);
Collections.sort(list);

ดังที่ Erel Segal Halevi กล่าวไว้ด้านล่างหาก coll เป็นรายการอยู่แล้วคุณสามารถข้ามขั้นตอนที่หนึ่งได้ แต่นั่นก็ขึ้นอยู่กับ internals ของ TreeBidiMap

List list;
if (coll instanceof List)
  list = (List)coll;
else
  list = new ArrayList(coll);

4
เพียงเพื่อให้ทราบว่ามีผลข้างเคียงที่แตกต่างกันของทั้งสองวิธี: การรวบรวมคอลเลกชันไปยังรายการแล้วการเรียงลำดับก็จะเรียงลำดับคอลเลกชันดั้งเดิม การสร้างสำเนาจะไม่
บาร์นีย์

วิธีการนี้จะลดประสิทธิภาพลงอย่างมากหากใช้ซ้ำ ๆ ดูคำตอบของฉันสำหรับวิธีแก้ปัญหาที่ใช้งานได้ทันทีมันเกี่ยวข้องกับการสะสม
Vlasec

สิ่งนี้ไม่ได้แก้ไขกรณีและปัญหาเมื่อ map.values ​​() ส่งคืนคอลเลกชัน "inner class" คอมไพเลอร์รายงานว่า Collections.sort (รายการ <T>) ไม่ยอมรับ Collections.sort (รายการ <InnerClass>) การแก้ปัญหาคือการใช้: List <InnerClass> list = map.values ​​(). stream (). collect (Collector.toList ())
Pereira


33

ฉันคิดว่าคำตอบของ Paul Tomblin อาจสิ้นเปลืองในกรณีที่ coll เป็นรายการอยู่แล้วเพราะจะสร้างรายการใหม่และคัดลอกองค์ประกอบทั้งหมด หาก coll ประกอบด้วย eleme หลายตัวอาจใช้เวลานาน

คำแนะนำของฉันคือ:

List list;
if (coll instanceof List)
  list = (List)coll;
else
  list = new ArrayList(coll);
Collections.sort(list);

21

ฉันเชื่อว่าคุณสามารถเขียนได้เช่น:

coll.stream().collect(Collectors.toList())

วิธีที่ดีกว่าในการรับงานหล่อ
Stackee007

ที่ดี! กรณีนี้ได้รับการแก้ไขของฉัน map.values ​​ของฉัน () ส่งคืนคอลเล็กชัน "inner class" คอมไพเลอร์รายงานว่า Collections.sort (รายการ <T>) ไม่ยอมรับ Collections.sort (รายการ <InnerClass>)
Pereira

ไม่ได้ใช้งานกับเคสของฉันใน Android ต้องมี api ขั้นต่ำ 24
ansh sachdeva

8
Collections.sort( new ArrayList( coll ) );

ไม่มีการอ้างอิงเพื่อเข้าถึง ArrayList ใช่หรือไม่
Zach Scrivena

@Zach: mmhh จุดดี ฉันรู้ว่ามีเหตุผลให้ฉันทำเครื่องหมายว่าเป็น CW BTW ans คือหนึ่ง ฉันไม่รู้ว่าทำไมเขามีแค่ UV ของฉัน
OscarRyz

4

@ Kunigami: ฉันคิดว่าคุณอาจเข้าใจผิดเกี่ยวกับnewArrayListวิธีการของ Guava มันไม่ได้ตรวจสอบว่า Iterable เป็นประเภทรายการหรือไม่และเพียงแค่คืนค่ารายการที่กำหนดตามสภาพ มันสร้างรายการใหม่เสมอ :

@GwtCompatible(serializable = true)
public static <E> ArrayList<E> newArrayList(Iterable<? extends E> elements) {
  checkNotNull(elements); // for GWT
  // Let ArrayList's sizing logic work, if possible
  return (elements instanceof Collection)
      ? new ArrayList<E>(Collections2.cast(elements))
      : newArrayList(elements.iterator());
}

วิธีนี้ไม่ได้รับการโหวตมากขึ้น? คำตอบของ Kunigami นั้นไม่ถูกต้อง (เท่าที่คิดเกี่ยวกับการใช้งานพื้นฐาน)
GreenieMeanie

0

สิ่งที่คุณร้องขอเป็นการดำเนินการที่ค่อนข้างมีค่าใช้จ่ายตรวจสอบให้แน่ใจว่าคุณไม่จำเป็นต้องทำบ่อย ๆ (เช่นในรอบ)

มิฉะนั้นคุณสามารถสร้างคอลเลกชันที่กำหนดเอง ฉันมากับคนที่มีของคุณTreeBidiMapและTreeMultisetภายใต้ประทุน ใช้งานเฉพาะสิ่งที่คุณต้องการและใส่ใจเกี่ยวกับความถูกต้องของข้อมูล

class MyCustomCollection implements Map<K, V> {
    TreeBidiMap<K, V> map;
    TreeMultiset<V> multiset;
    public V put(K key, V value) {
        removeValue(map.put(key, value));
        multiset.add(value);
    }
    public boolean remove(K key) {
        removeValue(map.remove(key));
    }
    /** removes value that was removed/replaced in map */
    private removeValue(V value) {
        if (value != null) {
            multiset.remove(value);
        }
    }
    public Set keySet() {
        return map.keySet();
    }
    public Multiset values() {
        return multiset;
    }
    // many more methods to be implemented, e.g. count, isEmpty etc.
}

วิธีนี้คุณมีเรียง กลับมาจากMultiset values()อย่างไรก็ตามหากคุณต้องการให้เป็นรายการ (เช่นคุณต้องการวิธีอาร์เรย์เหมือนget(index)) คุณจะต้องประดิษฐ์สิ่งที่ซับซ้อนมากขึ้น


keySet()และvalues()เป็น Views ไปที่ต้นฉบับMapดังนั้นเมื่อมีการแก้ไขการสำรองข้อมูลMapจำเป็นต้องแก้ไขด้วยโซลูชันของคุณไม่สนับสนุนสิ่งนี้
Lino

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