La forma más concisa de convertir un conjunto <T> en una lista <T>

201

Por ejemplo, actualmente estoy haciendo esto:

Set<String> setOfTopicAuthors = ....

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

¿Puedes vencer esto?

Jacques René Mesrine
fuente
2
Uso java.util.Collection: O (0)
Tim
@Carl, tengo que enviar el Set a una interfaz de terceros que requiere una Lista. @Tim Ojalá pudiera cambiar la interfaz de terceros para usar la Colección.
Jacques René Mesrine
1
Veo; salvo restricciones extrañas, iría con la respuesta de Roger. Sin embargo, a menos que vuelva a usar la Lista, omitiría asignarla a cualquier cosa (es decir, usar foo.api (nueva ArrayList <String> (listOfTopicAuthors)) en lugar de foo.api (lista)).
Carl
2
@ JacquesRenéMesrine: La primera línea de código en cuestión es engañosa: Esperado: Set<String> setOfTopicAuthors = ....Actual:Set<String> listOfTopicAuthors = ....
realPK
O una forma alternativa de hacer lo mismo podría ser List<String> list = Arrays.asList(setOfTopicAuthors.toArray(String[]::new)), detallada en la respuesta vinculada.
Naman

Respuestas:

432
List<String> list = new ArrayList<String>(listOfTopicAuthors);
Schildmeijer
fuente
1
... y por lo tanto desafiando radicalmente las convenciones del código Java: oracle.com/technetwork/java/javase/documentation/… ! :) :)
Håvard Geithus 01 de
después de esto cuando intenté acceder al elemento de la lista, me dio un error, "java.lang.ClassCastException: java.lang.Integer no se puede convertir a java.lang.String" ..don; no sé por qué ... es simple list.get (int) eso es todo ... alguna sugerencia?
Código de
2
Creo en Java 7 y superior, puede omitir el parámetro type para obtener ArrayList: ¿ List<String> l = new ArrayList<>(listOfTopicAuthors); Más conciso sin usar una biblioteca externa?
Brett Duncavage
Lanzará NullPointerException en caso de que listOfTopicAuthorssea ​​nulo.
w35l3y
91
List<String> l = new ArrayList<String>(listOfTopicAuthors);
Adamski
fuente
44
por responder en el mismo minuto que la respuesta aceptada y no obtener la credibilidad. +1
jayeffkay
@ Adamski Termino con una lista cuyo índice comienza en 1 en lugar de 0, ¿algún remedio?
Jack
1
@ Jack: Eso definitivamente no será el caso. Desde el Javadoc de java.util.List: "Las listas (como las matrices de Java) están basadas en cero".
Adamski
@Adamski Gracias por la respuesta. Sé que las listas deberían estar basadas en cero y por eso es tan extraño para mí. Después de convertir mi conjunto a una lista, no puedo realizar ninguna operación iterativa en cada uno de ellos, ordenar, etc. Obtengo una NullPointerException, sin embargo, cuando espero que mi lista ninguno de los elementos sea nulo, y lo único extraño que noto es que el el índice comienza en 1. Sin embargo, si solo creo una lista normal, el índice comienza en 0. ¿Extraño?
Jack
1
@ Jack: Eso suena muy raro. Si publica su código como una pregunta separada, estoy seguro de que alguien podrá ayudarlo.
Adamski
23

Teniendo en cuenta que tenemos Set<String> stringSet, podemos usar lo siguiente:

Java 10 (lista no modificable)

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

Java 8 (Listas modificables)

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

Según el documento para el métodotoList()

No hay garantías sobre el tipo, mutabilidad, serialización o seguridad de subprocesos de la Lista devuelta; Si se requiere un mayor control sobre la Lista devuelta, use toCollection (Proveedor).

Entonces, si necesitamos una implementación específica, por ejemplo ArrayList, podemos obtenerla de esta manera:

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

Java 8 (Listas no modificables)

Podemos hacer uso del Collections::unmodifiableListmétodo y ajustar la lista devuelta en ejemplos anteriores. También podemos escribir nuestro propio método personalizado como:

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

Y luego úsalo como:

List<String> stringList3 = stringSet.stream()
             .collect(ImmutableCollector.toImmutableList(ArrayList::new)); 

Otra posibilidad es hacer uso del collectingAndThenmétodo que permite realizar una transformación final antes de devolver el resultado:

    List<String> stringList4 = stringSet.stream().collect(collectingAndThen(
      toCollection(ArrayList::new),Collections::unmodifiableList));

Un punto a tener en cuenta es que el método Collections::unmodifiableListdevuelve una vista no modificable de la lista especificada, según el documento . Una colección de vistas no modificables es una colección que no se puede modificar y también es una vista de una colección de respaldo. Tenga en cuenta que los cambios en la colección de respaldo aún podrían ser posibles, y si ocurren, son visibles a través de la vista no modificable. Pero el método del recopilador Collectors.unmodifiableListdevuelve una lista verdaderamente inmutable en Java 10 .

akhil_mittal
fuente
He utilizado este para convertir una Set<Double>a una List<Double, donde el conjunto vino de un LinkedHashMap's .keySet()método. Eclipse me dijo que había una falta de coincidencia de tipos y que no podía convertir de Objecta List<Double>. ¿Podría decirme por qué puede haber sucedido esto? Lo solucioné lanzando, pero me preguntaba por qué sucede.
Ungeheuer
1
Sí, dado que los desarrolladores de Java deberían usar más y más funciones de Java 8, esta respuesta es mejor que las 2 respuestas anteriores.
Shubham Pandey
13

Prueba esto para Set :

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

Prueba esto para el mapa :

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());
Prabhakar Manthena
fuente
2

Si está utilizando Guava, importa estáticamente el newArrayListmétodo de la clase Listas :

List<String> l = newArrayList(setOfAuthors);
Andrejs
fuente
0

no estoy seguro de lo que estás haciendo exactamente a través del contexto de tu código pero ...

¿Por qué hacer la listOfTopicAuthorsvariable?

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

el "...." representa sin embargo su conjunto entró en juego, ya sea nuevo o provenga de otra ubicación.

jp093121
fuente