Reputation: 1682
I am currently writing a game for fun and I notice I still fall back to the "old" way of looping. Can anyone lend me a hand and show me how this method would look like using lambdas?
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;
}
Upvotes: 0
Views: 68
Reputation: 361595
Start with a stream()
.
The if
/continue
check maps to filter()
.
Use min()
to find the smallest object. min()
accepts a custom comparator, which is how we can tell it to compare enemies by their Euclidean distance.
Instead of returning null let's return Optional<GameObject>
to ensure the caller handles the case where there is no closest enemy.
public Optional<GameObject> findClosestEnemy(Game game, GameObject actor) {
return game.getObjects().stream()
.filter(o -> !isNoEnemy(actor, o))
.min(Comparator.comparing(actor::calculateMinEuclideanDistance));
}
Also, consider using more member functions. It seems like findClosestEnemy()
should be a method in the Game
class, and isNoEnemy()
should be in GameObject
. And avoid negations in identifiers: it should probably just be isEnemy()
. actor.isEnemy(o)
or o.isEnemyOf(actor)
both read better to me than isNoEnemy(actor, o)
.
Upvotes: 5