Самый краткий способ преобразовать Set <T> в Список <T>

201

Например, я сейчас занимаюсь этим:

Set<String> setOfTopicAuthors = ....

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

Вы можете победить это?

Жак Рене Месрин
источник
2
Использование java.util.Collection: O (0)
Тим
@Carl, я должен отправить набор в сторонний интерфейс, который требует список. @Tim Я хотел бы изменить сторонний интерфейс для использования Collection.
Жак Рене Месрин
1
Я вижу; за исключением любых странных ограничений, я бы пошел с ответом Роджера. Хотя, если вы на самом деле не используете список снова, я бы пропустил назначение его чему-либо (то есть, использовал бы foo.api (новый ArrayList <String> (listOfTopicAuthors)) вместо foo.api (list)).
Карл
2
@ JacquesRenéMesrine: первая строка рассматриваемого кода вводит в заблуждение: ожидается: Set<String> setOfTopicAuthors = ....актуально:Set<String> listOfTopicAuthors = ....
realPK
Или альтернативный способ сделать то же самое List<String> list = Arrays.asList(setOfTopicAuthors.toArray(String[]::new)), подробно описано в связанном ответе.
Наман

Ответы:

432
List<String> list = new ArrayList<String>(listOfTopicAuthors);
Schildmeijer
источник
1
... и, таким образом, радикально игнорируем соглашения Java-кода: oracle.com/technetwork/java/javase/documentation/… ! :) :)
Håvard Geithus
после этого, когда я пытался получить доступ к элементу списка, он выдавал ошибку "java.lang.ClassCastException: java.lang.Integer не может быть приведен к java.lang.String" ..don; не знаю, почему ... это простой list.get (int) это все ... есть предложения?
CoDe
2
Я полагаю, что в Java 7 и выше вы можете опустить параметр type для ArrayListвыдачи: List<String> l = new ArrayList<>(listOfTopicAuthors); наиболее кратким без использования внешней библиотеки?
Бретт Данкаваж,
Он выдаст исключение NullPointerException, если значение listOfTopicAuthorsравно нулю.
w35l3y
91
List<String> l = new ArrayList<String>(listOfTopicAuthors);
Адамский
источник
4
за то, что он ответил в ту же минуту, что и принятый ответ, и не получил кредит. +1
джеффкай
@ Adamski Я получаю список, чей индекс начинается с 1, а не с 0, любое средство?
Джек,
1
@ Джек: Это определенно не будет иметь место. Из Javadoc из java.util.List: «Списки (например, массивы Java) основаны на нуле».
Адамски
@ Adamski Спасибо за ответ. Я знаю, что списки должны быть и основаны на нуле, поэтому это так странно для меня. После преобразования моего набора в список я не могу выполнить какую-либо итеративную операцию над ним, foreach, sort и т. Д. Я получаю исключение NullPointerException, однако, когда я ожидаю, что мой список ни один из элементов не является нулевым, и единственное, что я замечаю, это то, что индекс начинается с 1. Однако, если я просто создаю обычный список, индекс начинается с 0. Странно?
Джек,
1
@Jack: это звучит очень странно. Если вы разместите свой код в качестве отдельного вопроса, я уверен, что кто-то сможет вам помочь.
Адамски
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()

Нет никаких гарантий относительно типа, изменчивости, сериализуемости или безопасности потока возвращаемого списка; если требуется больший контроль над возвращенным списком, используйте 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возвращает неизменяемое представление указанного списка согласно документу . Неизменяемая коллекция представлений - это коллекция, которую нельзя изменить, а также представление резервной коллекции. Обратите внимание, что изменения в резервной коллекции все еще возможны, и если они происходят, они видны через неизменяемое представление. Но метод сборщика Collectors.unmodifiableListвозвращает действительно неизменный список в Java 10 .

akhil_mittal
источник
Я использовал это , чтобы преобразовать Set<Double>к List<Double, где множество Происходило из LinkedHashMap«S .keySet()методы. Затмение сказал мне, что было несовпадение типов, и что я не мог преобразовать из Objectв List<Double>. Не могли бы вы сказать мне, почему это могло произойти? Я обошел это путем кастинга, но мне было интересно, почему это происходит.
Ungeheuer
1
Да, поскольку разработчики Java должны использовать все больше и больше функций Java 8, этот ответ лучше, чем предыдущие 2 ответа.
Шубхам Пандей
13

Попробуйте это для Set :

Set<String> listOfTopicAuthors = .....
List<String> setList = new ArrayList<String>(listOfTopicAuthors); 

Попробуйте это для карты :

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

«....» означает, что ваш набор вступил в игру, будь то новый или пришедший из другого места.

jp093121
источник