Mapの基礎
Map<key, record>を例にとると、代表的なメソッドとして下記が挙げられます。
戻り値 | メソッド | 説明 |
record | put(key, record) | mapにkeyとrecordのペアを格納 |
record | get(key) | keyに対応する値を取得 |
int | size() | 格納されているペア数を返す |
boolean | isEmpty() | 要素数がゼロか判定 |
boolean | containsKey(key) | 指定データがkeyに含まれているか判定 |
boolean | containsValue(record) | 指定データが値に含まれているか判定 |
Set<key> | keySet() | 格納されているkeyの一覧を返す |
List<Object> | values() | ペアのすべての値を含むリストを返す |
※mapの参照先レコードの値を更新した後、以下のコードでupdate可能
update accountMap.values();
Salesforce開発でMapを使う場面
ユースケースは無数にありますが、ApexにおいてListではなくMapを使う典型的なケースの一つは「idの照合に際して.conteinsKeyメソッドを利用することでfor文を不要にする」というものです。
以下で具体例を二つご紹介したいと思います。
ケース1(商談成約時に自動的に親契約レコードを自動生成)
trigger TriggerContractBefore on Opportunity (before update) {
Map<String, Opportunity> createContract = new Map<String, Opportunity>();
for (Opportunity record : Trigger.new) {
if (
record.StageName == '成約' &&
record.StageName <> trigger.oldMap.get(record.Id).StageName
){
System.debug('--- TriggerContractBefore : createContract --- #Record : ' + record.Id);
createContract.put(record.AccountId, record);
}
}
if (createContract.isEmpty() == false) {
List<Contract__c> insertContract = new List<Contract__c>();
for (Opportunity record : createContract.values()) {
insertContract.add(new Contract__c(
AccountId = record.AccountId,
Name = record.AccountName__c + '契約'
));
}
insert insertContract;
for (Contract__c contract : insertContract) {
Opportunity record = createContract.get(contract.AccountId);
record.Contract__c = contract.Id;
}
}
商談成約時に契約レコードを自動生成したあと、当該の商談を契約に紐づけるコードです。
mapを利用することで、契約レコード生成後に起点となった商談を契約に紐づけ直すところがスマートになっているのが分かるかと思います。
ケース2(レコード同士の値の一致判定)
List<Account> accountList = [Select Id, Name From Account];
List<Contact> contactList = [Select Name, AccountId From Contact];
Map<Id, Account> accountMap = new Map<Id, Account>(accountList);
for (Contact con : contactList) {
if(accountMap.containsKey(con.AccountId)) {
//なにか処理
}
}
for文でListを二つネストさせて回し、そこで両者の値を比較して処理を行っていくパターンの場合、Mapを利用するとforループが一つ減り、ガバナ制限への抵触を回避することが可能です。