Reputation: 10975
I have a coordinate system such as this:
public enum Direction {
N ( 0, 1),
NE ( 1, 1),
E ( 1, 0),
SE ( 1, -1),
S ( 0, -1),
SW (-1, -1),
W (-1, 0),
NW (-1, 1);
private int x = 0, y = 0;
private Direction(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public Direction combine(Direction direction) {
//unsure
}
}
I'm trying to combine directions with a method within the enum, like:
Direction.N.combine(Direction.E) -> should become Direction.NE
Direction.N.combine(Direction.N) -> null or Direction.N again
My thoughts are to loop through all the values in the enum, and find one that matches its x and y combined:
public Direction combine(Direction direction) {
Direction[] directions = Direction.values();
for (int i = 0; i < directions.length; i++)
if (x + direction.x == directions[i].x && y + direction.y == directions[i].y)
return directions[i];
return this;
}
But I feel like that's an inefficient way to approach this. Is there another way to combine these directions that doesn't involve looping through all the enums?
I also want to create an uncombine function that will reverse the combine.
Direction.NE.uncombine() -> Direction[] {Direction.N, Direction.E}
I could also use the same looping technique, like:
public Direction[] uncombine() {
Direction[] directions = Direction.values(),
rtn = new Direction[2];
for (int i = 0; i < directions.length; i++)
if (x == directions[i].x && directions[i].y == 0)
rtn[0] = directions[i];
for (int i = 0; i < directions.length; i++)
if (y == directions[i].y && directions[i].x == 0)
rtn[1] = directions[i];
return rtn;
}
So is there a more efficient way that I could try out?
Upvotes: 1
Views: 445
Reputation: 1056
If your real class is as simply as the one from the question I think that the most efficient way would be to either manually "hardcode" or pre-calculate (e.g. in static init block) the relationship between argument and result and keep it in map and then only refer to already existing results.
Upvotes: 1
Reputation: 718826
I think that creating a Map<Direction, Direction>
for each enum value is going to give you a good balance between performance and code neatness.
The combine
method becomes:
public Direction combine(Direction other) {
return this.combinerMap.get(other);
}
Of course, you need to build the maps during initialization of the enum class.
Returning null
from this method is a bad idea because it pushes the responsibility for sanity checking back onto the caller. So I'd write it like this:
public Direction combine(Direction other)
throws InsaneDirectionsException{
Direction res = this.combineMap.get(other);
if (res == null) {
throw new InsaneDirectionsException(
"Can't combine directions " + this +
" and " + other);
}
return res;
}
Upvotes: 2
Reputation: 3511
You can keep Map<Byte, Map<Byte, Direction>>
where x
and y
will be indexes. Once you compute new x
and y
, obtaining Direction
will be as simple as matrix.get(x).get(y)
.
Upvotes: 0