使用Java流将字母从A打印到Z

时间:2018-12-27 21:41:32

标签: java java-8 char java-stream

我有这段代码,但它给了我一个错误:

  

类型不匹配:无法从int转换为Character

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)

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作为{{1 }},因为您需要找到数字以截断无限流。
  3. 与装箱rangeClosed一起生成 infinite 流,在此特定情况下,该流比具有iterate finite 开销更大。此外,并行运行rangeClosed要容易得多,并不是您想在这种特定情况下运行,而是要牢记。这是Brian Goetz在Generators as sources上的一些讨论。

等...

答案 1 :(得分:17)

怎么样:

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

i -> i + 1不起作用,因为iCharacter,并且i + 1导致隐式变窄转换(JLS 5.1.3),这是不允许的。您可以如图所示明确地投射它。但是++i之所以有效,是因为(来自JLS 15.15.1):

  

在加法之前,对值1和变量的值执行二进制数值提升(第5.6.2节)。如有必要,可通过缩小原始转换(第5.1.3节)来对和进行缩小,和/或在存储变量之前将其进行装箱转换(第5.1.7节)至变量的类型。

++运算符负责缩小转换,而无需我们显式转换