Печать букв от А до Я с использованием потока Java

У меня есть этот код, но он дает мне ошибку:

Несоответствие типов: невозможно преобразовать из типа int в символ

Stream.iterate('a', i -> i + 1).limit(26).forEach(System.out::println);

Хотя хорошо написать int я = 'a';

Я знаю, что могу написать так, но это кажется слишком большим количеством кода для простой задачи.

Stream.iterate('a', i -> (char)(i + 1)).limit(26).forEach(System.out::println);

Почему вывод типа Java терпит неудачу?

Ответы

Ответ 1

Причина, по которой i → я + 1 не компилируется, состоит в том, что вы пытаетесь неявно преобразовать int в Character который компилятор не может сделать сам по себе.

Другими словами, вы можете думать о Stream.iterate('a', я → я + 1) как:

Stream.iterate('a', (Character i) -> {
       int i1 = i + 1;  
       return i1; // not possible 
});

Как вы заметили, явное приведение к char решает это:

Stream.iterate('a', i -> (char)(i + 1))...

Кстати, это лучше сделать как:

IntStream.rangeClosed('a', 'z').forEach(c -> System.out.println((char)c));

Это лучше, потому что:

  1. Никаких накладных расходов на бокс, следовательно, более эффективный
  2. если бы вы остановились, скажем, на букве h с использованием iterate вам пришлось бы делать больше обработки мозга, чем просто вводить h в качестве верхней границы в rangeClosed потому что вам нужно было бы найти число для усечения бесконечного потока.
  3. Наряду с боксом iterate генерирует бесконечный поток, который в этом конкретном случае имеет больше накладных расходов, чем конечный с rangeClosed. Кроме того, гораздо проще запускать IntStream.rangeClosed параллельно, не то, что вы хотите в данном конкретном случае, а то, о чем следует помнить. Вот несколько рассуждений о Генераторах как источниках Брайана Гетца.

так далее...

Ответ 2

Как насчет просто:

Stream.iterate('a', i -> ++i).limit(26).forEach(System.out::println);

i → я + 1 не работает, потому что i является Character а i + 1 вызывает неявное сужающее преобразование (JLS 5.1.3), что недопустимо. Вы можете явно привести его, как было показано. Однако ++i работает, потому что (из JLS 15.15.1):

Перед добавлением двоичное числовое продвижение (§5.6.2) выполняется для значения 1 и значения переменной. При необходимости сумма сужается путем сужающего преобразования примитивов (§5.1.3) и/или подвергается боксовому преобразованию (§5.1.7) в тип переменной перед ее сохранением.

Оператор ++ заботится о сужающемся преобразовании без необходимости его явного приведения