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

fas*_*ava 15 java char java-8 java-stream

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

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

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

虽然写得很好 int i = 'a';

我知道我可以像这样写它,但对于一个简单的任务来说,这似乎太多了.

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

为什么Java类型推断失败?

Ous*_* D. 29

为什么原因i -> i + 1无法编译是因为你试图隐式的转换intCharacter该编译器不能做自己孤单.

换句话说,您可以将其Stream.iterate('a', i -> i + 1)视为:

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

正如您所指出的那样,明确地转换为char解决它:

Stream.iterate('a', i -> (char)(i + 1))...
Run Code Online (Sandbox Code Playgroud)

顺便说一句,这样做更好:

IntStream.rangeClosed('a', 'z').forEach(c -> System.out.println((char)c));
Run Code Online (Sandbox Code Playgroud)

这更好,因为:

  1. 没有拳击开销因此更有效率
  2. 如果你停止h使用iterate你的信件,你必须做更多的大脑处理,而不仅仅是输入h上限,rangeClosed因为你需要找到截断无限流的数字.
  3. 随着拳击iterate产生一个无限这在该特定情况下具有比所述更多的开销流有限一个与rangeClosed.此外,IntStream.rangeClosed并行运行要容易得多,而不是在这种特定情况下你想要这样做,但要记住这一点.以下是Brian Goetz 对发电机作为资料来源的一些讨论.

等等...

  • "在这个特定情况下有一个无限的流,比有限的那个有更多的开销,"那就更好了:)这个分裂性能的好标注. (2认同)

GBl*_*ett 17

怎么样:

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

i -> i + 1不起作用,因为i是a Characteri + 1导致隐式缩小转换(JLS 5.1.3),这是不允许的.您可以按照显示的方式显式地投射它.不过++i工作,因为(从JLS 15.15.1):

在添加之前,对值1和变量的值执行二进制数字提升(第5.6.2节).如果必要,在存储之前,通过缩小的基元转换(第5.1.3节)和/或经过装箱转换(第5.1.7节)将总和缩小到变量的类型.

++运营商已经明确地投它负责将收缩转换没有我们

  • 1对于令人敬畏的解释@GBlodgett (3认同)