将 Set<T> 转换为 List<T> 的最简洁方法
Posted
技术标签:
【中文标题】将 Set<T> 转换为 List<T> 的最简洁方法【英文标题】:Most concise way to convert a Set<T> to a List<T> 【发布时间】:2011-01-20 03:27:32 【问题描述】:例如,我目前正在这样做:
Set<String> setOfTopicAuthors = ....
List<String> list = Arrays.asList(
setOfTopicAuthors.toArray( new String[0] ) );
你能打败这个吗?
【问题讨论】:
使用java.util.Collection
: O(0)
@Carl,我必须将 Set 提交到需要列表的第 3 方界面。 @Tim 我希望我可以将第 3 方界面更改为使用 Collection。
我明白了;除非有任何奇怪的限制,否则我会接受罗杰的回答。不过,除非您实际上再次使用 List,否则我会跳过将其分配给任何东西(即,使用 foo.api(new ArrayListSet<String> setOfTopicAuthors = ....
实际:Set<String> listOfTopicAuthors = ....
或者另一种方法可以是List<String> list = Arrays.asList(setOfTopicAuthors.toArray(String[]::new))
,在链接的答案中有详细说明。
【参考方案1】:
List<String> list = new ArrayList<String>(listOfTopicAuthors);
【讨论】:
... 从而彻底违反 Java 代码约定:oracle.com/technetwork/java/javase/documentation/…! :) :) 在此之后,当我尝试访问列表元素时,它给了我错误,“java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String” ..don;t know为什么......它很简单 list.get(int) 就是这样......有什么建议吗? 我相信在 Java 7 及以上版本中你可以将类型参数省略为ArrayList
yielding: List<String> l = new ArrayList<>(listOfTopicAuthors);
最简洁不使用外部库?
如果listOfTopicAuthors
为空,它会抛出NullPointerException。【参考方案2】:
List<String> l = new ArrayList<String>(listOfTopicAuthors);
【讨论】:
在与接受的答案相同的分钟内回答并且没有获得信任。 +1 @Adamski 我最终得到了一个索引从 1 而不是 0 开始的列表,有什么补救措施吗? @Jack:绝对不会这样。来自 java.util.List 的 Javadoc:“列表(如 Java 数组)是从零开始的。” @Adamski 感谢您的回复。我知道列表应该并且是基于零的,这就是为什么这对我来说如此奇怪。将我的集合转换为列表后,我无法对其执行任何迭代操作 foreach、排序等。我得到一个 NullPointerException,但是当我期望我的列表没有任何元素为空时,我注意到的唯一奇怪的是索引从 1 开始。但是,如果我只是创建一个普通列表,则索引从 0 开始。奇怪吗? @Jack:这听起来很奇怪。如果您将代码作为单独的问题发布,我相信有人可以帮助您。【参考方案3】:考虑到我们有Set<String> stringSet
,我们可以使用以下内容:
纯 Java
List<String> strList = new ArrayList<>(stringSet);
番石榴
List<String> strList = Lists.newArrayList(stringSet);
Apache Commons
List<String> strList = new ArrayList<>();
CollectionUtils.addAll(strList, stringSet);
Java 10(不可修改列表)
List<String> strList = List.copyOf(stringSet);
List<String> strList = stringSet.stream().collect(Collectors.toUnmodifiableList());
Java 8(可修改列表)
import static java.util.stream.Collectors.*;
List<String> stringList1 = stringSet.stream().collect(toList());
按照doc的方法toList()
不保证类型、可变性、可序列化或 返回列表的线程安全;如果对退货有更多的控制权 列表是必需的,使用 toCollection(Supplier)。
因此,如果我们需要特定的实现,例如ArrayList
我们可以这样搞定:
List<String> stringList2 = stringSet.stream().
collect(toCollection(ArrayList::new));
Java 8(不可修改的列表)
我们可以利用Collections::unmodifiableList
方法包装前面例子中返回的列表。我们也可以编写自己的自定义方法:
class ImmutableCollector
public static <T> Collector<T, List<T>, List<T>> toImmutableList(Supplier<List<T>> supplier)
return Collector.of( supplier, List::add, (left, right) ->
left.addAll(right);
return left;
, Collections::unmodifiableList);
然后将其用作:
List<String> stringList3 = stringSet.stream()
.collect(ImmutableCollector.toImmutableList(ArrayList::new));
另一种可能性是使用collectingAndThen
方法,该方法允许在返回结果之前进行一些最终转换:
List<String> stringList4 = stringSet.stream().collect(collectingAndThen(
toCollection(ArrayList::new),Collections::unmodifiableList));
需要注意的一点是,Collections::unmodifiableList
方法根据doc 返回指定列表的不可修改视图。不可修改的视图集合是不可修改的集合,也是支持集合的视图。请注意,对支持集合的更改可能仍然是可能的,并且如果发生更改,它们将通过不可修改的视图可见。但是收集器方法 Collectors.unmodifiableList
在 Java 10 中返回真正不可变的列表。
【讨论】:
我用它来将Set<Double>
转换为List<Double
,其中集合来自LinkedHashMap
的.keySet()
方法。 Eclipse 告诉我存在类型不匹配,并且我无法从 Object
转换为 List<Double>
。你能告诉我为什么会发生这种情况吗?我通过强制转换解决了这个问题,但我想知道为什么会这样。
是的,既然Java开发者应该使用越来越多的Java 8特性,这个答案比上面2个答案要好。【参考方案4】:
试试这个Set:
Set<String> listOfTopicAuthors = .....
List<String> setList = new ArrayList<String>(listOfTopicAuthors);
试试这个Map:
Map<String, String> listOfTopicAuthors = .....
// List of values:
List<String> mapValueList = new ArrayList<String>(listOfTopicAuthors.values());
// List of keys:
List<String> mapKeyList = new ArrayList<String>(listOfTopicAuthors.KeySet());
【讨论】:
【参考方案5】:如果您使用 Guava,则从 Lists 类静态导入 newArrayList
方法:
List<String> l = newArrayList(setOfAuthors);
【讨论】:
【参考方案6】:不太确定您通过代码的上下文到底在做什么,但是...
为什么要设置listOfTopicAuthors
变量?
List<String> list = Arrays.asList((....).toArray( new String[0] ) );
“....”代表您的系列如何发挥作用,无论它是新的还是来自其他位置。
【讨论】:
以上是关于将 Set<T> 转换为 List<T> 的最简洁方法的主要内容,如果未能解决你的问题,请参考以下文章
如何将通用 List<T> 转换为基于接口的 List<T>