Найбільш стислий спосіб перетворення набору <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 (список).
Карл

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

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 і вище ви можете опустити параметр типу, щоб отримати ArrayListурожай: List<String> l = new ArrayList<>(listOfTopicAuthors); Найбільш стислий без використання зовнішньої бібліотеки?
Brett Duncavage

Він кине NullPointerException у випадку, якщо він listOfTopicAuthorsє нульовим.
w35l3y

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

4
за відповідь у ту ж хвилину, що і прийняту відповідь, і не отримати рахунок. +1
jayeffkay

@Adamski Я закінчую список того, хто починається з 1 замість 0, будь-який засіб?
Джек

1
@Jack: Це точно не буде. З Javadoc від java.util.List: "Списки (як масиви Java) засновані на нулі".
Адамські

@Adamski Дякую за відповідь. Я знаю, що списки мають бути і є нульовими, тому це для мене так дивно. Після перетворення мого набору в список я не можу виконувати жодних ітеративних операцій над ним: передбачати, сортувати тощо. Я отримую 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 (постачальник).

Отже, якщо нам потрібна конкретна реалізація, наприклад, 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 .


Я використовував це для перетворення a Set<Double>в a List<Double, де набір походив із методу LinkedHashMap's .keySet(). Eclipse сказав мені, що існує невідповідність типу, і що я не міг перетворити Objectна List<Double>. Не могли б ви сказати мені, чому це могло статися? Я обійшов його на кастингу, але мені було цікаво, чому це відбувається.
Ungeheuer

1
Так, оскільки розробники Java повинні використовувати все більше і більше функцій Java 8, ця відповідь краща, ніж зазначені вище 2 відповіді.
Shubham Pandey

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метод із класу Списки :

List<String> l = newArrayList(setOfAuthors);

0

не дуже впевнений, що саме ви робите через контекст свого коду, але ...

навіщо listOfTopicAuthorsвзагалі робити змінну?

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

"...." означає, що ваш набір прийшов у гру, будь то новий чи прийшов з іншого місця розташування.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.