将Set <T>转换为List <T>的最简洁方法


201

例如,我目前正在这样做:

Set<String> setOfTopicAuthors = ....

List<String> list = Arrays.asList( 
    setOfTopicAuthors.toArray( new String[0] ) );

你能打败这个吗?


2
使用java.util.Collection:O(0)
Tim

@Carl,我必须将Set提交到需要列表的第三方界面。@Tim我希望我可以更改3rd Party界面以使用Collection。
雅克·雷内·梅斯林(JacquesRenéMesrine)2010年

1
我懂了; 除非有任何奇怪的限制,否则我将接受罗杰的回答。但是,除非您再次实际使用List,否则我将跳过将其分配给任何内容的操作(即,使用foo.api(new ArrayList <String>(listOfTopicAuthors))而不是foo.api(list))。
卡尔2010年

2
@JacquesRenéMesrine:有问题的第一行代码具有误导性:预期:Set<String> setOfTopicAuthors = ....实际:Set<String> listOfTopicAuthors = ....
realPK

List<String> list = Arrays.asList(setOfTopicAuthors.toArray(String[]::new))在链接的答案中有详细说明的另一种方法。
纳曼

Answers:


432
List<String> list = new ArrayList<String>(listOfTopicAuthors);

1
...从而从根本上违反Java代码约定:oracle.com/technetwork/java/javase/documentation / ...!:) :)
哈佛Geithus

此后,当我尝试访问列表元素时,它给我错误,“ java.lang.ClassCastException:java.lang.Integer无法转换为java.lang.String” ..don;不知道为什么。.这就是简单的list.get (int)就是...任何建议吗?
2014年

2
我相信在Java 7及更高版本中,您可以将type参数省略为ArrayListyield: List<String> l = new ArrayList<>(listOfTopicAuthors); 最简洁而不使用外部库?
Brett Duncavage 2014年

如果listOfTopicAuthors为null ,它将抛出NullPointerException 。
w35l3y

91
List<String> l = new ArrayList<String>(listOfTopicAuthors);

4
在与接受答案的同一分钟内回答,却没有得到信任。+1
jayeffkay 2015年

@Adamski我最终得到一个列表,该列表的索引从1而不是0开始,有什么补救方法吗?
杰克

1
@杰克:绝对不是这样。来自Javadoc,来自java.util.List:“列表(如Java数组)是从零开始的。”
亚当斯基

@Adamski感谢您的回复。我知道列表应该是并且基于零,这就是为什么这对我来说很奇怪。将集合转换为列表后,无法对它进行foreach,sort等的任何迭代操作。我得到了NullPointerException,但是当我期望列表中的所有元素都不为null时,我注意到的唯一奇怪的是索引从1开始。但是,如果我仅创建一个普通列表,则索引从0开始。
杰克

1
@杰克:听起来很奇怪。如果您将代码作为一个单独的问题发布,我敢肯定有人会帮助您。
亚当斯基

23

考虑到我们Set<String> stringSet可以使用以下方法:

Java 10(无法修改的列表)

List<String> strList = stringSet.stream().collect(Collectors.toUnmodifiableList());

Java 8(可修改列表)

import static java.util.stream.Collectors.*;
List<String> stringList1 = stringSet.stream().collect(toList());

根据该方法的文档toList()

不保证返回的List的类型,可变性,可序列化性或线程安全性;如果需要对返回的List进行更多控制,请使用toCollection(Supplier)。

因此,如果我们需要特定的实现,例如ArrayList,可以通过以下方式获取它:

List<String> stringList2 = stringSet.stream().
                              collect(toCollection(ArrayList::new));

Java 8(不可修改的列表)

我们可以利用Collections::unmodifiableListmethod并包装前面示例中返回的列表。我们还可以将自己的自定义方法编写为:

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返回指定列表的不可修改视图,按照文档。不可修改的视图集合是不可修改的集合,并且也是支持集合的视图。请注意,对后备集合的更改仍然可能,并且,如果发生更改,则可以通过不可修改的视图看到它们。但是收集器方法Collectors.unmodifiableListJava 10中返回真正不变的列表。


我用它将a转换Set<Double>List<Double,其中集合来自LinkedHashMap.keySet()方法。Eclipse告诉我,类型不匹配,并且我无法从转换ObjectList<Double>。你能告诉我为什么会这样吗?我通过投射解决了它,但是我想知道为什么会发生。
Ungeheuer

1
是的,因为Java开发人员应该使用越来越多的Java 8功能,所以这个答案比以上两个答案要好。
Shubham Pandey

13

试试这个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());

2

如果使用的是Guava,newArrayList则从Lists类静态导入方法:

List<String> l = newArrayList(setOfAuthors);

0

不确定通过代码的上下文究竟在做什么,但是...

为什么要listOfTopicAuthors全部设置变量?

List<String> list = Arrays.asList((....).toArray( new String[0] ) );

“ ....”代表您的设备是否起作用,无论它是新的还是来自其他位置。

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.