有人可以简单地向我解释一下IntStream会发生什么吗?

时间:2016-01-28 01:18:53

标签: 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 个答案:

答案 0 :(得分:4)

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

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

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

    static int turn(int player) {
        ...
    }
    
  3. 流管道现在看起来像这样:

        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和{{1}中维护}。

    safeScore阶段仅传递大于-1的值,因此在游戏进行过程中会丢弃所有前导-1值的值,只有在玩家获胜后才会产生值。

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

    现在,findFirst()返回findFirst(),其中包含获胜玩家的号码。通常它可能是空的,但在这种情况下它永远不会为空,因为OptionalInt产生无限流。因为它永远不会为空,所以iterate()内的lambda表达式总是被执行并传递给获胜玩家的号码;这打印出最终的游戏结果。

    这基本上就是这样的。

    请注意,正如我和其他人在评论中指出的那样,这里有几个不良的代码气味和反模式,加上一些错误。我强烈建议使用它作为良好的lambda和流编码实践的一个例子。