hash map

3795 ワード

import java.util.*;
class Dog {
public Dog(String n) { name = n; }
public String name;
public boolean equals(Object o) {
if((o instanceof Dog) &&
(((Dog)o).name == name)) {
return true;
} else {
return false;
}
}
public int hashCode() {return name.length(); }
}
class Cat { }
enum Pets {DOG, CAT, HORSE }
class MapTest {
public static void main(String[] args) {
Map<Object, Object> m = new HashMap<Object, Object>();
m.put("k1", new Dog("aiko")); // add some key/value pairs
m.put("k2", Pets.DOG);
m.put(Pets.CAT, "CAT key");
Dog d1 = new Dog("clover"); // let's keep this reference
m.put(d1, "Dog key");
m.put(new Cat(), "Cat key");
System.out.println(m.get("k1")); // #1
String k2 = "k2";
System.out.println(m.get(k2)); // #2
Pets p = Pets.CAT;
System.out.println(m.get(p)); // #3
System.out.println(m.get(d1)); // #4
System.out.println(m.get(new Cat())); // #5
System.out.println(m.size()); // #6
}
}
which produces something like this:
Dog@1c
DOG
CAT key
Dog key
null
5
Let's review the output. The first value retrieved is a Dog object (your value
will vary). The second value retrieved is an enum value (DOG). The third value
retrieved is a String; note that the key was an enum value. Pop quiz: What's the
implication of the fact that we were able to successfully use an enum as a key?
The implication of this is that enums override equals() and hashCode(). And,
if you look at the java.lang.Enum class in the API, you will see that, in fact, these
methods have been overridden.
The fourth output is a String. The important point about this output is that the
key used to retrieve the String was made of a Dog object. The fifth output is null.
The important point here is that the get() method failed to find the Cat object
that was inserted earlier. (The last line of output confirms that indeed, 5 key/value
pairs exist in the Map.) Why didn't we find the Cat key String? Why did it work to
use an instance of Dog as a key, when using an instance of Cat as a key failed?
It's easy to see that Dog overrode equals() and hashCode() while Cat didn't.
Let's take a quick look at hashcodes. We used an incredibly simplistic hashcode
formula in the Dog class—the hashcode of a Dog object is the length of the
instance's name. So in this example the hashcode = 6. Let's compare the following
two hashCode() methods:
public int hashCode() {return name.length(); } // #1
public int hashCode() {return 4; } // #2
Time for another pop quiz: Are the preceding two hashcodes legal? Will they
successfully retrieve objects from a Map? Which will be faster?
The answer to the first two questions is Yes and Yes. Neither of these hashcodes
will be very efficient (in fact they would both be incredibly inefficient), but they
are both legal, and they will both work. The answer to the last question is that the
first hashcode will be a little bit faster than the second hashcode. In general, the
more unique hashcodes a formula creates, the faster the retrieval will be. The first
hashcode formula will generate a different code for each name length (for instance
the name Robert will generate one hashcode and the name Benchley will generate
a different hashcode). The second hashcode formula will always produce the same
result, 4, so it will be slower than the first.