如何将集合转换为列表?

我使用的是Apache集合库中的TreeBidiMap。我想对doubles的值进行排序。

我的方法是使用以下方法检索值的Collection:

Collection coll = themap.values();

这很正常。

我现在想知道如何将/cast(不确定哪个是正确的)coll转换为List,以便它可以排序?

然后,我打算遍历已排序的List对象,该对象应该是有序的,并使用themap.getKey(iterator.next())TreeBidiMap (themap)中获取适当的键,其中迭代器将遍历doubles的列表。

611168 次浏览
List list = new ArrayList(coll);
Collections.sort(list);

正如Erel Segal Halevi在下面所说的,如果coll已经是一个列表,您可以跳过第一步。但这取决于TreeBidiMap的内部结构。

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

类似这样的方法应该可以工作,调用接受Collection的ArrayList构造函数:

List theList = new ArrayList(coll);
Collections.sort( new ArrayList( coll ) );

我认为Paul Tomblin的答案在coll已经是一个列表的情况下可能是浪费的,因为它将创建一个新的列表并复制所有元素。如果coll包含很多元素,这可能需要很长时间。

我的建议是:

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

@Kunigami:我认为你可能误解了Guava的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());
}

下面是一个次优解决方案:

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

你的要求是一个相当昂贵的操作,确保你不需要经常这样做(例如在一个周期)。

如果您需要它保持排序并经常更新它,您可以创建一个自定义集合。例如,我想出了一个有你的TreeBidiMapTreeMultiset在引擎盖下。只实现您需要的并关心数据完整性。

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<K> keySet() {
return Collections.unmodifiableSet(map.keySet());
}
public Collection<V> values() {
return Collections.unmodifiableCollection(multiset);
}
// many more methods to be implemented, e.g. count, isEmpty etc.
// but these are fairly simple
}

这样,你就从values()返回了一个排序 Multiset。然而,如果你需要它是一个列表(例如,你需要类似数组的get(index)方法),你就需要更复杂的东西。

为简洁起见,我只返回不可修改的集合。@Lino提到的是正确的,修改keySetvalues集合会使它不一致。我不知道有什么一致的方法可以使values可变,但如果keySet使用了上面MyCustomCollection类中的remove方法,它就可以支持remove

我相信你可以这样写:

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

Java 10引入了List#copyOf,它在保留顺序的同时返回无法改变的列表:

List<Integer> list = List.copyOf(coll);

使用流:

someCollection.stream().collect(Collectors.toList())

Java 8开始…

你可以使用Streams and collections . tocollection ()将Collection转换为任何Collection(即List, Set和Queue)。

考虑下面的示例地图

Map<Integer, Double> map = Map.of(
1, 1015.45,
2, 8956.31,
3, 1234.86,
4, 2348.26,
5, 7351.03
);

对数组列表

List<Double> arrayList = map.values()
.stream()
.collect(
Collectors.toCollection(ArrayList::new)
);

输出:[7351.03,2348.26,1234.86,8956.31,1015.45]

排序数组列表(升序)

List<Double> arrayListSortedAsc = map.values()
.stream()
.sorted()
.collect(
Collectors.toCollection(ArrayList::new)
);

输出:[1015.45,1234.86,2348.26,7351.03,8956.31]

排序数组列表(降序)

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]

到链表

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]

参考

Java - Package Java .util.stream

Java - Package Java .util