【Apex】2つのMapのkeyとvalueの組合せが等しいことを確認する
2つのMapの対応付け(KeyとValueの組合せ)が等しいことを確認する場面が出てきたので、調査がてら書いていこうと思います。
Apex開発者ガイドを見ると、equals(map2)メソッドで対応付けが等しいかの確認ができるとのこと。
Apex 開発者ガイド Map クラス
まずは別インスタンスですが、KeyとValueの組合せが全く同じ2つのMapの比較をしてみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
public class MapEqualsTest { public static void main() { Map<String, Integer> map1 = new Map<String, Integer>(); map1.put('あああ',1); map1.put('いいい',2); map1.put('ううう',3); Map<String, Integer> map2 = new Map<String, Integer>(); map2.put('あああ',1); map2.put('いいい',2); map2.put('ううう',3); if (map1.equals(map2)) { System.debug('map1とmap2は同じ'); } else { System.debug('map1とmap2は違う'); } } } |
結果は2つのMapは同じと判定されました。まあ、ここまでは良いでしょう。
USER_DEBUG [16]|DEBUG|map1とmap2は同じ |
続いて、Mapにputする順番を変えて比較してみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
public class MapEqualsTest { public static void main() { Map<String, Integer> map1 = new Map<String, Integer>(); map1.put('あああ',1); map1.put('いいい',2); map1.put('ううう',3); Map<String, Integer> map2 = new Map<String, Integer>(); map2.put('ううう',3); map2.put('あああ',1); map2.put('いいい',2); if (map1.equals(map2)) { System.debug('map1とmap2は同じ'); } else { System.debug('map1とmap2は違う'); } } } |
こちらも同じものと判定されました。
USER_DEBUG [16]|DEBUG|map1とmap2は同じ |
ちなみにkeyとvalueの組合せが違う場合や、keyの数が違う場合には ちゃんとequals=falseの結果となりました。
・・・という感じで、今回私がやりたかったことの調査は終わったのですが、Mapといえばよく使うのがkeyがId、valueがsObject型の組合せだと思いますので、ついでにそちらも調査してみました。
まずはSOQLで取得したAccountリストを別インスタンスのMapにそれぞれツッコんでみて、equalsで比較してみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public class MapEqualsTest { public static void main() { List<Account> accList = [SELECT Id, Name FROM Account]; Map<String, Account> map1 = new Map<String, Account>(); for (Account acc : accList) { map1.put(acc.Id, acc); } Map<String, Account> map2 = new Map<String, Account>(); for (Account acc : accList) { map2.put(acc.Id, acc); } if (map1.equals(map2)) { System.debug('map1とmap2は同じ'); } else { System.debug('map1とmap2は違う'); } } } |
結果は同じMapと認識されました。まずは想定通りです。
USER_DEBUG [18]|DEBUG|map1とmap2は同じ |
では別インスタンスのAccountリストをツッコんだ場合はどうなるでしょう。
Mapの組合せ的には同じでも、equalsはfalseになると思うのですが・・
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
public class MapEqualsTest { public static void main() { List<Account> accList = [SELECT Id, Name FROM Account]; Map<String, Account> map1 = new Map<String, Account>(); for (Account acc : accList) { map1.put(acc.Id, acc); } List<Account> accList2 = [SELECT Id, Name FROM Account]; Map<String, Account> map2 = new Map<String, Account>(); for (Account acc : accList2) { map2.put(acc.Id, acc); } if (map1.equals(map2)) { System.debug('map1とmap2は同じ'); } else { System.debug('map1とmap2は違う'); } } } |
お~、結果は同じMapと判定されました。予想外。
USER_DEBUG [20]|DEBUG|map1とmap2は同じ |
これは、sObjectの中身をちゃんと見てequalsかどうかを比較しているということですかね。
試しに上記コードのmap2の方、少し値を変えてみようと思います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
public class MapEqualsTest { public static void main() { List<Account> accList = [SELECT Id, Name FROM Account]; Map<String, Account> map1 = new Map<String, Account>(); for (Account acc : accList) { map1.put(acc.Id, acc); } List<Account> accList2 = [SELECT Id, Name FROM Account]; Map<String, Account> map2 = new Map<String, Account>(); for (Account acc : accList2) { map2.put(acc.Id, acc); } // map2にツッコんだAccountの内、1つだけAccount名を変更 for (Id key : map2.keySet()) { map2.get(key).Name = map2.get(key).Name + '変更'; break; } if (map1.equals(map2)) { System.debug('map1とmap2は同じ'); } else { System.debug('map1とmap2は違う'); } } } |
結果は異なるMapと認識されました。やはりsObjectの中身もちゃんと見て比較しているようですね。
Javaのクラス型だと、中身が同じでも別インスタンスだと別物の扱いとなった記憶があるので、その感覚で考えていました(Javaも最近触っていないので、薄~い記憶ですが・・)。
いずれにしても、Mapクラスのequalsはけっこう使いみちがあるかも!?です。