2017-05-22 41 views
1

我有座標的大名單(此表):優化建議(HashMap的)

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)迭代列表中找到它呢?

+2

號包含HashMap返回* *基本恆定的時間AFAIK。這就是人們使用它們的原因。注意,雖然要將座標置於HashMap中,您需要將數字分組到某個向量或其他東西中,並且反覆散列容器也可能會慢一些;儘管可能比你現在的t方法更快。 – Carcigenicate

+1

'HashMap.get()'是恆定時間(加上衝突解決方案 - 取決於列表大小與列表中項目之間的比例) – Achilles

+0

做你自己的研究什麼是哈希表。下面是開始的一些事情:[哈希表如何工作](https:// stackoverflow。COM /問題/ 730620 /如何-做的那樣 - 一個哈希表工作) –

回答

1

您確實可以使用Map作爲關鍵字,將自定義類用作這3個數據的組件值:x,yz

通過公平的實施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)); 
0

HashMap很少重複從它的結構中獲取元素。正確的實現很少進行迭代,以至於人們通常不會提及該部分存在。因此,O(1)的複雜性。

想象一下你的元素表(每個元素都有一個鍵)。理想情況下,HashMap將把你的每一個元素放在一個唯一的行中(所以每行只有一個元素)。當給定一個鍵來獲取一個元素時,HashMap將計算該鍵的散列(int)並找出哪一行是它的合適值。一行中可能會出現多個元素,因爲有時兩個不同的鍵可以具有相同的散列,然後您迭代該行以找到您的元素。

我想你可以使用你的問題,一個HashMap加快步伐位(其中x,y和z應該是唯一的鍵)。

1

這裏有一個問題在這裏與「地圖」一詞共同使用,就像在一張紙上顯示一幅土地的微型表示,而程序員或數學家使用「地圖」,其中的值與其他值相關聯。

如果幾乎每個3D座標都有相應的返回值,那麼最好是直接查找表。您可以使用3D陣列來完成此操作,即的陣列陣列-的陣列的:

Rock[][][] rockMap = ... // Google for guidance on initialising a 3D array 

... 
rockMap[1054][63][1112] = blackwood; 
// etc. 

這裏「rockMap」更靠近共同使用的詞語「地圖」的。如果你畫出這個3D陣列,那將是你的「世界地圖」。

那麼你的查找是:

return rockMap[x][y][z]; 

或者,您也可以使用一維數組,並計算出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]; 

如果你對每個座標都沒有石頭,這種方法仍然可行(你只需要一個nu在所有的空插槽中,或者其他缺席標記)。但是這太浪費了。

在這種情況下,創建Coordinate類型並構造Map<Coordinate>會更有效。

Map<Coordinate> rockMap = ...; 
rockMap.put(new Coordinate(x,y,z), blackwood); 

... 

return rockMap.get(new Coordinate(x,y,z)); 

你應該做你自己的測試,以找出什麼類型的Map最適合你的程序 - HashMapTreeMap?測試他們。

對於這些工作,Coordinate需要實現某些方法 - 檢查Javadoc並確保它。

-1

我將創建具有檢查(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包裝器關鍵對象。隨着該方法被頻繁調用,您可能會遇到垃圾收集器無法快速清理它們的問題。