Как создать поток <String[]> с одним элементом с Stream.of?

Использование Stream.of для создания общих потоков очень удобно, но что если я хочу создать Stream<String[]> только из одного элемента?

Допустим, у меня есть:

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

Затем Stream.of(tropicalFruits, fruits) создает Stream<String[]> из двух элементов. Как я могу добиться того же для потока одного элемента? Если я попробую:

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

Я получил:

Ошибка: несовместимые типы: переменная вывода T имеет несовместимые границы
ограничения равенства: java.lang.String[]
нижние границы: java.lang.String

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

Я гуглил это и искал в SO, но я ничего не получил. Мне кажется, что это не очень необычная или эзотерическая проблема, поэтому удивительно, что я не получил никаких ответов (или я не ищу правильные ключевые слова).

Ответ 1

Решение

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

или

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

объяснение

Чтобы создать Stream<T>, Stream.of принимает либо T либо T...
Параметр T[] отлично применяется ко второй подписи.
Поэтому передача String[] вызывает Stream.of(String...).

Чтобы изменить это поведение, нам нужно предоставить дополнительную информацию о T (1) или определить его более четко (= однозначно) (2).

Мне пришло в голову две идеи:

  1. Чтобы указать аргумент типа метода явно использовать первую подпись.
    Stream.<String[]>of(new String[]{}) создаст Stream<String[]>.
  2. Для того, чтобы обернуть T[] значение в T[][] массива, чтобы использовать вторую подпись.
    Stream.of(new String[][]{}) создаст Stream<String[]>.

Ответ 2

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

вызывает метод var-arg Stream.of.

Я могу подумать об этом обходном пути:

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

Или вы можете вызвать метод var-args несколько иначе:

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

Ответ 3

Вызывая Stream#of с одним T[], Java по умолчанию использует метод vararg factory, создавая Stream<T> а не Stream<T[]>. Чтобы создать Stream<T[]> с помощью одного элемента, вы можете создать Stream<T[]> с несколькими элементами и limit(1) вызова limit(1) или использовать фиктивный массив для второго элемента:

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

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