【问题标题】:Printing the letters from A to Z using a Java stream使用 Java 流打印从 A 到 Z 的字母
【发布时间】:2019-05-25 20:13:52
【问题描述】:

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

类型不匹配:无法从 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 类型推断失败?

【问题讨论】:

标签: java java-8 char java-stream


【解决方案1】:

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. 如果您要停止使用iterate 说字母h,那么您必须进行更多的大脑处理,而不仅仅是输入h 作为rangeClosed 的上限,因为您需要找到要截断无限流的数字。
  3. 与装箱iterate 一起生成一个infinite 流,在这种特定情况下,它比rangeClosedfinite 流具有更多的开销。此外,并行运行IntStream.rangeClosed 要容易得多,在这种特定情况下并不是您想要这样做,但需要牢记这一点。这是 Brian Goetz 对 Generators as sources 的一些讨论。

等等……

【讨论】:

  • "迭代生成一个无限流,它再次比有限流具有更多开销。"这是为什么呢?
  • @Alexander 首先,我会改进我的措辞,因为它可能不是消除歧义的最佳方法。谢谢。我还引用了一个可能感兴趣的博客。
  • “一个无限流,在这种特定情况下,它比有限流具有更多开销”,这更好:) 很好地标注了它的拆分性能。
  • 链接已损坏。该页面似乎已(重新)移动。
【解决方案2】:

怎么样:

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

i -> i + 1 不起作用,因为 iCharacteri + 1 导致隐式缩小转换 (JLS 5.1.3),这是不允许的。您可以显式地按所示进行投射。但是++i 有效,因为(来自JLS 15.15.1):

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

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

【讨论】:

  • 很好的答案,如果你能解释为什么++i 有效而i + i 无效,那就更好了。
  • 1 ?? 精彩的解释@GBlodgett
猜你喜欢
  • 2021-09-22
  • 1970-01-01
  • 2020-09-19
  • 2011-05-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多