如何将集合转换为列表?

Posted

技术标签:

【中文标题】如何将集合转换为列表?【英文标题】:How to convert a Collection to List? 【发布时间】:2010-10-09 11:20:24 【问题描述】:

我正在使用来自Apache Collections 库的TreeBidiMap。我想对 doubles 的值进行排序。

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

Collection coll = themap.values();

这自然可以正常工作。

主要问题:我现在想知道如何将coll 转换/转换(不确定哪个正确)为List,以便对其进行排序?

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

【问题讨论】:

您可能希望通过直接使用某种 SortedMap 来避免此步骤,因此条目按所使用键的自然顺序排列。 Java 自己的 TreeMap 实现了 SortedMap。 TreeBidiMapOrderedMap,顺序应该没问题。问题中要求的排序是值,而不是键。 【参考方案1】:

Java 8 以上...

您可以使用 StreamsCollectors.toCollection() 将 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]

到 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]

到链表

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

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

到哈希集

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

【讨论】:

【参考方案2】:

使用流:

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

【讨论】:

【参考方案3】:

Java 10 引入了List#copyOf,它在保留顺序的同时返回不可修改的列表

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

【讨论】:

【参考方案4】:

您要求的操作成本很高,请确保您不需要经常执行此操作(例如在一个循环中)。

如果您需要它保持排序并且经常更新它,您可以创建一个自定义集合。例如,我想出了一个在引擎盖下有你的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

【讨论】:

keySet()values() 是原始 Map 的视图,因此当修改它们时,支持 Map 也需要修改,您的解决方案不支持此 是的,你说得对。要做到这一点,我需要至少再创建两个集合类,以确保 keySet 和 values 都受到两个集合的支持。我更新了我的答案。【参考方案5】:

我相信你可以这样写:

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

【讨论】:

绕过投射的更好方法 太棒了!这解决了我的情况。我的 map.values() 返回一个“内部类”集合。编译器报告 Collections.sort(List ) 不接受 Collections.sort(List)。 不适用于我在 android 中的用例。需要最低 api 24【参考方案6】:
Collections.sort( new ArrayList( coll ) );

【讨论】:

缺少访问 ArrayList 的引用? @Zach:嗯嗯嗯好点。我知道我有理由将其标记为 CW。顺便说一句,保罗的答案就是一个。我不知道为什么他只有我的紫外线。【参考方案7】:

这样的事情应该可以工作,调用带有集合的ArrayList constructor:

List theList = new ArrayList(coll);

【讨论】:

【参考方案8】:

这是一个次优的单线解决方案:

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

【讨论】:

【参考方案9】:

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

【讨论】:

这不是更多的投票吗? Kunigami 的回答是不正确的(就其对底层实现的假设而言)。【参考方案10】:
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);

【讨论】:

请注意,这两种方法有不同的副作用:将集合转换为列表然后排序也会对原始集合进行排序;不会创建副本。 如果重复使用,这种方法会大大降低性能。请参阅我的答案以获取即时有效的解决方案,它涉及自定义集合。 这并不能解决 map.values() 返回“内部类”集合的情况。编译器报告 Collections.sort(List ) 不接受 Collections.sort(List)。解决方案甚至是使用: List list = map.values().stream().collect(Collectors.toList())【参考方案11】:

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

我的建议是:

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

【讨论】:

以上是关于如何将集合转换为列表?的主要内容,如果未能解决你的问题,请参考以下文章

在这种情况下如何将集合转换为列表

如何将嵌套列表中的值转换为集合?

如何将字典、集合、元组列表的多列转换为列

如何通过元素的属性将集合转换/转换为另一个集合?

如何将数组列表转换为多维数组

如何在python中将集合转换为列表?