我正在使用这段代码将一个Set转换为一个List:

Map<String, List<String>> mainMap = new HashMap<>();

for (int i=0; i < something.size(); i++) {
  Set<String> set = getSet(...); //returns different result each time
  List<String> listOfNames = new ArrayList<>(set);
  mainMap.put(differentKeyName, listOfNames);
}

我希望避免在循环的每次迭代中创建一个新列表。这可能吗?


当前回答

Java 8提供了使用流的选项,你可以从Set<String> setString中获得一个列表为:

List<String> stringList = setString.stream().collect(Collectors.toList());

尽管内部实现现在提供了一个ArrayList实例:

public static <T>
    Collector<T, ?, List<T>> toList() {
        return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
                                   (left, right) -> { left.addAll(right); return left; },
                                   CH_ID);
    }

但是JDK并不能保证它。如本文所述:

没有对类型、可变性、可序列化性或 返回List的线程安全;如果更多的控制返回 需要清单,使用收集(供应商)。

如果你想确保总是,那么你可以请求一个实例,具体为:

List<String> stringArrayList = setString.stream()
                     .collect(Collectors.toCollection(ArrayList::new));

其他回答

为了完整起见……

假设您确实希望将Map值视为列表,但希望避免每次都将Set复制到列表中。

例如,可能您调用了一个创建Set的库函数,但是您将Map<String, List<String>>结果传递给了一个只接受Map<String, List<String>>的库函数(设计很差,但不是您能控制的),尽管您知道它对列表所做的操作同样适用于任何Collection(因此也适用于任何Set)。出于某种原因,您需要避免将每个Set复制到List所带来的速度/内存开销。

在这种特殊情况下,根据库函数需要从列表中获得的行为(可能是不可知的),您可以在每个Set上创建一个List视图。注意,这本质上是不安全的(因为每个List中的库函数需求可能会在您不知情的情况下发生变化),因此应该采用另一种解决方案。但你可以这样做。

您将创建一个实现List接口的类,在构造函数中接受一个Set并将该Set赋值给一个字段,然后使用该内部Set来实现List API(在可能和需要的范围内)。

请注意,如果不将元素存储为List,您将无法模仿某些List行为,而某些行为只能部分模仿。同样,这个类通常不是list的安全替代品。特别是,如果您知道用例需要与索引相关的操作或MUTATING List,那么这种方法很快就会失败。

public class ListViewOfSet<U> implements List<U> {
    private final Set<U> wrappedSet;
    public ListViewOfSet(Set<U> setToWrap) { this.wrappedSet = setToWrap; }

    @Override public int size() { return this.wrappedSet.size(); }
    @Override public boolean isEmpty() { return this.wrappedSet.isEmpty(); }
    @Override public boolean contains(Object o) { return this.wrappedSet.contains(o); }
    @Override public java.util.Iterator<U> iterator() { return this.wrappedSet.iterator(); }
    @Override public Object[] toArray() { return this.wrappedSet.toArray(); }
    @Override public <T> T[] toArray(T[] ts) { return this.wrappedSet.toArray(ts); }
    @Override public boolean add(U e) { return this.wrappedSet.add(e); }
    @Override public boolean remove(Object o) { return this.wrappedSet.remove(o); }
    @Override public boolean containsAll(Collection<?> clctn) { return this.wrappedSet.containsAll(clctn); }
    @Override public boolean addAll(Collection<? extends U> clctn) { return this.wrappedSet.addAll(clctn); }
    @Override public boolean addAll(int i, Collection<? extends U> clctn) { throw new UnsupportedOperationException(); }
    @Override public boolean removeAll(Collection<?> clctn) { return this.wrappedSet.removeAll(clctn); }
    @Override public boolean retainAll(Collection<?> clctn) { return this.wrappedSet.retainAll(clctn); }
    @Override public void clear() { this.wrappedSet.clear(); }
    @Override public U get(int i) { throw new UnsupportedOperationException(); }
    @Override public U set(int i, U e) { throw new UnsupportedOperationException(); }
    @Override public void add(int i, U e) { throw new UnsupportedOperationException(); }
    @Override public U remove(int i) { throw new UnsupportedOperationException(); }
    @Override public int indexOf(Object o) { throw new UnsupportedOperationException(); }
    @Override public int lastIndexOf(Object o) { throw new UnsupportedOperationException(); }
    @Override public ListIterator<U> listIterator() { throw new UnsupportedOperationException(); }
    @Override public ListIterator<U> listIterator(int i) { throw new UnsupportedOperationException(); }
    @Override public List<U> subList(int i, int i1) { throw new UnsupportedOperationException(); }
}

...
Set<String> set = getSet(...);
ListViewOfSet<String> listOfNames = new ListViewOfSet<>(set);
...

您可以使用以下一行更改:toArray(新对象(set.size ())))

Map<String, List> mainMap = new HashMap<String, List>();

for(int i=0; i<something.size(); i++){
  Set set = getSet(...); 
  mainMap.put(differentKeyName, Arrays.asList(set.toArray(new Object[set.size()])));
}  

我发现这工作很好,有用的从一个集合创建一个列表。

ArrayList < String > L1 = new ArrayList < String > ();
L1.addAll(ActualMap.keySet());
for (String x: L1) {
    System.out.println(x.toString());
}

最简单的解决方案

我想要一种非常快速的方法将我的set转换为List并返回它,所以在一行中我做到了

 return new ArrayList<Long>(mySetVariable);

我创建一个简单的静态方法:

public static <U> List<U> convertSetToList(Set<U> set)
{
    return new ArrayList<U>(set);
}

... 或者如果你想设置列表的类型,你可以使用:

public static <U, L extends List<U>> List<U> convertSetToList(Set<U> set, Class<L> clazz) throws InstantiationException, IllegalAccessException
{
    L list = clazz.newInstance();
    list.addAll(set);
    return list;
}