用lambdas替换命令式for循环
我目前正在编写一个有趣的游戏,我注意到我仍然回到“旧”的循环方式。谁能帮我看看这个方法在使用 lambda 时会是什么样子?
public GameObject findClosestEnemy(Game game, GameObject actor) {
Double minDistance = null;
GameObject closestEnemy = null;
for (GameObject o : game.getObjects()) {
if (isNoEnemy(actor, o)) {
continue;
}
double distance = actor.calculateMinEuclideanDistance(o);
if (minDistance == null || distance < minDistance) {
minDistance = distance;
closestEnemy = o;
}
}
return closestEnemy;
}
回答
从一个stream().
该if/continue检查映射到filter()。
使用min()发现的最小的对象。min()接受自定义比较器,这就是我们可以告诉它通过欧几里德距离比较敌人的方式。
让我们返回Optional<GameObject>以确保调用者处理没有最近敌人的情况,而不是返回 null 。
public Optional<GameObject> findClosestEnemy(Game game, GameObject actor) {
return game.getObjects().stream()
.filter(o -> !isNoEnemy(actor, o))
.min(Comparator.comparing(actor::calculateMinEuclideanDistance));
}
此外,请考虑使用更多成员函数。似乎findClosestEnemy()应该是Game类中的一个方法,并且isNoEnemy()应该在GameObject. 并避免标识符中的否定:它可能应该只是isEnemy(). actor.isEnemy(o)或者o.isEnemyOf(actor)两者都比isNoEnemy(actor, o).