Как преобразовать коллекцию в список? - PullRequest
257 голосов
/ 24 февраля 2009

Я использую TreeBidiMap из библиотеки Apache Collections . Я хочу отсортировать это по значениям, которые doubles.

Мой метод - получить Collection значений, используя:

Collection coll = themap.values();

Что, естественно, прекрасно работает.

Основной вопрос: Теперь я хочу узнать, как я могу преобразовать / привести (не уверен, что это правильно) coll в List, чтобы его можно было отсортировать?

Затем я собираюсь перебрать отсортированный объект List, который должен быть в порядке, и получить соответствующие ключи от TreeBidiMap (themap), используя themap.getKey(iterator.next()), где итератор будет над списком doubles.

Ответы [ 8 ]

433 голосов
/ 24 февраля 2009
List list = new ArrayList(coll);
Collections.sort(list);

Как говорит Эрел Сигал Халеви ниже, если coll уже список, вы можете пропустить первый шаг. Но это будет зависеть от внутренних компонентов TreeBidiMap.

List list;
if (coll instanceof List)
  list = (List)coll;
else
  list = new ArrayList(coll);
84 голосов
/ 24 февраля 2009

Как-то так должно работать, вызывая конструктор ArrayList , который принимает коллекцию:

List theList = new ArrayList(coll);
32 голосов
/ 24 июля 2011

Я думаю, что ответ Пола Томблина может быть расточительным, если coll - это уже список, потому что он создаст новый список и скопирует все элементы. Если в coll содержится много элементов, это может занять много времени.

Мое предложение:

List list;
if (coll instanceof List)
  list = (List)coll;
else
  list = new ArrayList(coll);
Collections.sort(list);
14 голосов
/ 24 августа 2017

Полагаю, вы можете написать это так:

coll.stream().collect(Collectors.toList())
7 голосов
/ 24 февраля 2009
Collections.sort( new ArrayList( coll ) );
4 голосов
/ 09 января 2014

@ Кунигами: Я думаю, вы можете ошибаться в методе newArrayList Гуавы. Он не проверяет, является ли Iterable типом List, и просто возвращает данный список как есть. Он всегда создает новый список:

@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());
}
1 голос
/ 28 мая 2015

То, что вы запрашиваете, является довольно дорогостоящей операцией, убедитесь, что вам не нужно делать это часто (например, в цикле).

В противном случае вы можете создать собственную коллекцию. Я придумал тот, у которого под капотом твои 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), подобный массиву), вам придется изобрести что-то более сложное.

0 голосов
/ 29 июля 2014

Вот неоптимальное решение в виде однострочника:

Collections.list(Collections.enumeration(coll));
...