HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaModerate

Find the closest unvisited visible home

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
findvisibletheunvisitedhomeclosest

Problem

I'm writing a 2d top down game where I perform a lot of "closest" searches between one point and all the rest of the points.

In this example, "me" wants to search for the closest visible house (Home) that I haven't visited yet, and if it is not found, return null.

protected Home getClosestUnvisitedVisibleHome(Person me, final int VISIBLE_ZONE) {
    List visitedHomes = me.getVisitedHomes();
    Map homeDistances = new HashMap<>();
    List allHomes = getHomes();
    allHomes.stream().parallel().forEach(home -> homeDistances.put(home, range(me, home)));
    List unvisitedVisibleHomes = allHomes.stream().parallel().filter(
            home -> !visitedHomes.contains(home) && homeDistances.get(home)  homeDistances.get(home1).compareTo(homeDistances.get(home2)));
    try {
        return unvisitedVisibleHomes.get(0);
    } catch (IndexOutOfBoundsException e) {
        return null;
    }
}

protected int range(VisibleEntity visibleEntity, VisibleEntity me) {
    return (int)Math.sqrt(Math.pow((visibleEntity.xy[0] - me.xy[0]), 2) + Math.pow((visibleEntity.xy[1] - me.xy[1]), 2));
}


I'm looking for suggestions on how to optimize this particular function and or any suggestions of its content.

Solution

I don't see why you use a HashMap (or any Map) at all.

What I'd do is:

  • Get all the homes



  • Filter all the homes to only get those which are unvisited



  • Get the home that is closest



The home that you get will either be visible, or it won't be visible. If it is not visible, there won't be any other visible homes either.

Combining this with @Vogel's suggestion of using Set the code would go something like this:

Set visitedHomes = me.getVisitedHomes();
Set allHomes = getHomes();
Optional result = allHomes.stream().parallel()
    .filter(home -> !visitedHomes.contains(home))
    .min(Comparator.comparingInt(home -> range(me, home)))
    .map(result -> range(me, result) <= VISIBLE_ZONE ? result : null);


And then you can choose between either returning the optional:

return result;


or returning null if there is no match:

return result.orElse(null);

Code Snippets

Set<Home> visitedHomes = me.getVisitedHomes();
Set<Home> allHomes = getHomes();
Optional<Home> result = allHomes.stream().parallel()
    .filter(home -> !visitedHomes.contains(home))
    .min(Comparator.comparingInt(home -> range(me, home)))
    .map(result -> range(me, result) <= VISIBLE_ZONE ? result : null);
return result;
return result.orElse(null);

Context

StackExchange Code Review Q#118618, answer score: 14

Revisions (0)

No revisions yet.