繁体   English   中英

Java - 使用lambda表达式的if语句有多短?

[英]Java - How shorten if statements using lambda expressions?

首先,我知道有类似的问题。 然而,这个问题的答案对我没有帮助。

我有以下代码:

boolean result = fields[x][y + 1].getRing().getPlayer() == player || fields[x][y - 1].getRing().getPlayer() == player || fields[x + 1][y].getRing().getPlayer() == player || fields[x - 1][y].getRing().getPlayer() == player

该代码应该检查当前播放器上方,下方或旁边是否存在当前播放器的响铃。

我试图通过使用lambda表达式使这些代码更具可读性,但我无法做到正确。 不过,我不确定这是否可行。

我试图用变量field替换fields[x][y] ,然后使field变为fields[x][y+1], fields[x][y-1], fields[x+1][y], fields[x-1][y]

boolean result = field.getRing().getPlayer() == player -> field = {fields[x][y+1], fields[x][y-1], fields[x+1][y], fields[x-1][y]};

但这给了我一个语法错误,我期望,因为field = {fields[x][y+1], fields[x][y-1], fields[x+1][y], fields[x-1][y]}; 将字段设置为数组,而不迭代该数组。

有什么办法可以使用lambda表达式缩短代码吗?

你在4个不同的值上不断重复相同的条件。 所以你想要的实际上是避免这种重复,并写一次条件。 并且您想要测试4个值中的任何一个是否与条件匹配。 首先将4个值存储在集合中:

List<Field> neighbors = Arrays.asList(fields[x + 1][y],
                                      fields[x - 1][y],
                                      fields[x][y + 1],
                                      fields[x][y - 1]);

然后测试这些值是否与条件匹配:

boolean result = neighbors.stream().anyMatch(field -> field.getRing().getPlayer() == player);

这不一定使代码更快或更短,但它使它更具可读性和干燥性。

我不认为lambdas会在这里提供帮助。 我认为更好的只是介绍一些方法,以便代码更具可读性。

例如,您可以创建四个方法ringAboveringBelowringRightringLeft ,这将使代码更具可读性。

boolean result = ringAbove(x,y) || ringBelow(x,y) || ringRight(x,y) || ringLeft(x,y);

现在只需实现每个方法,并进行一些重构:

private boolean ringAbove( int x, int y ) {
    return ringAt( x+1, y);

}

其他三种方法可以类似地实现。

我真的不明白这段代码,但我们假设它有效。 player需要作为全局变量使用,或者您还需要将其作为参数传递。

private boolean ringAt( int x, int y ) {
     if( x < 0 || y < 0 || x >= fields.length || y >= fields[x].length )
          return false;
     return fields[x][y].getRing().getPlayer() == player;
}

这是处理职位和领域的另一种“小型嵌入式领域特定语言”。 它使用Java8 Streams和lambdas。

neighborhood方法抽象出离散几何邻域形状的概念,因此很容易处理网格上的所有类型的邻域,例如:

 #     ###      # #
#x#    #x#     #   #
 #     ###       x
               #   #
                # #

你想要第一种情况,但是在下面的代码中,用8个单元格的邻域(第二种情况)替换“邻居”的概念,或者甚至更奇怪的东西,例如允许的移动,这将是非常容易的。国际象棋骑士(第三案)。

neighboringFields方法利用纯几何位置的流,对其执行一些额外的检查(以确保您不离开游戏世界),然后使用其内容枚举所有字段。

然后,您可以使用这些字段流快速检查它们上的各种谓词,例如使用allMatchanyMatch方法,如最后一个方法checkRingsInNeighborhood ,这样笨拙的if-expression就会崩溃到这样:

return neighboringFields(pos).anyMatch(
    field -> field.getRing().getPlayer() == player
);

以下是完整的代码段:

import java.util.function.*;
import java.util.stream.*;

class NeighborPositions {

    // Mock up implementations of `Ring`, `Player`, and `Position`, 
    // whatever those things are
    public static class Ring {
        private Player player;
        public Ring(Player player) {
            this.player = player;
        }
        public Player getPlayer() {
            return this.player;
        }
    }

    public static class Player {
        private final String name;
        public Player(String name) {
          this.name = name;
        }
    }

    public static class Field {
        private final Ring ring;
        public Field(Ring ring) {
            this.ring = ring;
        }
        public Ring getRing() {
            return this.ring;
        }
    }

    // you probably want to fill it somehow...
    public static int DIM_X = 100;
    public static int DIM_Y = 42;
    public static Field[][] fields = null; 

    /** Position on a rectangular grid */
    public static class Position {
        final int x;
        final int y;
        public Position(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }

    /** Shortcut for accessing fields at a given position */
    public static Field field(Position p) {
        return fields[p.x][p.y];
    }

    /** Generates stream of neighboring positions */
    public static Stream<Position> neighborhood(Position pos) {
        return Stream.of(
            new Position(pos.x + 1, pos.y),
            new Position(pos.x - 1, pos.y),
            new Position(pos.x, pos.y + 1),
            new Position(pos.x, pos.y - 1)
        );
    }

    /** Generates stream of neighboring fields */
    public static Stream<Field> neighboringFields(Position pos) {
        return neighborhood(pos).
            filter(p -> p.x >= 0 && p.x < DIM_X && p.y >= 0 && p.y < DIM_Y).
            map(p -> field(p));
    }

    /** This is the piece of code that you've tried to implement */
    public static boolean checkRingsInNeighborhood(Position pos, Player player) {
        return neighboringFields(pos).anyMatch(
            field -> field.getRing().getPlayer() == player
        );
    }
}

您显然不应该尝试将所有内容都塞入单个文件并将其声明为public static ,这只是一个示例。

你可以创建一个BiFunction<Integer, Integer, Player> ,给定xy坐标,返回一个Player

BiFunction<Integer, Integer, Player> fun = (coordX, coordY) ->
    fields[coordX][coordY].getRing().getPlayer();

现在,要检查给定player的戒指是否位于给定坐标对的上方,下方或旁边,您可以使用:

boolean result = List.of(
        fun.apply(x, y - 1), 
        fun.apply(x, y + 1), 
        fun.apply(x - 1, y), 
        fun.apply(x + 1, y))
    .contains(player);

这使用Java 9的List.of 如果您还没有使用Java 9,只需使用Arrays.asList

此外,它还使用List.contains方法,该方法通过Objects.equals方法检查给定对象是否属于列表,而List.contains方法又使用equals方法(处理null s)。 如果Player不覆盖equals ,则身份相等==将用作后备。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM