2016-07-08 169 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