ソートマップ(java.util.TreeMap)を使用した場合、キーの等価性の判断にはequalsではなくComparable#compareToの結果が使われます。 *1
これは、
Map (Java Platform SE 6)
の規約に違反していますが、TreeMapのドキュメントにはMapの規約に違反していることが明記されています。*2
このため、独自オブジェクトをTreeMapのキーに使用する場合は、equalsを実装しても実行されることがないのでカバレッジが低くなったりするので注意が必要です。基本的に独自オブジェクトをキーに突っ込むなんてことしないはずですが・・・
ちょっとしたお試しコードです。equalsを実装していないオブジェクトをキーにぶち込んだ場合のTreeMapとHashMapのcontainsKeyを呼び出した結果がわかるようになっています。
import java.util.HashMap; import java.util.Map; import java.util.TreeMap; public class Main { public static void main(String[] args) { MapKey key1 = new MapKey("1", "2"); MapKey key2 = new MapKey("1", "2"); Map<MapKey, String> treeMap = new TreeMap<MapKey, String>(); treeMap.put(key1, "1"); // TreeMapの場合は、equalsを実装していなくてもcompareToの結果で等価性が判断される System.out.println("treeMap.containsKey(key2) = " + treeMap.containsKey(key2)); HashMap<MapKey, String> hashMap = new HashMap<MapKey, String>(); hashMap.put(key1, "1"); // ソートマップではないので、java.util.Mapの規約どおりにequalsの結果で等価性が判断される。 // MapKeyは、equalsをoverrideしていないので、key1とkey2では等価にはならない System.out.println("hashMap.containsKey(key2) = " + hashMap.containsKey(key2)); } private static class MapKey implements Comparable<MapKey> { private final String key1; private final String key2; private MapKey(String key1, String key2) { this.key1 = key1; this.key2 = key2; } @Override public int compareTo(MapKey o) { int result = key1.compareTo(o.key1); if (result == 0) { result = key2.compareTo(o.key2); } return result; } } }
実行結果は、TreeMapの場合はキーが存在していると判断されますが、HashMapの場合は存在していないとなります。
treeMap.containsKey(key2) = true hashMap.containsKey(key2) = false
TreeMapなんてめったに使わないし、たいていStringをキーにするのでこんな仕様があることは全く知りませんでした。
おわり。