Java 自作クラスを Map のキーにする
Map のキーは、int 型 や String 型で済ませることが多い。
自作クラスを Map のキーにする機会はたぶん今までなかった。
今回たまたま、それをする機会があったのだけど、get する時に果たして Map に格納されているものと等しいキーとして認識してくれるのだろうか?
作成したクラス
オブジェクトのソート条件を保持するクラス。
ソート対象フィールド名と、昇順・降順の何れかを保持する。
public final class SortCondition { private final String field; private final Direction direction; public SortCondition(String field, Direction direction) { this.field = field; this.direction = direction; } }
Map の生成
こんな感じで Map を生成する。
Map<SortCondition, Comparator<Item>> comparatorMap = new HashMap<>(); comparatorMap.put(new SortCondition("reviewAve", Direction.ASC), Comparator.comparing(Item::getReviewAve));
Map から get してみる
SortCondition condition1 = new SortCondition("reviewAve", Direction.ASC); Comparator<Item> comparator = this.comparatorMap.get(condition1); System.out.println(comparator); // <- null
見た目上は、同じキーを生成しているつもりでも、インスタンスが異なるので、値は取得できず comparator は null。
Map に入っているものと一致するキーにするためには?
SortCondition 内で hashCode() と equals() を正しくオーバーライドする必要があります。
SortCondiiton クラスに以下を追記します。
@Override public boolean equals(Object obj) { if (obj instanceof SortCondition) { SortCondition condition = (SortCondition) obj; return this.field.equals(condition.field) && this.direction.equals(condition.direction); } else { return false; } } @Override public int hashCode() { return Objects.hash(field, direction); }
equals() の結果が true で、hashCode() の結果が両オブジェクトで等しくなるので、この状態であれば一致するキーがあった時、Mapから対応する値が取得されるようになります。
SortCondition condition1 = new SortCondition("reviewAve", Direction.ASC); Comparator<Item> comparator = this.comparatorMap.get(condition1); System.out.println(comparator); // <- 指定したキーで、値(null ではない) が取得できた