java - 有人可以向我简要解释一下 IntStream 发生了什么吗?

标签 java java-8

我在网上查找了多个示例,但我似乎无法理解这里发生的情况。当程序打印出当前玩家和分数时,我不清楚它们存储在哪里。我是一名初学者,我被告知分析这段代码以帮助“更好地理解”我们当前的类项目。

import java.util.Arrays;
import java.util.Random;
import java.util.Scanner;
import java.util.stream.IntStream;

public interface PigDice {
    public static void main(String... arguments) {
        final int maxScore = 100;
        final int playerCount = 2;
        final String[] yesses = { "y", "Y", "" };

        final Scanner scanner = new Scanner(System.in);
        final Random random = new Random();

        final int[] safeScore = new int[2];
        final int[] score = new int[2];

        IntStream.iterate(0, player -> (player + 1) % playerCount).map(player -> {
            boolean isRolling = true;
            while (isRolling) {
                System.out.printf("Player %d: (%d, %d) Rolling? (y/n) ", player, safeScore[player], score[player]);
            isRolling = safeScore[player] + score[player] < maxScore
                    && Arrays.asList(yesses).contains(scanner.nextLine());
                if (isRolling) {
                    final int rolled = random.nextInt(6) + 1;
                    System.out.printf("Rolled %d\n", rolled);
                    if (rolled == 1) {
                        System.out.printf("Bust! You lose %d but keep %d\n\n", score[player], safeScore[player]);
                        return -1;
                    } else {
                        score[player] += rolled;
                    }
                } else {
                    safeScore[player] += score[player];
                    if (safeScore[player] >= maxScore) {
                        return player;
                    }
                    System.out.printf("Sticking with %d\n\n", safeScore[player]);
                }
            }
            score[player] = 0;
            return -1;
        }).filter(player -> player > -1).findFirst().ifPresent(
                player -> System.out.printf("\n\nPlayer %d wins with a score of %d", player, safeScore[player]));
    }
}

最佳答案

为了理解这段代码的作用,我首先应用几个关键的重构:

  1. main() 的所有局部变量提升为 PigDice 类的静态变量。

  2. 将传递给 map() 的大型多行 lambda 提取到 PigDice 类的静态方法中。调用此方法turn():

    static int turn(int player) {
        ...
    }
    

流管道现在看起来像这样:

    IntStream.iterate(0, player -> (player + 1) % playerCount)
             .map(PigDice::turn)
             .filter(player -> player > -1)
             .findFirst()
             .ifPresent(
                player ->
                    System.out.printf("\n\nPlayer %d wins with a score of %d",
                        player, safeScore[player]));

IntStream.iterate() 方法生成一个 int 值流,从提供的初始值开始,在本例中初始值为零。后续值由 lambda 表达式计算。在此,该表达式加一并用 playerCount 计算余数,在本例中为 2。结果是值 0, 1, 0, 1, 0, 1, ... 的流,表示轮到的玩家编号。

map() 阶段将每个值传递给 turn() 方法,该方法执行所有游戏逻辑。但如果你简化这个逻辑,基本上,如果没有获胜者,它会返回 -1;如果该玩家获胜,它会返回其输入参数(当前玩家编号)。如果玩家 0 获胜,则结果为流 -1, -1, -1, -1, ... 0(如果玩家 1 获胜,则最后一个值为 1)。

来自 map() 的结果流只是故事的一部分。实际的游戏逻辑通过对游戏状态的副作用进行操作,这些状态保存在捕获的变量scannerrandomscore<中safeScore

filter() 阶段仅传递大于 -1 的值,因此它会在游戏进行时丢弃所有前导 -1 值,仅在玩家获胜后才生成值.

findFirst() 阶段获取第一个元素,然后终止流。这就是游戏最终终止的原因。

现在,findFirst() 返回一个 OptionalInt,其中包含获胜玩家的号码。一般来说,它可能是空的,但在这种情况下,它永远不会是空的,因为 iterate() 会产生无限流。由于它永远不会为空,因此 ifPresent() 内部的 lambda 表达式始终会被执行,并传递获胜玩家的号码;这会打印出最终的游戏结果。

这基本上就是它的工作原理。

请注意,正如我和其他人在评论中指出的那样,这里存在一些不好的代码味道和反模式,以及一些错误。我强烈建议不要使用此作为良好的 lambda 和流编码实践的示例。

关于java - 有人可以向我简要解释一下 IntStream 发生了什么吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35051248/

相关文章:

java - 使用jsf连接数据库

java - JAX-RS:NoSuchMethodFound 异常 Jersey-media-moxy JSON

java - 如何从 Java 8 的学生列表中的列表中找到前 n 个最受欢迎的运动

Java 将特定类的列表添加到 java.lang.Object 的列表与 java 8 流一起工作 - 为什么?

java - 使用 DefaultHttpClient 设置语言环境?

java - 如何使用 JCE 中的 PBEWITHHMACSHA256ANDAES_256 算法

java - 如果请求在同一天到来,则对象保持不变,否则比较并创建新对象

java - 将 Instant 从大纪元时间转换为微秒

Java 8 Instant.range 和 Instant.with 出现不一致

Java8枚举避免多个if else