java中任何对象都继承于Object,在创建HashMap的键的类时,可能会忘记在其中放置必要的方法。
例如:一个天气预报系统,将Goundhog(土拨鼠)--key对象与Prediction(预报)对象--value联系起来。
package map; public class Groundhog { protected int number; public Groundhog(int number) { super(); this.number = number; } /**必须覆盖object中的equals和hashCode方法,否则无法用散列处理key,注意别写成了hashcode*/ /* public boolean equals(Object o) { return o instanceof Groundhog && (this.number == ((Groundhog) o).number); } public int hashCode() { return this.number; }*/ public String toString() { return "Groundhog #" + number; } }
package map; import java.util.Random; public class Prediction { private static Random rand = new Random(47); private boolean shadow = rand.nextDouble() > 0.5; public String toString() { if(shadow){ return "Six more weeks of winter!"; }else{ return "Early spring!"; } } }
package map; import java.lang.reflect.Constructor; import java.util.Map; import java.util.HashMap; public class SpringDetector { public static <T extends Groundhog> void detectSpring(Class<T> type) throws Exception { Constructor<T> ghog = type.getConstructor(int.class); Map<Groundhog, Prediction> map = new HashMap<Groundhog, Prediction>(); for (int i = 0; i < 10; i++) { map.put(ghog.newInstance(i), new Prediction()); } System.out.println("map=" + map); Groundhog ghog3 = new Groundhog(3); System.out.println("Looking up Prediction for " + ghog3); if (map.containsKey(ghog3)) { System.out.println(map.get(ghog3)); } else { System.out.println("key not found!"); } } public static void main(String[] args) throws Exception { detectSpring(Groundhog.class); } }
Goundhog自动继承基类Object,默认使用对象的地址计算散列码,由于反射生成第一个Goundhog(3)实例与直接生成的Goundhog(3)地址显然不相等, 因此在map查询不到这个key。
总结:要使用自己的类作为key,必须同时重载hashCode()和equals()。