2016-07-08 179 views
0

我想在Groovy中使用映射,其中鍵將是不可變類的實例。使用Groovy和Java中的自定義鍵映射

這是我在Java中經常這樣做,它工作正常,就像這個例子類:

public class TestMap { 
    static final class Point { 
     final int x; final int y; 
     public Point(int x, int y) {this.x = x;this.y = y;} 
    } 

    public static void main(String[] args) { 
     Map<Point, String> map = new HashMap<>(); 
     final Point origin = new Point(0, 0); 
     map.put(origin, "hello world !"); 
     if(!map.containsKey(origin)) 
      throw new RuntimeException("can't find key origin in the map"); 
     if(!map.containsKey(new Point(0,0))) { 
      throw new RuntimeException("can't find new key(0,0) in the map"); 
     } 
    } 
} 

但是當我嘗試實現使用Groovy同樣的事情,這是行不通的。 爲什麼? 下面是使用Groovy樣本非工作示例:

class Point { 
    final int x; final int y 
    Point(int x, int y) { this.x = x; this.y = y } 
    public String toString() { return "{x=$x, y=$y}" } 
} 

def origin = new Point(0, 0) 
def map = [(origin): "hello"] 
map[(new Point(1,1))] = "world" 
map.put(new Point(2,2), "!") 

assert map.containsKey(origin) // this works: when it's the same ref 
assert map.containsKey(new Point(0,0)) 
assert map.containsKey(new Point(1,1)) 
assert map.containsKey(new Point(2,2)) 
assert !map.containsKey(new Point(3,3)) 
+0

您的Java版本也不起作用。見[這裏](https://ideone.com/hUsD2H)。 – Ironcache

回答

5

您必須對您的Point類的equalshashCode方法,以便實例可以作爲按鍵在HashMap

你可以找到這很快通過在Groovy中添加註釋:

import groovy.transform.* 

@EqualsAndHashCode 
class Point { 
    final int x; final int y 
    Point(int x, int y) { this.x = x; this.y = y } 
    public String toString() { return "{x=$x, y=$y}" } 
} 
+0

爲什麼它在Java中開箱即用? – Guillaume

+0

它沒有。你也需要'equals()'和'hashCode()'。這就是爲什麼你的Java代碼拋出'RuntimeException:無法在映射中找到新的鍵(0,0)。 – Andreas

+0

安德烈亞斯是對的;給出的Java代碼會創建一個受損的映射(如我在對該問題的評論中給出的[示例輸出](https://ideone.com/hUsD2H)所示)。這是正確的答案。 – Ironcache