java的chars()流如何与reduce一起工作?它使用字符编码吗?

rai*_*ker 2 java char java-stream

代码战争的挑战在于计算你必须将 Long 的各个整数相乘多少次才能成为一位数。例如

39 -> 3 * 9 = 27 -> 2 * 7 = 14 -> 1 * 4 = 4 // 答案是 3

这是已发布的解决方案之一 -

class Persist {
  public static int persistence(long n) {
    int times = 0;
    while (n >= 10) {
      n = Long.toString(n).chars().reduce(1, (r, i) -> r * (i - '0'));
      times++;
    }
    return times;
  }
}
Run Code Online (Sandbox Code Playgroud)

我对代码的“(i - '0')”部分感到非常困惑。我昨天才知道 Java 的 chars() 方法返回一个 IntStream 表示字符,所以立即使用 reduce 对我来说很有意义。但随后它减去了一个让我失望的字符,因为它似乎适用于它正在使用字符,但是它们是如何相乘的?

我复制了上面的代码,然后删除了字符减法,所以这是我理解的一个简单的reduce语句,也就是

n = Long.toString(n).chars().reduce(1, (r, i) -> r * i);
Run Code Online (Sandbox Code Playgroud)

然后运行调试器。第一个循环将 3 * 9 计算为 2907。这个答案从何而来?我最好的猜测是它与字符编码有关,但是为什么减去字符 '0' 会修复它呢?

Hol*_*ger 5

Achar只是在0to范围内的数字,0xFFFF在打印或连接到字符串时具有特殊含义。

你可以轻松写

int i = 'A';
Run Code Online (Sandbox Code Playgroud)

但是也

char c = 65;
Run Code Online (Sandbox Code Playgroud)

两个变量指代相同的数字,因此,

System.out.println(i == c);
Run Code Online (Sandbox Code Playgroud)

会打印true,但当你执行

System.out.println(i);
System.out.println(c);
Run Code Online (Sandbox Code Playgroud)

不同的变量类型将导致选择不同的方法对值的不同解释。

您可以使用char值进行计算并始终将它们分配给int变量,因为它们的值范围适合int值范围,因此可以使用 处理一系列charIntStream并保存另一个专用 Stream 类的创建。您只需要注意正确解释结果值。

说到编码,char被定义为一个 UTF-16 单元,所以如果你想给它一个名字,那就是正确的。

对于你的问题的例子,它是重要的是了解的字符'0''9'必须在UTF-16编码(它适用于所有的Unicode编码)相邻值,这样做不仅减去'0''0'给你的int价值0,减去'0'从任何字符'0'to '9'range 会给你相应的int值。这一事实'0'的编码值是48不是连这个逻辑相关。

请注意该codepoints()方法的存在,该方法返回范围为( )的 Unicode代码点值序列。对于BMP 中的字符,值与值相同,但 BMP 之外的值被编码为两个 UTF-16 单元,因此用流处理它们更容易。01,114,1110x10FFFFcharcodepoints()