Печать букв от А до Я с использованием потока Java - PullRequest
0 голосов
/ 28 декабря 2018

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

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

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

Хотя это нормальнонапишите int i = 'a';

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

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

Почему происходит сбой вывода типа Java?

Ответы [ 2 ]

0 голосов
/ 28 декабря 2018

Как насчет:

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

i -> 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) в тип переменной перед ее сохранением.

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

0 голосов
/ 28 декабря 2018

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

Другими словами, вы можете думать о Stream.iterate('a', i -> i + 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 параллельно, не то, что вы хотите в данном конкретном случае, но об этом следует помнить.Вот несколько рассуждений о Генераторах как источниках Брайана Гетца.

и т. д.

...