SalesforceのApexでMapを使いこなそう|実例付き解説

※本サイトにはプロモーション・広告が含まれています。

(最終更新月: 2023年12月)

✔以下の疑問をお持ちの方へ向けた記事です

「Salesforce ApexでMapコレクションはどのように使用するのだろうか?」
「ApexのMapコレクションの基本的な使い方とは?」
「ApexでMapコレクションを使った具体的なプログラミング例が見たい」

✔当記事を読むことで得られる知識

  • Salesforce ApexにおけるMapコレクションの基本的な概念
  • Mapの作成、操作、およびアクセスの基本的な方法
  • Mapを使用したApexプログラミングの具体的な例

当記事では、Salesforceの開発言語であるApexにおけるMapコレクションの使い方について詳しく解説します。

Salesforceの開発者やApexを学び始めた方々にとって、役立つ情報が満載です。

ぜひ最後までご覧ください。

Salesforce

定義や属性などは公式ガイドを必ず参考にしましょう。

当記事では、主にその使い方を具体例とともに解説します。

筆者プロフィール

筆者プロフィールアイコン

【現職】プロダクトマネージャー

プロダクトマネージャーとして、Apex・Visualforceの開発エンジニアとして、以下のようなプロジェクトに従事してきました

  • 新規事業の立ち上げに伴うビジネスプロセス構築とSalesforceのカスタマイズ
  • SFDXを活用した大規模リリース
  • Visualforce等による一般ユーザー向けサイト・アプリケーションの構築

相談・業務の依頼も承ります。ご質問・ご希望をお問い合わせください。

SalesforceのApexで使うMapの基本

こちらでは、Salesforceで使用される言語「Apex」のMapについてお伝えしていきます。

データの効率的な管理と検索、処理の最適化に役立つでしょう。

  • Salesforce Apexの基本
  • Mapの基本概念
  • ApexとMapの組み合わせの利点
  • Mapを使用するシナリオと例

Salesforce Apexの基本

Apexは、Salesforceのプラットフォーム上で動作するオブジェクト指向のプログラミング言語です。

この言語を用いて、Salesforce内のデータに対してさまざまな処理をおこなえます。

Account myAccount = new Account(Name='サンプル取引先'); 

新しい顧客アカウントを作成するなどの操作が可能。

ApexをマスターすることでSalesforceの機能をフルに活用し、カスタマイズされたビジネスロジックの実装が可能になるのです。

ベースとなるのはJava言語ですが、多少異なります。

ただしJavaの知識がある方はスムーズに扱えるでしょう。

Mapの基本概念

Mapはキーと値のペアで構成されるコレクション型データ構造のひとつ。

keyとvalueのペアとしてデータを格納することで、キーを使って高速にデータを取り出すことが可能です。

例としては、以下のとおり。

Map<Id, Account> accountMap = new Map<Id, Account>();

Idをキーとし、Accountオブジェクトを値とするMapを宣言します。

この基本的な概念を把握することは、Apex内でのデータ構造を扱う上で非常に重要です。

ApexとMapの組み合わせの利点

ApexでMapを利用することにはいくつかの明確な利点があります。

  1. Mapを用いることでデータの検索時間を短縮し、効率的なコードを書くことが可能
  2. データを重複なく一元管理できるため、整合性を保てる
accountMap.get(someId);

特定のIdに対応するAccountオブジェクトを素早く取得できます。

これらの利点は、大量のデータを扱う際に特に価値を発揮します。

Mapを使用するシナリオと例

Mapはさまざまなシナリオで使用されます。

  • データを一時的に格納する場面
  • オブジェクト間の関連付けを必要とする処理
for (Account acc : [SELECT Id, Name FROM Account]) { accountMap.put(acc.Id, acc); } 

コードを使い、SOQLクエリで取得したAccountレコードをMapに格納し、キー(Id)でアクセスするシナリオが考えられます。

このような方法は、処理の簡潔さと性能の向上をもたらします。

セールスフォースにはガバナ制限といい、一度に処理できるSOQLクエリ数などに制限があります。

何度も呼び出すことを避けるために別の形で保存しておくこともときには必要なのです。

基本的なMap操作

こちらでは、Apex Salesforceにおける「基本的なMap操作」について紹介します。

「基本的なMap操作」をマスターすることで、Apexコーディング時のデータ構造への理解が深まり、効率的なプログラミングが可能になるでしょう。

  • Mapの作成と初期化
  • 要素の追加とアクセス
  • Mapの繰り返し処理
  • キーと値の操作

Mapの作成と初期化

Mapを作成するには、Map型の変数を宣言し、必要に応じて初期化しましょう。

Map<String, Integer> wordCount = new Map<String, Integer>();

列をキーとし、整数を値とする空のMapを生成します。

またMapの初期化には、リテラル表現を用いて、以下のように直接値を設定する方法もあります。

Map<String, Integer> wordCount = {'hello': 1, 'world': 2}; 

要素の追加とアクセス

Mapに要素を追加するには、putメソッドを使用します。

wordCount.put('salesforce', 5);

‘salesforce’というキーに対して5という値をMapに追加できます。

また、Mapから値にアクセスするにはgetメソッドを用いるのが一般的。

Integer count = wordCount.get('salesforce'); 

‘salesforce’キーに対応する値を取得できます。

Mapの繰り返し処理

Mapを繰り返し処理する方法としては、forループを利用する方法があります。

キーのセットか値のリストを繰り返し処理する方法です。

for (String key : wordCount.keySet()) { System.debug(key + ' -> ' + wordCount.get(key)); } 

Map内のすべてのキーに対してその値をデバッグログに出力できます。

キーと値の操作

Map内のキーと値を操作する際には、さまざまなメソッドやアプローチが役立ちます。

たとえば、containsKeyメソッドはMapに特定のキーが存在するかをチェックするのに使用されるもの。

if (wordCount.containsKey('apex')) { /* 処理 */ } 

containsKeyで変えるのはBoolean型です。

また、removeメソッドはMapからキーと対応する値を削除する時に便利です。

wordCount.remove('hello'); 

コードで’hello’キーとその値をMapから削除できます。

実践的なMapの使用例

こちらでは、「実践的なMapの使用例」について見ていきたいと思います。

実践的なMapの使用例を学ぶことで、実際のビジネス要件に合わせたApexコーディングがおこなえるでしょう。

  • データの管理と検索
  • 効率的なデータ処理
  • エラー処理とデバッグ
  • 複数のMapを使用する方法

データの管理と検索

データの管理と検索の文脈において、Mapは非常に有効なツールです。

バルクデータに対して、特定のフィールド値をキーとして使用することで、SOQLクエリ無しに関連レコードを迅速に検索できます。

たとえば、以下のコードなどが一例です。

Map<String, Contact> contactByEmail = new Map<String, Contact>();
for (Contact c : [SELECT Email, Name FROM Contact]) { contactByEmail.put(c.Email, c); } 

EmailをキーとしてContactオブジェクトをMapに格納。

あとからEmailアドレスを使って即時に関連するContact情報にアクセスできるようになります。

効率的なデータ処理

大量のレコードをループしながら処理する際に、処理速度が向上します。

Mapを活用することで、ロジックが単純化されるからです。

Map<Id, List<Opportunity>> oppsByAccountId = new Map<Id, List<Opportunity>>();

Id(アカウントID)をキーとして、そのアカウントに関連するOpportunityオブジェクトのリストを格納しています。

あとになって特定のアカウントIDのOpportunity一覧をすばやく取得し、バッチ処理などをおこなう際に利用できます。

エラー処理とデバッグ

Mapは、エラー処理とデバッグをおこなう際にも使えます。

エラーメッセージをキーとするMapを作ることで、特定のエラーに対応するアクションを効率よく管理できるからです。

Map<String, String> errorMessageToAction = new Map<String, String>(); 
errorMessageToAction.put('INVALID_ID', 'レコードIDを調べてください。'); 

‘INVALID_ID’エラーメッセージが表示された場合の対応策をMapから取得できます。

複数のMapを使用する方法

複雑なシナリオでは、複数のMapを組み合わせて使用することがあります。

ユーザーによって異なるアクセス権を持たせたい場合の例で見てみましょう。

Map<Id, Map<Id, AccessLevel>> userToAccessMap = new Map<Id, Map<Id, AccessLevel>>();

二重Mapを使用することで、外側のMapでユーザーIDをキーにし、内側のMapでレコードIDとアクセスレベルを管理できます。

この技法は、関連性が高いデータのグループ化に役立ちます。

Apex Mapの高度なテクニック

こちらでは、Apex Mapの高度なテクニックを取り上げ、探求していきたいと思います。

より洗練されたデータ処理が可能になり、複雑なビジネスロジックへの対応力が向上するはずです。

  • カスタムオブジェクトとの連携
  • パフォーマンスの最適化
  • セキュリティと保守性
  • マップの高度な集約とデータ処理

カスタムオブジェクトとの連携

Apexでは、カスタムオブジェクトやカスタムフィールドとの連携も非常に重要です。

Mapを用いることで、カスタムオブジェクトのインスタンスをキーにして、関連するデータを管理できます。

Map<CustomObject__c, List<RelatedRecord__c>> customMap = new Map<CustomObject__c, List<RelatedRecord__c>>(); 

カスタムオブジェクトをMapに格納し、関連性を効果的に管理できます。

パフォーマンスの最適化

Mapを用いたパフォーマンスの最適化では、以下のような工夫も重要です。

  • ループ内のSOQLクエリを避ける
  • サイズを考慮したコードを書く
Map<Id, AggregateResult> summaryResults = new Map<Id, AggregateResult>([SELECT AccountId, SUM(Amount) FROM Opportunity GROUP BY AccountId]); 

集約クエリの結果をMapに格納しておくと、後から何度もクエリを実行せずに集約結果にアクセスでき、パフォーマンスを向上させます。

AggregateResultは、集計結果を受け取る際の型です。

セキュリティと保守性

Mapのデータ構造を使用する際にも、セキュリティと保守性を考慮することが非常に重要です。

データアクセスに関する制約をメソッドやクラスの設計に組み込むことで、データの整合性を保ちながら安全に処理をおこなえます。

public class AccessManager { 
 private Map<Id, UserAccess> accessMap; 
 public AccessManager() { 
  accessMap = new Map<Id, UserAccess>(); // データの初期化など 
 } 
 // アクセス権の確認などのメソッド 
} 

Mapをプライベート変数として扱い、安全なアクセスしかできないように設計する方法です。

マップの高度な集約とデータ処理

複雑なデータ処理においては、Mapの高度な集約も効果的です。

複数のデータソースからの情報を統合し、意味のある結果を導き出せます

Map<String, CombinedResult__c> resultsMap = new Map<String, CombinedResult__c>();
for (String key : combinedResults.keySet()) {
    CombinedResult__c value = combinedResults.get(key);
    if (resultsMap.containsKey(key)) {
        resultsMap.get(key).addResult(value);
    } else {
        resultsMap.put(key, value);
    }
}

異なるソースからのデータを組み合わせた新しい結果オブジェクトをMap内で管理し、分析やレポート作成に活用します。

Mapのメソッド一覧とその例文

以下は、ApexでのMapクラスに対して使用できるメソッドの一覧表です。

各メソッドのタイトル、その意味、および例文を含みます。

メソッド名例文意味
clear()myMap.clear();すべてのキーと値の対応付けを削除。
clone()Map clonedMap = myMap.clone();対応付けの重複コピーを作成。
containsKey(key)Boolean hasKey = myMap.containsKey(‘key1’);指定されたキーが含まれている場合は true 。
deepClone()Map clonedMap = myMap.deepClone();sObjectレコードを含む、対応付けの重複コピーを作成。
equals(map2)Boolean isEqual = myMap.equals(anotherMap);対応付けを比較。両方の対応付けが等しい場合は true 、そうでない場合は false を返す。
get(key)Integer value = myMap.get(‘key1’);指定したキーに対する値、またはこのキーの対応付けに値が含まれていない場合は null を返す。
getSObjectType()Schema.SObjectType sType = myMap.getSObjectType();Map値を構成するsObjectデータ型のトークンを返す。
hashCode()Integer hashCode = myMap.hashCode();この対応付けのhashcode を返す。
isEmpty()Boolean isEmpty = myMap.isEmpty();対応付けのキーと値のペアが存在しない場合にtrue を返す。
keySet()Set keys = myMap.keySet();すべてのキーを含むセットを返す。
put(key, value)myMap.put(‘key1’, 123);指定された値を指定したキーに関連付ける。
putAll(fromMap)myMap.putAll(anotherMap);指定先のMapから全中身を元のMapにコピー。
putAll(sobjectArray)myMap.putAll(sObjectsArray);sObject レコードのリストを、Map、または Map として宣言されている対応付けに追加。
remove(key)Integer removedValue = myMap.remove(‘key1’);指定されたキーを削除し、対応する値がある場合は、その値を返す。
size()Integer size = myMap.size();Map内のキー-値のペアの数を返す。
toString()String mapString = myMap.toString();Mapの文字列表現を返す。
values()List<Integer> values = myMap.values();対応付けのすべての値を含むリストを返します。
参考: Map クラス | Apex 開発ガイド

toStringは以下のように表現されます。

Map<String, Integer> wordCount = new Map<String, Integer>();
wordCount.put('hello', 1);
wordCount.put('world',2);

System.debug(wordCount.toString());

//以下のように出力されます。
{hello=1, world=2}

よくある質問とトラブルシューティング

「よくある質問とトラブルシューティング」セクションでは、Apex Mapの使用中に出会う可能性のある一般的な問題とその解決策について解説します。
この情報により、開発者はよりスムーズな開発プロセスを経験し、問題発生時の対応力を強化できるはずです。

  • 一般的なエラーとその解決法
  • パフォーマンス問題の診断
  • コミュニティとリソース
  • ベストプラクティスと効率的なコーディング

一般的なエラーとその解決法

Mapを使う際には「NullPointerException」や「KeyNotFoundException」といったエラーに遭遇することがあります。

これらは、主にMapがnullであったり、Map内に該当するキーが存在しない場合に発生するものです。

著者の経験上、以下の順番でチェックすると良いでしょう。

  1. 初期化がおこなわれているか
  2. 適切なnullチェック
  3. Map内のキーの存在チェック
  4. 型変換の確認をおこなう

初期化していないMapに値を入れようとすると、エラーとなりますので必ず初期化を忘れずにおこないましょう。

エラーは以下のようになります。

System.NullPointerException: Attempt to de-reference a null object

パフォーマンス問題の診断

パフォーマンスの問題は、Mapが非常に大きい、または繰り返し処理の中で非効率的にアクセスされる場合に発生することがあります。

これらの問題を診断するためには、Mapのサイズや反復処理の方法を検討し、必要に応じてデータ構造の再設計が重要です。

ベストプラクティスと効率的なコーディング

ApexでMapを使用する際のベストプラクティスには、以下のようなものがあります。

  • 適切なデータ型の選択
  • キーとしての意味のある値の使用
  • 不要なMap操作の削減
  • コードの可読性とメンテナンス性を保つ

効率的なコーディングは、システムのパフォーマンスを向上させ、将来のエラーを防ぐのに役立ちます。

まとめ

ApexでのMapの使用は、Salesforce開発において不可欠なスキルです。

当記事では、Mapの基本操作から高度な使用方法までを網羅しているはず。

Mapはデータの管理、検索、効率的な処理に非常に有効であり、適切に使用することで、Salesforceアプリケーションのパフォーマンスと保守性を大幅に向上させられます。

常にベストプラクティスを念頭に置きながら、これらのテクニックを活用してください。

タイトルとURLをコピーしました