SalesforceのApexでリストをフィルタリング|実例付き解説

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

(最終更新月:2024年2月)

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

「Salesforce Apexでリストの要素をどのようにフィルタリングするのか?」
「リストフィルタリングのための効率的なコーディング手法は?」
「Apexでリストをフィルタリングする際のベストプラクティスは?」

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

  • Salesforce Apexにおけるリストフィルタリングの基本概念
  • Apexでのリストフィルタリングの効率的な実装方法
  • リストフィルタリング時のパフォーマンスとメモリ管理のヒント

Apexでリストを効率的にフィルタリングすることは、データの処理速度とアプリケーションのパフォーマンス向上に直結します。

当記事では、forループ、ifステートメント、およびApexのコレクション操作を用いたフィルタリングテクニックを紹介し、特にLambda式やStream APIを使った最新の手法についても触れます。

Salesforceの開発者がよりクリーンで効率的なコードを書くためのベストプラクティスを学べる内容です。

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

Salesforce

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

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

筆者プロフィール

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

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

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

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

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

Apexリスト操作の基本

こちらでは、プログラミング言語Apexにおけるリスト操作の基本について解説します。

リストはApexプログラミングにおいてデータを管理し、流動的にアプリケーションを動作させるために不可欠なデータ構造です。

  • Apexにおけるリストの重要性
  • リストの基本操作(作成、追加、削除)
  • リストのイテレーション

Apexにおけるリストの重要性

リストはApexにおいて、複数の要素を順序付けて格納するための非常に強力なデータ構造です。

Salesforceの開発では、顧客や商談の情報など、複数のデータを扱う場面が数多くあり、それらを効率良く管理するためにリストは使われます。

また、リストを使用することで、コードの可読性やメンテナンス性も向上するため、開発の品質を高めることにも寄与します。

以下は、リストの宣言と初期化の例です。

List<String> myStringList = new List<String>(); // 文字列型のリストを作成

このようにリストを活用することで、Apexプログラミングにおいて柔軟かつ強力なデータ操作が可能になります。

リストの基本操作(作成、追加、削除)

リストの操作には、作成、追加、削除などの基本的な方法があります。

まずは、リストの作成から学びましょう。

以下のコードは新しいリストを作成する方法を示しています。

List<Integer> numbers = new List<Integer>(); // 整数型のリストを作成

作成したリストに値を追加するには、addメソッドを使います。

numbers.add(1); // リストに1を追加
numbers.add(2); // リストに2を追加

リストから特定の要素を削除する場合は、removeメソッドを使用。

リストのインデックスを指定して要素の削除が可能です。

numbers.remove(1); // リストの2番目(インデックスは0から始まる)の要素を削除

これらの基本的な操作をマスターすることで、リストを効果的に使いこなすことができるようになります。

リストのイテレーション

リスト内の各要素にアクセスするにはイテレーション(繰り返し処理)が必要です。

Apexではforループを使用してイテレーションをおこなえます。

以下は、リスト内の各整数に対して出力する簡単なループ例です。

List<Integer> numbers = new List<Integer>{1, 2, 3, 4, 5};
for(Integer num : numbers) {
    System.debug(num); // デバッグログに各要素を出力
}

このようにforループを使うことで、リスト内の要素を順に操作できます。

イテレーションを理解し適切に使用することは、リストを扱う上で非常に重要です。

リストのフィルタリング方法

リストのフィルタリングは、特定の条件にマッチする要素のみを選択するプロセスです。

ここでは、Apexにおけるリストのフィルタリング方法について学びます。

フィルタリング技術を身につけることで、Salesforceのデータ操作をより柔軟におこなえるようになります。

  • 条件文を使用したフィルタリング
  • filter メソッドによるアプローチ
  • ラムダ式と匿名クラスを活用した高度なフィルタリング

条件文を使用したフィルタリング

条件文を用いたフィルタリングは、以下のような手順でおこないます。

  1. ifステートメントを使用してリストの要素をチェック
  2. 条件に合致する要素だけを新しいリストへ追加

次の例は、数値リストから偶数のみを選び出す簡単なフィルタリングです。

List<Integer> numbers = new List<Integer>{1, 2, 3, 4, 5, 6};
List<Integer> evenNumbers = new List<Integer>();
for(Integer num : numbers) {
    if(num % 2 == 0) {
        evenNumbers.add(num);
    }
}
System.debug(evenNumbers); // 2, 4, 6 のみが含まれる

このように特定の条件でリストから要素を選択できます。

filter メソッドによるアプローチ

ApexではJavaScriptのような直接的なfilterメソッドが存在しませんが、独自のフィルタリングを実装するために条件ループが使えます。

例えば、特定の条件にマッチするアカウントのリストを作成する場合は、次のようなコーディングが可能です。

List<Account> allAccounts = [SELECT Id, Name FROM Account];
List<Account> filteredAccounts = new List<Account>();

for(Account a : allAccounts) {
    if(a.Name.startsWith('A')) {
        filteredAccounts.add(a);
    }
}

これで、名前が’A’で始まるアカウントのみがfilteredAccountsリストに格納されます。

ラムダ式と匿名クラスを活用した高度なフィルタリング

Apexでは直接的なラムダ式はサポートされていませんが、匿名クラスを利用して抽象メソッドをオーバーライドすることで、同様の機能を実装することが可能です。

次のコードスニペットは、各要素が特定の条件を満たす場合にのみ処理をおこなう匿名クラスの例です。

public interface Predicate {
    Boolean test(Account a);
}

List<Account> accounts = [SELECT Id, Name FROM Account];
List<Account> largeAccounts = new List<Account>();
Predicate isLargeAccount = new Predicate() {
    public Boolean test(Account a) {
        return a.AnnualRevenue > 1000000;
    }
};

for(Account a : accounts) {
    if(isLargeAccount.test(a)) {
        largeAccounts.add(a);
    }
}

この例では、年間収益が100万ドルを超えるアカウントを大口アカウントとみなし、それを判定する匿名クラスisLargeAccountを使用してフィルタリングしています。

フィルタリングの実践的応用

リストフィルタリングの技術は現実の問題を解決するために実際のアプリケーションで適用されます。

ここではSOQLクエリの結果をフィルタする方法、ユーザ入力を基にした動的フィルタリング、さらにフィルタリング戦略を考える際のパフォーマンスの観点など、フィルタリングの実践的な応用について見ていきます。

  • SOQLクエリ結果のフィルタリング
  • ユーザー入力に基づく動的フィルタリング
  • パフォーマンスの観点から見た最適なフィルタリング戦略

SOQLクエリ結果のフィルタリング

フィルタリングの典型的なシナリオはSOQLクエリの結果に対しておこなう場合です。

プログラム的にクエリ結果をさらに絞り込めます。

以下のコードはクエリの結果から特定の条件に一致する要素をフィルタリングする例です。

List<Contact> contacts = [SELECT Id, LastName, FirstName, Birthdate FROM Contact];
List<Contact> birthdayContacts = new List<Contact>();

for(Contact c : contacts) {
    if(c.Birthdate != null && c.Birthdate.month() == Date.today().month()) {
        birthdayContacts.add(c);
    }
}
System.debug(birthdayContacts); // 今月誕生日を迎えるコンタクトリスト

このようにSOQLクエリの結果に対する後処理としてフィルタリングを適用できます。

ユーザー入力に基づく動的フィルタリング

ユーザーからの入力に基づく動的なフィルタリングは、とくにユーザーインターフェイスが関わるアプリケーションにおいて重要です。

ユーザーが画面上で入力や選択したデータに基づいて、リストをフィルタリングします。

例えば、ユーザーが選択した産業分野に一致するアカウントのみを表示するコードは以下のようになります。

String selectedIndustry = 'Technology'; // ユーザーが選択した産業を想定
List<Account> accounts = [SELECT Id, Name, Industry FROM Account];
List<Account> filteredAccounts = new List<Account>();

for(Account a : accounts) {
    if(a.Industry == selectedIndustry) {
        filteredAccounts.add(a);
    }
}

ここでselectedIndustry変数はユーザーが選択した値を表し、該当する産業分野に所属するアカウントだけがフィルタリングされます。

パフォーマンスの観点から見た最適なフィルタリング戦略

フィルタリングを実装するにあたり、パフォーマンスは重要な考慮事項です。

とくに大量のデータを扱う場合は、ガバナ制限や処理速度の問題が生じる可能性があります。

効率的なフィルタリング戦略を採用するには、以下を考慮しましょう。

  • SOQLクエリでできるだけ絞り込むこと
  • フィルタリング処理で不要なイテレーションを避けること
  • 結果セットのサイズを予め制限することが有効です。

バッチ処理やasync/awaitパターンを使用することで、パフォーマンスの問題を解決する場合もあります。

リストフィルタリングのベストプラクティス

リストフィルタリングのコードを書く際には、ベストプラクティスを守ることが重要です。

これにはガバナ制限の考慮、コードの再利用とメンテナンス性の向上、そして大量データの処理においてパフォーマンスを保つといったアスペクトが含まれます。

  • ガバナ制限の考慮
  • コードの再利用とメンテナンス性
  • 大量データのフィルタリングとパフォーマンス

ガバナ制限の考慮

Salesforceではガバナ制限という実行制限が設けられており、これを意識してコードを書く必要があります。

とくにSOQLクエリやDML操作の実行回数には厳しい制限があるため、これらの操作をループ内で行わないように注意が必要です。

また、ループ内での過度なリスト操作も制限を超える原因となるため、フィルタリングロジックは効率よく設計する必要があります。

コードの再利用とメンテナンス性

再利用可能なコードを作成することは、長期的に見てメンテナンスの負担を軽減します。

フィルタリングロジックをメソッドとして分離し、パラメータ化することで、異なる条件で再利用が可能です。

また、コードは読みやすく、適切にコメントを付けることで、ほかの開発者が理解しやすく、修正しやすいものにしましょう。

大量データのフィルタリングとパフォーマンス

大量のデータに対してフィルタリングする際には、パフォーマンスが重要になります。

ひとつの戦略としては、SOQLクエリを使ってデータベースレベルでできるだけ絞り込み、アプリケーション側での処理を最小限に抑えること。

バッチ処理を検討したり、フィルタリング時にはインデックスが利用されるようにフィールドと条件を選定することも有効です。

リストフィルタリングに関するトラブルシューティング

開発したフィルタリングロジックに問題やバグが発生したときのトラブルシューティングのテクニックも知っておく必要があります。

  • 一般的な問題とその解決策
  • デバッグとパフォーマンスチューニング
  • 単体テストでのフィルタリングロジックの検証

一般的な問題とその解決策

フィルタリングの際、よく遭遇する問題には、以下のようなものがあります。

  • 予期しないデータの出現
  • ガバナ制限の超過
  • フィルタリングロジックの誤り

これらの問題に対処するためには、まずデータ検証を行うことが重要です。

データ型が正しいか、意図した範囲の値かなどを確認し、問題がデータによるものかロジックによるものかを特定します。

例えば、次のようなコードを記述することで、意図せずnullがリストに含まれていないかをチェックできます。

for(Account a : accounts) {
    if(a != null && a.Industry != null && a.Industry == selectedIndustry) {
        filteredAccounts.add(a);
    }
}

このようなnullチェックを行うことで、NullPointerExceptionを防げます。

デバッグとパフォーマンスチューニング

フィルタリングロジックが期待通りに機能しないとき、デバッグは誤りを検出し修正するプロセスです。

Salesforceでは、System.debug()ステートメントを使用して、プログラム内の変数の値や実行の流れを追跡できます。

パフォーマンスのチューニングには、実行時間を測定するLimitsクラスのメソッドが役立ちます。

例えば、SOQLクエリの実行回数は以下のコマンドで確認できます。

System.debug('SOQL queries: ' + Limits.getQueries());

これにより、ガバナ制限に達する前に問題を特定し対処できます。

単体テストでのフィルタリングロジックの検証

開発したフィルタリングロジックは単体テストを通じて検証することが重要です。

特定の条件下でコードが予期通りに動作することを保証できます。

テストケースを用意し、期待される結果と実際の結果を比較することにより、バグを発見しやすくなります。

以下が、簡単な単体テストの例です。

@isTest
private class FilterTest {
    @isTest static void testFilterAccountsByIndustry() {
        // テストデータの準備
        List<Account> testAccounts = new List<Account>{
            new Account(Name='TechCorp', Industry='Technology'),
            new Account(Name='HealthCorp', Industry='Healthcare')
        };
        insert testAccounts;

        // テスト対象のメソッドを実行
        List<Account> result = AccountFilter.filterByIndustry(testAccounts, 'Technology');

        // 期待する結果の検証
        System.assertEquals(1, result.size());
        System.assertEquals('TechCorp', result[0].Name);
    }
}

このテストでは、filterByIndustryメソッドが正しく特定業界のアカウントをフィルタリングすることを検証しています。

まとめ

Apexにおけるリスト操作とフィルタリングはデータ処理の中核をなす技術です。

これらの知識を活用することで、Salesforceのデータに対してより柔軟かつ効率的な操作が可能となり、開発者としてのスキルを大きく向上させられます。

常にベストプラクティスを心がけ、効果的にデータを扱うことで、高品質なアプリケーションを構築しましょう。

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