我有一个很大的坐标列表(这个表格):
if(x == 1055 && y == 63 && z == 1117)
return blackwood;
if(x == 1053 && y == 63 && z == 1117)
return blackwood;
if(x == 1049 && y == 64 && z == 1113)
return blackwood;
if(x == 1054 && y == 63 && z == 1112)
return blackwood;
if(x == 1058 && y == 63 && z == 1112)
return blackwood;
if(x == 1062 && y == 64 && z == 1117)
return blackwood;
if(x == 1050 && y == 64 && z == 1117)
return blackwood;
if(x == 1062 && y == 64 && z == 1118)
return glass;
if(x == 1050 && y == 64 && z == 1118)
return andesite;
(比这长得多)
但是,当我调用执行这些指令的方法时,我有一个滞后(不是很长,但足以在游戏中产生冻结印象)。
所以,我的问题是,我该如何优化呢?
我正在考虑在HashMap
中存储这些内容并使用HashMap.get(key)
,但HashMap.get(key)
是否会重复列表以找到它?
答案 0 :(得分:1)
您确实可以使用Map作为关键字,将自定义类用作这3个数据的组件值:x
,y
和z
。
公平地实施hashCode()
方法,它应该是一个恒定的时间[O(1)]或非常接近。
如果你需要经常重新创建地图,那么使用地图可能会让人感到无助,因为从一方面你可以放松你从另一方获得的东西。
因此,创建此自定义类并通过考虑这3个字段来覆盖hashCode()
和equals()
:
public class Coordinate {
private int x;
private int y;
private int z;
public Coordinate(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
result = prime * result + z;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!(obj instanceof Coordinate))
return false;
Coordinate other = (Coordinate) obj;
if (x == other.x && y == other.y && z == other.z)
return true;
return false;
}
}
然后,您可以使用预期的键值初始化地图:
Map<Coordinate, MyValue> mapValuesByCoord = new HashMap<>();
mapValuesByCoord.put(new Coordinate(1055,63,1117), blackwood);
mapValuesByCoord.put(new Coordinate(1053,63,1117), blackwood);
mapValuesByCoord.put(new Coordinate(1062, 64, 1118), glass);
...
以这种方式使用地图:
MyValue value = mapValuesByCoord.get(new Coordinate(1055,63,1117));
答案 1 :(得分:1)
这里有一个问题,常用的是“#34; map&#34;”,就像在一张纸上显示一块土地的缩影,而不是程序员或数学家&#39 ;使用&#34; map&#34;,其中的值与其他值相关联。
如果几乎每个3D坐标都有相应的返回值,那么最好使用直接查找表。您可以使用3D数组执行此操作,即阵列数组:
Rock[][][] rockMap = ... // Google for guidance on initialising a 3D array
...
rockMap[1054][63][1112] = blackwood;
// etc.
这里&#34; rockMap&#34;更接近于'#34; map&#34;这个词的常用用法。如果您绘制了3D阵列,它将是您的世界地图&#34;。
然后你的查询是:
return rockMap[x][y][z];
或者,您可以使用1D数组并从x,y,z计算索引:
Rock[] rockMap = new Rock[SIZE_X * SIZE_Y * SIZE_Z];
rockMap[1054 * SIZE_Y * SIZE_Z + 63 * SIZE_Z + 1112] = blackwood;
查找类似于作业:
return rockMap[x * SIZE_Y * SIZE_Z + y * SIZE_Z + z];
如果你没有为每个坐标设置摇滚,这种方法仍然有用(你在所有空插槽中只有一个空值或其他缺席标记)。但这会浪费太多空间。
在这种情况下,创建Coordinate
类型并构建Map<Coordinate>
可能更有效。
Map<Coordinate> rockMap = ...;
rockMap.put(new Coordinate(x,y,z), blackwood);
...
return rockMap.get(new Coordinate(x,y,z));
您应该进行自己的测试,以了解哪种类型的Map
最适合您的计划 - HashMap
? TreeMap
?测试它们。
要使这些工作正常,Coordinate
需要实现某些方法 - 检查Javadoc并确保它。
答案 2 :(得分:0)
HashMap很少迭代从其结构中获取元素。正确的实现很少迭代,人们通常不会提及该部分存在。因此O(1)的复杂性。
想象一下你的元素表(每个元素都有一个键)。理想情况下,HashMap会将每个元素放在一个唯一的行中(因此每行只有1个元素)。当给定获取元素的键时,HashMap将计算键的哈希(int)并找出其适当值位于哪一行。可能会出现一行中的多个元素,因为有时两个不同的键可以具有相同的哈希值,然后您迭代该行以查找您的元素。
我认为您可以在问题上使用HashMap来加快速度(x,y和z应该是唯一键)。
答案 3 :(得分:0)
我会创建具有check(x,y,z)方法的黑木,玻璃和安山岩对象。
修改强>
也许我应该补充一点,为了提高效率,你可以像这样实现blackwood.check(x,y,z):
public boolean check(int x, int y, int z){
if ( y == 63 || y == 64){
if (z == 1117 || z == 1113 || z == 1112){
if (x == 1055 || x == 1053 || x == 1049 || x = 1054 ||
x == 1058 || x == 1062 || x == 1050){
return true;
}
}
}
return false;
}
你将从中获得什么:
1)每种类型的逻辑被封装到单独的类中,你不会有一个带有长“ifs”的巨大方法。添加新类型很容易。
2)通过将“y”检查移到顶部,如果它不是63或64,则会快速退出。同样适用于z。由于Java中的“或”检查不会检查其余部分,因此如果x为1055,则不会检查所有“x”值,因此会购买一些性能。
3)使用Map或Set方法,您必须在每次调用方法时创建X,Y,Z包装密钥对象。通过非常频繁地调用该方法,您可能会遇到垃圾收集器无法以足够快的速度清理它们的问题。