Как преобразовать коллекцию в список?
Я использую TreeBidiMap
из библиотеки Apache Collections. Я хочу отсортировать это по значениям, которые doubles
,
Мой метод состоит в том, чтобы получить Collection
из значений, использующих:
Collection coll = themap.values();
Что, естественно, отлично работает.
Основной вопрос: теперь я хочу знать, как я могу конвертировать / кастовать (не уверен, что это правильно) coll
в List
так это можно отсортировать?
Затем я намерен перебрать отсортированный List
объект, который должен быть в порядке и получить соответствующие ключи от TreeBidiMap
(themap
) с помощью themap.getKey(iterator.next())
где итератор будет над списком doubles
,
11 ответов
List list = new ArrayList(coll);
Collections.sort(list);
Как говорит Эрел Сегал Халеви ниже, если coll - это уже список, вы можете пропустить первый шаг. Но это будет зависеть от внутренних компонентов TreeBidiMap.
List list;
if (coll instanceof List)
list = (List)coll;
else
list = new ArrayList(coll);
Нечто подобное должно работать, вызывая конструктор ArrayList, который принимает коллекцию:
List theList = new ArrayList(coll);
Я считаю, что вы можете написать это так:
coll.stream().collect(Collectors.toList())
Я думаю, что ответ Пола Томблина может быть расточительным, если coll уже является списком, потому что он создаст новый список и скопирует все элементы. Если в coll содержится много элементов, это может занять много времени.
Мое предложение:
List list;
if (coll instanceof List)
list = (List)coll;
else
list = new ArrayList(coll);
Collections.sort(list);
Представлена Java 10 List#copyOf
который возвращает неизменяемый список при сохранении порядка:
List<Integer> list = List.copyOf(coll);
Java 8 и новее ...
Вы можете преобразовать Collection в любую коллекцию (например, List, Set и Queue) с помощью Streams и Collectors.toCollection () .
Рассмотрим следующий пример карты
Map<Integer, Double> map = Map.of(
1, 1015.45,
2, 8956.31,
3, 1234.86,
4, 2348.26,
5, 7351.03
);
в ArrayList
List<Double> arrayList = map.values()
.stream()
.collect(
Collectors.toCollection(ArrayList::new)
);
Выход: [7351.03, 2348.26, 1234.86, 8956.31, 1015.45]
в Sorted ArrayList (в порядке возрастания)
List<Double> arrayListSortedAsc = map.values()
.stream()
.sorted()
.collect(
Collectors.toCollection(ArrayList::new)
);
Выход: [1015.45, 1234.86, 2348.26, 7351.03, 8956.31]
в Sorted ArrayList (в порядке убывания)
List<Double> arrayListSortedDesc = map.values()
.stream()
.sorted(
(a, b) -> b.compareTo(a)
)
.collect(
Collectors.toCollection(ArrayList::new)
);
Выход: [8956.31, 7351.03, 2348.26, 1234.86, 1015.45]
в LinkedList
List<Double> linkedList = map.values()
.stream()
.collect(
Collectors.toCollection(LinkedList::new)
);
Выход: [7351.03, 2348.26, 1234.86, 8956.31, 1015.45]
в HashSet
Set<Double> hashSet = map.values()
.stream()
.collect(
Collectors.toCollection(HashSet::new)
);
Выход: [2348.26, 8956.31, 1015.45, 1234.86, 7351.03]
в PriorityQueue
PriorityQueue<Double> priorityQueue = map.values()
.stream()
.collect(
Collectors.toCollection(PriorityQueue::new)
);
Выход: [1015.45, 1234.86, 2348.26, 8956.31, 7351.03]
Справка
@Kunigami: я думаю, что вы можете ошибаться насчет Гуавы newArrayList
метод. Он не проверяет, является ли Iterable типом List, и просто возвращает заданный 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());
}
Используйте потоки:
someCollection.stream().collect(Collectors.toList())
То, что вы запрашиваете, является довольно дорогостоящей операцией, убедитесь, что вам не нужно делать это часто (например, в цикле).
В противном случае вы можете создать собственную коллекцию. Я придумал тот, который имеет ваш 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)
метод), вам придется изобрести что-то более сложное.
Вот неоптимальное решение в виде однострочника:
Collections.list(Collections.enumeration(coll));