Làm cách nào để chuyển đổi Bộ sưu tập thành Danh sách?


294

Tôi đang sử dụng TreeBidiMaptừ thư viện Bộ sưu tập Apache . Tôi muốn sắp xếp cái này theo các giá trị doubles.

Phương pháp của tôi là lấy một Collectiontrong các giá trị bằng cách sử dụng:

Collection coll = themap.values();

Mà tự nhiên hoạt động tốt.

Câu hỏi chính: Bây giờ tôi muốn biết làm thế nào tôi có thể chuyển đổi / truyền (không chắc cái nào đúng) collthành mộtList cái để nó có thể được sắp xếp?

Sau đó, tôi dự định lặp lại Listđối tượng đã sắp xếp , thứ tự sẽ theo thứ tự và nhận các khóa thích hợp từ TreeBidiMap( themap) bằng cách sử dụng themap.getKey(iterator.next())nơi trình lặp sẽ nằm trong danh sách doubles.


4
Bạn có thể muốn tránh bước này bằng cách trực tiếp sử dụng một số loại Sắp xếp Bản đồ, vì vậy các mục nhập theo thứ tự tự nhiên của các khóa được sử dụng. TreeMap riêng của Java thực hiện SortedMap.
Axel Knauf

TreeBidiMaplà một OrderedMap, thứ tự nên ok. Việc sắp xếp cần thiết trong câu hỏi là trên các giá trị, không phải trên các khóa.
Vlasec

Câu trả lời:


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

Như Erel Segal Halevi nói dưới đây, nếu coll đã là một danh sách, bạn có thể bỏ qua bước một. Nhưng điều đó sẽ phụ thuộc vào nội bộ của TreeBidiMap.

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

4
Chỉ cần lưu ý rằng có hai tác dụng phụ khác nhau cho hai cách tiếp cận: chuyển bộ sưu tập vào danh sách và sau đó sắp xếp cũng sẽ sắp xếp bộ sưu tập gốc; tạo một bản sao sẽ không.
Barney

Cách tiếp cận này làm giảm hiệu suất rất nhiều nếu sử dụng nhiều lần. Xem câu trả lời của tôi cho một giải pháp hoạt động nhanh chóng, nó liên quan đến một bộ sưu tập tùy chỉnh.
Vlasec

Điều này không giải quyết trường hợp khi map.values ​​() trả về bộ sưu tập "lớp bên trong". Trình biên dịch báo cáo rằng Collections.sort (Danh sách <T>) không chấp nhận Collections.sort (Danh sách <InternalClass>). Giải pháp thậm chí là sử dụng: List <InsideClass> list = map.values ​​(). Stream (). Collection (Collector.toList ())
Pereira

92

Một cái gì đó như thế này sẽ hoạt động, gọi hàm tạo ArrayList có Bộ sưu tập:

List theList = new ArrayList(coll);

Đẹp và đơn giản.
James Gawron

33

Tôi nghĩ rằng câu trả lời của Paul Tomblin có thể lãng phí trong trường hợp coll đã là một danh sách, bởi vì nó sẽ tạo ra một danh sách mới và sao chép tất cả các yếu tố. Nếu coll chứa nhiều elemeents, điều này có thể mất nhiều thời gian.

Đề nghị của tôi là:

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

21

Tôi tin rằng bạn có thể viết nó như vậy:

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

Cách tốt hơn để đi vòng quanh
Stackee007

Tuyệt quá! Điều này đã giải quyết trường hợp của tôi. Map.values ​​() của tôi trả về một bộ sưu tập "lớp bên trong". Trình biên dịch đã báo cáo rằng Collections.sort (Danh sách <T>) không chấp nhận Collections.sort (Danh sách <InternalClass>).
Pereira

đã không làm việc cho trường hợp sử dụng của tôi trong Android. yêu cầu tối thiểu 24
ansh sachdeva

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

Thiếu tham chiếu để truy cập ArrayList?
Zach Scrivena

@Zach: mmhh điểm tốt. Tôi biết có một lý do để tôi đánh dấu đây là CW. Ans của BTW Paul là một. Tôi không biết tại sao anh ta chỉ có uv của tôi.
OscarRyz

4

@Kunigami: Tôi nghĩ bạn có thể nhầm về newArrayListphương pháp của Guava . Nó không kiểm tra xem Iterable có phải là loại Danh sách hay không và chỉ trả về Danh sách đã cho. Nó luôn tạo ra một danh sách mới:

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

Làm thế nào là điều này không được bình chọn nhiều hơn? Câu trả lời của Kunigami là không chính xác (theo như giả định về việc triển khai cơ bản).
GreenieMeanie

0

Những gì bạn yêu cầu là một hoạt động khá tốn kém, hãy chắc chắn rằng bạn không cần phải thực hiện thường xuyên (ví dụ: trong một chu kỳ).

Nếu không, bạn có thể tạo một bộ sưu tập tùy chỉnh. Tôi đã đưa ra một trong đó có của bạn TreeBidiMapTreeMultisetdưới mui xe. Chỉ thực hiện những gì bạn cần và quan tâm đến tính toàn vẹn dữ liệu.

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.
}

Bằng cách này, bạn có một sắp xếp Multiset trở về từ values(). Tuy nhiên, nếu bạn cần nó là một danh sách (ví dụ: bạn cần get(index)phương thức giống như mảng ), bạn sẽ phải phát minh ra thứ gì đó phức tạp hơn.


keySet()values()là Chế độ xem so với bản gốc Map, vì vậy khi chúng được sửa đổi, phần sao lưu cũng Mapcần được sửa đổi, giải pháp của bạn không hỗ trợ điều này
Lino

-4

Đây là một giải pháp tối ưu dưới dạng một lớp lót:

Collections.list(Collections.enumeration(coll));
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.