If you have a
Player
class that looks something like this;
package my.company;
public class Player {
private final double x;
private final double y;
public Player(final double x, final double y) {
this.x = x;
this.y = y;
}
public double getX() { return x; }
public double getY() { return y; }
public double getDistance(final Player other) {
final double dx = getX() - other.getX();
final double dy = getY() - other.getY();
return Math.sqrt(dx*dx + dy*dy);
}
}
And a map class between holding a player and a distance to another (implicit) player that implements
Comparable<Player>
;
package my.company;
public class PlayerDistance implements Comparable<playerdistance> {
private final Player player;
private final double distance;
public PlayerDistance(final Player player, final double distance) {
this.player = player;
this.distance = distance;
}
public Player getPlayer() {
return player;
}
public double getDistance() {
return distance;
}
@Override
public int compareTo(PlayerDistance other) {
return distance < other.distance ? -1 : 1;
}
}
The the list of
K closest
Player
s can be retrieved like this;
package my.company;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Program {
public static Iterable<playerdistance> getClosest(
final Player source,
final Iterable<player> others,
int maxToGrab) {
final List<playerdistance> distances = new ArrayList<playerdistance>();
for(final Player player : others) {
distances.add(new PlayerDistance(player, source.getDistance(player)));
}
Collections.sort(distances);
return distances.subList(0, Math.min(maxToGrab, distances.size()));
}
public static void main(String[] args) throws Exception {
final List<player> players = new ArrayList<player>();
players.add(new Player(1.0, 1.0));
players.add(new Player(2.0, 2.0));
players.add(new Player(3.0, 3.0));
final Player me = new Player(0.0, 0.0);
for(final PlayerDistance playerDistance : getClosest(me, players, 2)) {
System.out.println(playerDistance.getPlayer() + " at " + playerDistance.getDistance());
}
}
}
Added:
The above solution gives the distances as well as the closest
Player
s, but if as you say it's more important not to create another class then that can be achieved by letting
Player
implement
Comparator
(not
Comparable
).
Like, this;
package my.company;
import java.util.Comparator;
public class Player implements Comparator<Player> {
private final String name;
private final double x;
private final double y;
public Player(final String name, final double x, final double y) {
this.name = name;
this.x = x;
this.y = y;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
@Override
public String toString() {
return name;
}
public double getDistance(final Player other) {
final double dx = getX() - other.getX();
final double dy = getY() - other.getY();
return Math.sqrt(dx*dx + dy*dy);
}
@Override
public int compare(Player o1, Player o2) {
final double distanceDelta = getDistance(o1) - getDistance(o2);
return distanceDelta < 0 ? -1 : 1;
}
}
Then, the method of finding the
K closest simply becomes;
package my.company;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Program {
public static Iterable<Player> getClosest(final Player source, final List<Player> others, int maxToGrab) {
Collections.sort(others, source);
return others.subList(0, Math.min(maxToGrab, others.size()));
}
public static void main(String[] args) throws Exception {
final List<Player> players = new ArrayList<Player>();
players.add(new Player("A", 1.0, 1.0));
players.add(new Player("B", 2.0, 2.0));
players.add(new Player("C", 3.0, 3.0));
players.add(new Player("D", 1.0, 0.5));
final Player me = new Player("S", 0.0, 0.0);
for(final Player player : getClosest(me, players, 2)) {
System.out.println(player);
}
}
}
Hope this helps,
Fredrik