如何将收藏转换为列表?


294

我正在TreeBidiMapApache Collections库中使用。我想对这些值进行排序doubles

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

Collection coll = themap.values();

这自然工作正常。

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

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


4
您可能希望通过直接使用某种SortedMap来避免此步骤,因此条目按所使用键的自然顺序排列。Java自己的TreeMap实现了SortedMap。
Axel Knauf,

TreeBidiMapOrderedMap,顺序应该可以。问题中要求的排序是根据值而不是键。
Vlasec

Answers:


470
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);

4
只是要注意,这两种方法有不同的副作用:将集合转换为列表,然后排序还将对原始集合进行排序;创建副本不会。
巴尼2015年

如果重复使用,这种方法会大大降低性能。请参阅我的答案,以获取一种即时运行的解决方案,其中涉及一个自定义集合。
Vlasec

当map.values()返回“内部类”集合时,这不能解决问题。编译器报告Collections.sort(List <T>)不接受Collections.sort(List <InnerClass>)。解决方案甚至是使用:List <InnerClass> list = map.values()。stream()。collect(Collectors.toList())
Pereira


33

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

我的建议是:

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

21

我相信您可以这样写:

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

解决铸造问题的更好方法
Stackee007

大!这解决了我的情况。我的map.values()返回一个“内部类”集合。编译器报告说Collections.sort(List <T>)不接受Collections.sort(List <InnerClass>)。
佩雷拉

不适用于我在android中的用例。需要最少的api 24
ansh sachdeva

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

缺少对访问ArrayList的引用?
Zach Scrivena

@扎克:嗯,好点。我知道我有理由将其标记为CW。顺便说一句,保罗的ans是那个。我不知道为什么他只有我的紫外线。
OscarRyz

4

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

怎么还不投票呢?国头的答案是错误的(就基础实现而言)。
GreenieMeanie 2014年

0

您要求的操作成本很高,请确保您不需要经常执行此操作(例如,周期执行)。

否则,您可以创建一个自定义集合。我想出了一个有你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 keySet() {
        return map.keySet();
    }
    public Multiset values() {
        return multiset;
    }
    // many more methods to be implemented, e.g. count, isEmpty etc.
}

这样,您就有了从返回的排序 。但是,如果需要将其作为列表(例如,需要类似数组的方法),则必须发明一些更复杂的东西。Multisetvalues()get(index)


keySet()并且values()是原始视图Map,因此,在修改视图时,也Map需要修改背景,您的解决方案不支持此操作
Lino

-4

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

Collections.list(Collections.enumeration(coll));
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.