java java-8 java-stream variadic-functions type-inference

java - ¿Cómo puedo crear un Stream<String[]> con solo un elemento con Stream.of?



java-8 java-stream (3)

Usar Stream.of para crear flujos genéricos es muy conveniente, pero ¿qué Stream.of si deseo crear un Stream<String[]> de un solo elemento?

Digamos que tengo:

String[] tropicalFruits = new String[] {"pineapple", "banana", "mango"}; String[] fruits = new String[] {"melon", "peach", "apple"};

Luego, Stream.of(tropicalFruits, fruits) produce un Stream<String[]> de dos elementos. ¿Cómo puedo lograr lo mismo para un flujo de un solo elemento? Si lo intento

Stream<String[]> fruittyStream = Stream.of(tropicalFruits);

Yo obtengo:

Error: tipos incompatibles: la variable de inferencia T tiene límites incompatibles
restricciones de igualdad: java.lang.String[]
límites inferiores: java.lang.String

Stream<String[]> fruittyStream = Stream.of(fruits); ^---------------^

He buscado en Google para esto y busqué en SO pero no tengo nada. Me parece que no es un problema muy inusual o esoetérico, por lo que es sorprendente que no haya recibido ninguna respuesta (o no estoy buscando con las palabras clave adecuadas).


Solución

Stream<String[]> stream = Stream.<String[]>of(tropicalFruits);

o

Stream<String[]> stream = Stream.of(new String[][]{tropicalFruits});

Explicación

Para producir un Stream<T> , Stream.of toma T o T...
Un parámetro T[] se aplica perfectamente a la segunda firma.
Por lo tanto, al pasar un String[] invoca la Stream.of(String...) .

Para cambiar este comportamiento, necesitamos proporcionar alguna información adicional sobre T (1) o definirla más claramente (= sin ambigüedad) (2).

Hay dos ideas que vinieron a mi mente:

  1. Para especificar un argumento de tipo del método explícitamente para usar la primera firma.
    Stream.<String[]>of(new String[]{}) producirá un Stream<String[]> .
  2. Para envolver un valor T[] en una matriz T[][] para usar la segunda firma.
    Stream.of(new String[][]{}) producirá un Stream<String[]> .

Al llamar a Stream#of con una sola T[] , Java T... predeterminada el T... , creando un Stream<T> lugar de un Stream<T[]> . Para crear un Stream<T[]> con un solo elemento, puede crear un Stream<T[]> con múltiples elementos y un limit(1) llamadas limit(1) , o usar una matriz ficticia para el segundo elemento:

Stream<String[]> stream = Stream.of(tropicalFruits, fruits).limit(1); Stream<String[]> stream = Stream.of(tropicalFruits, new String[] {});


This Stream<String[]> fruittyStream = Stream.of(tropicalFruits);

llama al método var-arg de Stream.of .

Puedo pensar en esta solución:

List<String> list = Arrays.asList("one"); Stream.of(list) .map(x -> x.toArray(new String[1]));

O puedes llamar al método var-args un poco diferente:

Stream.of(tropicalFruits, null) .filter(Objects::nonNull) .forEach(x -> System.out.println(Arrays.toString(x)));