ApexでのMapの使い方を徹底解説!【Salesforce】
こんにちは、アンダーソンです。
今回はApexにおけるMapの使い方を説明していきたいと思います。
以前にApexのList,Map,Setの使い方を徹底解説!という記事を書いたんですが、
Mapを使いこなすことによるメリットはかなり大きいので
是非いろんな使い方をマスターしていくためにまとめておきたいと思います。
Mapを使いこなすと下記のようなメリットがあります。
ガバナ制限の回避をしやすくなる
Apexの実行時間の制限を回避しやすくなる
複雑なロジックにも対応しやすくなる
と言ったことです。
ではそれぞれどのように使っていくのかを実際のコードをみながら
解説していきたいと思います。
Mapの宣言と入れられる値
まず、Mapの基本的な使い方です。
ApexのList,Map,Setの使い方を徹底解説!
でも解説をしているのでおさらいになりますが、Mapは
キー=値
という形で格納されているものでしたね。
キーにくるのはプリミティブ型でもコレクションでも、sObject型でも
OKです。
また値も同じくです。
実際の宣言をみてみましょう。
Map<String, String> sampleMap1 = new Map<String, String>();
Map<Id, Account> sampleMap2 = new Map<Id, Account>();
Map<Integer, List<String>> sampleMap3 = new Map<Integer, List<String>>();
Map<Id, Map<String,sObject>> sampleMap4 = new Map<Id, Map<String,sObject>>();
このようにMapは対応付け、キーに対して値がある形なので、
Stringに対してStringの値、Idに対してAccountというように様々な形を表現できます。
初めからキーと値を宣言しておくこともできます。
Map<String, String> sampleMap1 = new Map<String, String>{
'a' => 'A', 'b' => 'B' , 'c' => 'C'
};
Map<Id, Account> sampleMap2 = new Map<Id, Account>([SELECT Id FROM Account]);
このように対応付けを宣言時に入れておくことも可能です。
後から対応付けを入れる場合にはputを使います。
Map<Id, Account> sampleMap2 = new Map<Id, Account>();
for ( Account acc : [SELECT Id, Name FROM Account] ) {
sampleMap2.put(acc.Id,acc);
}
初期化時点で入れておく方が圧倒的に楽なので前者のやり方は
覚えておく方がいいと思います(無駄にfor文を回さなくて済むメリットもあり)
値を取り出すには?
Mapのメリットはキー=値ということです。
Listはindexという番号が0から振られており、
例えば1万件のListがあったとして、5001件目にアクセスしたい値がある場合、
それを探し出さないといけません。
List<Integer> intList = new List<Integer>{1,2,3,4 ... 10000};
Boolean success = false;
for ( Integer i : intList ) {
if ( i == 5001 ) {
success = true;
break;
}
}
このような形だと、時間がかかってしまい非常に非効率です。
Mapの場合、キーさえあれば値を取り出すことができるので、
時間をかけることなく上記のようなことができます。
Map<Integer,Integer> intMap = new Map<Integer,Integer>{1 => 1 ,2 => 2 ... 10000 => 10000};
Boolean success = false;
if ( intMap.get(5001) != null ) success = true;
.get(key)で値を取り出すことができますし、なければnullが返ってくるので、
Listの場合よりも簡単にしかも早く結果を調べることができます。
また二つの値を比較するような場合でも効果があります。
たとえばListの場合
List<Account> accList = [SELECT Id, Name FROM Account];
List<Contact> conList = [SELECT AccountId FROM Contact];
for ( Account acc : accList ) {
for ( Contact con : conList ) {
if ( acc.Id = con.AccountId ) {
// 処理を書く
}
}
}
このような場合、リストの件数×リストの件数分ループが回ってしまうため、
トリガやバッチなどで大量レコードを扱う際にはあまりいい方法とは言えません。
これがMapの場合だと簡単にできます。
List<Contact> conList = [SELECT AccountId FROM Contact];
Map<Id,Account> accMap = new Map<Id,Account>([SELECT Id FROM Account]);
for ( Contact con : conList ) {
if ( accMap.get(con.AccountId) != null ) {
//ここに処理を書く
}
}
これでループ自体を1ブロック分減らしかつ、ダイレクトにMapの中をみにいくので
処理時間をかなり軽減させることができます。
他にも便利な使い方
他にもキーや値でループを回すこともできます。
Map<Id,Account> accMap = new Map<Id,Account>([SELECT Id FROM Account]);
for ( Id accId : accMap.keyset() ) {
// 何か処理を書く
}
for ( Account acc : accMap.values() ) {
// 何か処理を書く
}
任意の値を含んでいるかの確認の場合は下記のように書きます。
accMap.containsKey(key); //trueもしくはfalseで返ってくる
また、下記のようなこともできます。
Map<Id,Account> accMap = new Map<Id,Account>([SELECT Id FROM Account]);
for ( Id accId : accMap.keyset() ) {
accMap.get(accId).Industry = 'Agriculture';
}
update accMap.values();
わざわざリストにしなくてもまとめてvaluesでDML操作もしちゃえます。
valuesはループも回せますが、中の値のDML操作は1としてカウントできるので便利です。
まとめ
今回はListよりも実は知っておくべきMapについてより詳しく解説しました。
是非用途に応じて使いこなせるようになっていきましょう!
その他の開発に関する記事はこちらです。
Developerも含めた試験問題にチャレンジしてみましょう。
Salesforce
・
Account Engagement・
CRM Analyticsの導入支援、
AppExchange
開発支援でお悩みなら
今すぐご相談ください