2014-03-25 48 views
0
import java.util.*; 

class U { 
    int x; 

    U(int x) { 
     this.x = x; 
    } 
} 

public class G { 
    public U a = new U(22); 
    public U b = new U(23); 
    Integer y = 22; 
    Integer r = 23; 

    void a() { 
     Map<U, Integer> set = new HashMap<U, Integer>(); 
     set.put(a, y); 
     set.put(a, r); 
     set.put(b, y); 
     System.out.print(set.size() + " "); 
    } 

    public static void main(String[] args) { 
     G m = new G(); 
     m.a(); 
    } 
} 

我总是在地图和列表中感到困惑。 我知道,当映射将键放入集合中时,它会调用哈希码,如果桶相同,则会调用相同的方法。但是,我了解到,如果类覆盖这两种方法,则只会存储重复密钥。例如包装类:String实现自己的哈希码和等同的方法。此外,如果您不这样做,则会调用唯一的哈希码,并将重复的密钥存储在集合中。HashMap不添加重复键

但是在上面的例子中,U类并没有实现hashcode和equal方法。但是,Map不允许重复键。

我检查了SIZE:它的2 它应该是3,因为我的U类没有实现哈希代码或不等于。

请让我清醒

在此先感谢

回答

7

HashMap不允许重复键,

如果不提供hashcode()equals()实现它extends它从超类(你的情况它是java.lang.Object),并且该实现为同一对象提供相同的哈希码,并且在同一对象上返回equals()返回true

public boolean equals(Object obj) { 
    return (this == obj); 
} 

以及

1

您正在使用的U相同的实例作为键两次:

set.put(a, y); 
set.put(a, r); 

U类未实现hashCode()你提到的,所以默认实现Object#hashCode这显然是相同的,因为它是相同的情况。因此地图只包含第二个条目。但是,如果您尝试以下方法,你最终会与两个独立的条目:

set.put(new U(22), y); 
set.put(new U(22), r); 

但通常你会一直想实现equals()hashCode()用于作为地图的关键任何类 - 否则你无法查看该值无需访问存储的确切实例!

+0

这可能是一个愚蠢的问题,但不会是那种打败目的的东西添加到一个HashMap,而不访问它的参考? –

+0

@ C.B。您通常希望使用不等于身份但等于其内容的密钥。可以考虑使用String作为关键字:如果String的hashCode对每个实例都是唯一的,则必须跟踪存储在地图中的确切实例。但是因为所有包含相同字符的字符串都具有相同的hashCode,所以可以使用任何等效的String实例来查找它。 – andersschuller

0

如果你想添加重复键,尝试这样的事情:

Map<Integer, List<Integer>> map = new HashMap<Integer, List<Integer>>(); 

    map.put(1, new ArrayList<Integer>()); 
    map.get(1).add(1); 
    map.get(1).add(2);