背景
特定の値が一致したらMap<String, String>
のキーを探したいというメソッドを作るためです。
そこでJS好きの僕はfindIndexを思い出しました。
ロジック
ApexでJavaScriptのようなMap<String, String>
のfindIndex
機能を実装するには、マップのエントリを反復処理し、各エントリを条件と照合する必要があります。Apexのマップは配列やリストのように順序付けられたインデックスを維持しないため、特定のキー値ペアの「インデックス」を条件に基づいて見つける必要がある場合、通常はリストを使用してこの機能をシミュレートします。
実装
public class MapUtils {
/**
* 指定された条件を満たすMap<String, String>の最初のエントリのインデックスを見つけます。
*
* @param map 検索するマップ。
* @param condition 各エントリに対して評価する条件。
* @return 条件を満たす最初のマップエントリのインデックス、見つからない場合は-1。
*/
public static Integer findIndex(Map<String, String> map, MapCondition condition) {
// インデックスベースの順序を持つために、マップキーをリストに変換する
List<String> keys = new List<String>(map.keySet());
// 条件を満たす最初のキーを見つけるためにキーのリストを反復処理する
for (Integer i = 0; i < keys.size(); i++) {
String key = keys[i];
String value = map.get(key);
// 現在のエントリが条件を満たしているかどうかをチェック
if (condition.evaluate(key, value)) {
return i; // 条件が満たされた場合はインデックスを返す
}
}
return -1; // 条件を満たすエントリがない場合は-1を返す
}
/**
* マップエントリに対して評価する条件を定義するインターフェース。
*/
public interface MapCondition {
Boolean evaluate(String key, String value);
}
}
使う場面
次に、上記のユーティリティクラスを使用して、カスタム条件に基づいてマップエントリのインデックスを見つけることができます。例えば:
// 使用例
Map<String, String> myMap = new Map<String, String>{
'a' => 'apple',
'b' => 'banana',
'c' => 'cherry'
};
// 値が'b'で始まるかどうかをチェックする条件を定義
MapUtils.MapCondition condition = new MapUtils.MapCondition() {
public Boolean evaluate(String key, String value) {
return value.startsWith('b');
}
};
// 条件を満たす最初のエントリのインデックスを見つける
Integer index = MapUtils.findIndex(myMap, condition);
System.debug('Index: ' + index); // マップが挿入順序を保持していると仮定すると、1を出力するはずです
注意点
Apexにおけるマップキーのイテレーション順序は通常、挿入された順に従いますが、この挙動が公式文書で明確に保証されている訳ではありません。そのため、順序が特定の使用ケースにとって重要である場合、Listを活用するか、または順序の整合性を確実にするためにキーの別のリストを保持することを推奨します。これにより、予期せぬ挙動を防ぎ、アプリケーションが正確に要件を満たすことができるようになります。