ApexでSOQLクエリ結果をSetに効率的に変換する方法


SOQLクエリで取得したList<SObject>をSet<Id>に変換する場面は、Apex開発でよく直面する課題です。このタスクを効率的に実行する方法を解説します。


基本的な解決方法

通常の方法として、forループを使ってリストを走査し、各オブジェクトのIdをセットに追加する方法があります:

List<Account> accounts = [SELECT Id, Name FROM Account];
Set<Id> accountIds = new Set<Id>();
for (Account acc : accounts) {
    accountIds.add(acc.Id);
}

この方法は動作しますが、クエリで取得するオブジェクト数が多い場合、スクリプトステートメントを多く消費してしまいます。


Mapを活用した効率的な方法

Apexには、Mapコンストラクタを利用してList<SObject>から直接Set<Id>を取得する便利な方法があります。この方法では、追加のスクリプトステートメントを消費せずに、Idを効率的に抽出できます。

以下はその例です:

List<Account> accounts = [SELECT Id, Name FROM Account];

// MapコンストラクタでリストをMapに変換し、keySet()でIdのセットを取得
Set<Id> accountIds = (new Map<Id, Account>(accounts)).keySet();

この方法の仕組み

  1. new Map<Id, SObject>(List<SObject>)

    このコンストラクタは、リストをIdをキーとするMapに変換します。リスト内の各オブジェクトのIdがキーとなり、オブジェクト自体が値として格納されます。
  2. keySet()

    作成したMapからキー(Id)だけを取り出し、Set<Id>として返します。
  3. メモリ効率

    Mapは一時的なものであり、使用後にスコープ外となるため、ヒープスペースの消費を最小限に抑えることができます。

実用例

以下は、Set<Id>を別のメソッドに渡す例です:

public class AccountService {
    public void processAccounts() {
        List<Account> accounts = [SELECT Id, Name FROM Account WHERE CreatedDate = LAST_N_DAYS:30];
        Set<Id> accountIds = (new Map<Id, Account>(accounts)).keySet();
        performAction(accountIds);
    }

    private void performAction(Set<Id> ids) {
        // 他のロジックでIdセットを使用
        System.debug('Processing accounts with Ids: ' + ids);
    }
}

注意点

  • Idフィールド専用

    このテクニックは、Idフィールドにのみ適用可能です。その他のフィールドでSetを作成する場合は、別途ループ処理が必要です。
  • 重複の排除

    List内に重複があっても、Set<Id>では自動的に重複が排除されます。

コメント