[英]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会在这里提供帮助。 我认为更好的只是介绍一些方法,以便代码更具可读性。
例如,您可以创建四个方法ringAbove
, ringBelow
, ringRight
和ringLeft
,这将使代码更具可读性。
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
方法利用纯几何位置的流,对其执行一些额外的检查(以确保您不离开游戏世界),然后使用其内容枚举所有字段。
然后,您可以使用这些字段流快速检查它们上的各种谓词,例如使用allMatch
和anyMatch
方法,如最后一个方法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>
,给定x
和y
坐标,返回一个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.