sObject のリストの並び替え
sObject の場合、並び替えは昇順で、次のセクションで説明する一連の比較ステップを使用します。sObject のカスタム並び替え順は、Comparable インターフェースを実装する Apex クラスで sObject をラップして作成することができます。また、Comparator を実装するクラスをパラメータとして並び替えメソッドに渡して作成することもできます。「sObject のカスタム並び替え順」を参照してください。
sObject のデフォルトの並び替え順
- sObject 型の表示ラベル。
たとえば、Account sObject は Contact の前になります。
- Name 項目 (該当する場合)。
たとえば、リストに Alpha と Beta という名前の 2 つの取引先がある場合、取引先 Alpha が取引先 Beta よりも前になります。
- 標準項目。ID 項目と Name 項目を除き、アルファベット順で最初の項目から使用されます。
たとえば、2 つの取引先が同じ名前の場合、並び替えに使用される最初の標準項目は AccountNumber です。
- カスタム項目。アルファベット順で最初の項目から使用されます。
たとえば、2 つの取引先の名前と標準項目が同じで、FieldA と FieldB という 2 つのカスタム項目がある場合、並び替えでは FieldA の値が最初に使用されます。
この一連のすべてのステップが実行されるとは限りません。たとえば、同じ種別で一意の Name 値がある 2 つの sObject がリストに含まれている場合、このリストは、Name 項目に基づいて並び替えられ、並び替えはステップ 2 で停止します。別の例で、名前が同じか sObject に Name 項目がない場合、並び替えはステップ 3 まで進み、標準項目を基準に並び替えられます。
テキスト項目の場合、並び替えアルゴリズムは Unicode 並び替え順を使用します。また、空の項目は並び替え順で空でない項目より前になります。
Account sObject のリストの並び替えの例を次に示します。この例では、Name 項目が使用されて、リスト内で Acme 取引先が 2 つの sForce 取引先より前に配置されることを示します。sForce という名前の取引先が 2 つあり、アルファベット順で Industry 項目は Site 項目より前になるため、Industry 項目が残りの取引先の並び替えに使用され���す。
1Account[] acctList = new List<Account>();
2acctList.add( new Account(
3 Name='sForce',
4 Industry='Biotechnology',
5 Site='Austin'));
6acctList.add(new Account(
7 Name='sForce',
8 Industry='Agriculture',
9 Site='New York'));
10acctList.add(new Account(
11 Name='Acme'));
12System.debug(acctList);
13
14acctList.sort();
15Assert.areEqual('Acme', acctList[0].Name);
16Assert.areEqual('sForce', acctList[1].Name);
17Assert.areEqual('Agriculture', acctList[1].Industry);
18Assert.areEqual('sForce', acctList[2].Name);
19Assert.areEqual('Biotechnology', acctList[2].Industry);
20System.debug(acctList);次の例は前の例と同様ですが、Merchandise__c カスタムオブジェクトを使用する点が異なります。この例では、Name 項目が使用されて、リスト内で Notebooks 商品が Pens より前に配置されることを示します。Name 項目値が Pens の商品 sObject が 2 つあるため、Description 項目が残りの商品品目の並び替えに使用されます。Description 項目が並び替えに使用されるのは、アルファベット順で Price 項目と Total_Inventory 項目の前になるためです。
1Merchandise__c[] merchList = new List<Merchandise__c>();
2merchList.add( new Merchandise__c(
3 Name='Pens',
4 Description__c='Red pens',
5 Price__c=2,
6 Total_Inventory__c=1000));
7merchList.add( new Merchandise__c(
8 Name='Notebooks',
9 Description__c='Cool notebooks',
10 Price__c=3.50,
11 Total_Inventory__c=2000));
12merchList.add( new Merchandise__c(
13 Name='Pens',
14 Description__c='Blue pens',
15 Price__c=1.75,
16 Total_Inventory__c=800));
17System.debug(merchList);
18
19merchList.sort();
20Assert.areEqual('Notebooks', merchList[0].Name);
21Assert.areEqual('Pens', merchList[1].Name);
22Assert.areEqual('Blue pens', merchList[1].Description__c);
23Assert.areEqual('Pens', merchList[2].Name);
24Assert.areEqual('Red pens', merchList[2].Description__c);
25System.debug(merchList);sObject のカスタム並び替え順
リスト内の sObject のカスタム並び替え順を作成するには、Comparator インターフェースを実装し、それをパラメータとして List.sort メソッドに渡します。
sObject のラッパークラスを作成し、Comparable インターフェースを実装する方法もあります。ラッパークラスに対象の sObject を含め、並び替えロジックを指定する Comparable.compareTo メソッドを実装します。
例
次の例では、Amount 項目に基づいて 2 つの商談を比較する Comparator インターフェースを実装します。
1public class OpportunityComparator implements Comparator<Opportunity> {
2 public Integer compare(Opportunity o1, Opportunity o2) {
3 // The return value of 0 indicates that both elements are equal.
4 Integer returnValue = 0;
5
6 if(o1 == null && o2 == null) {
7 returnValue = 0;
8 } else if(o1 == null) {
9 // nulls-first implementation
10 returnValue = -1;
11 } else if(o2 == null) {
12 // nulls-first implementation
13 returnValue = 1;
14 } else if ((o1.Amount == null) && (o2.Amount == null)) {
15 // both have null Amounts
16 returnValue = 0;
17 } else if (o1.Amount == null){
18 // nulls-first implementation
19 returnValue = -1;
20 } else if (o2.Amount == null){
21 // nulls-first implementation
22 returnValue = 1;
23 } else if (o1.Amount < o2.Amount) {
24 // Set return value to a negative value.
25 returnValue = -1;
26 } else if (o1.Amount > o2.Amount) {
27 // Set return value to a positive value.
28 returnValue = 1;
29 }
30 return returnValue;
31 }
32}次のテストでは、Comparator オブジェクトのリストを並び替え、リストの要素が商談金額を基準に並び替えられていることを確認します。
1@isTest
2private class OpportunityComparator_Test {
3
4 @isTest
5 static void sortViaComparator() {
6 // Add the opportunity wrapper objects to a list.
7 List<Opportunity> oppyList = new List<Opportunity>();
8 Date closeDate = Date.today().addDays(10);
9 oppyList.add( new Opportunity(
10 Name='Edge Installation',
11 CloseDate=closeDate,
12 StageName='Prospecting',
13 Amount=50000));
14 oppyList.add( new Opportunity(
15 Name='United Oil Installations',
16 CloseDate=closeDate,
17 StageName='Needs Analysis',
18 Amount=100000));
19 oppyList.add( new Opportunity(
20 Name='Grand Hotels SLA',
21 CloseDate=closeDate,
22 StageName='Prospecting',
23 Amount=25000));
24 oppyList.add(null);
25
26 // Sort the objects using the Comparator implementation
27 oppyList.sort(new OpportunityComparator());
28 // Verify the sort order
29 Assert.isNull(oppyList[0]);
30 Assert.areEqual('Grand Hotels SLA', oppyList[1].Name);
31 Assert.areEqual(25000, oppyList[1].Amount);
32 Assert.areEqual('Edge Installation', oppyList[2].Name);
33 Assert.areEqual(50000, oppyList[2].Amount);
34 Assert.areEqual('United Oil Installations', oppyList[3].Name);
35 Assert.areEqual(100000, oppyList[3].Amount);
36 // Write the sorted list contents to the debug log.
37 System.debug(oppyList);
38 }
39}例
次の例では、Opportunity のラッパークラス Comparable を作成する方法を示します。このクラスの compareTo メソッドの実装では、Amount 項目 (このインスタンスに含まれるクラスメンバー変数)、およびメソッドに渡された商談オブジェクトに基づいて 2 つの商談を比較します。
1public class OpportunityWrapper implements Comparable {
2
3 public Opportunity oppy;
4
5 // Constructor
6 public OpportunityWrapper(Opportunity op) {
7 // Guard against wrapping a null
8 if(op == null) {
9 Exception ex = new NullPointerException();
10 ex.setMessage('Opportunity argument cannot be null');
11 throw ex;
12 }
13 oppy = op;
14 }
15
16 // Compare opportunities based on the opportunity amount.
17 public Integer compareTo(Object compareTo) {
18 // Cast argument to OpportunityWrapper
19 OpportunityWrapper compareToOppy = (OpportunityWrapper)compareTo;
20
21 // The return value of 0 indicates that both elements are equal.
22 Integer returnValue = 0;
23 if ((oppy.Amount == null) && (compareToOppy.oppy.Amount == null)) {
24 // both wrappers have null Amounts
25 returnValue = 0;
26 } else if ((oppy.Amount == null) && (compareToOppy.oppy.Amount != null)){
27 // nulls-first implementation
28 returnValue = -1;
29 } else if ((oppy.Amount != null) && (compareToOppy.oppy.Amount == null)){
30 // nulls-first implementation
31 returnValue = 1;
32 } else if (oppy.Amount > compareToOppy.oppy.Amount) {
33 // Set return value to a positive value.
34 returnValue = 1;
35 } else if (oppy.Amount < compareToOppy.oppy.Amount) {
36 // Set return value to a negative value.
37 returnValue = -1;
38 }
39 return returnValue;
40 }
41}次のテストでは、OpportunityWrapper オブジェクトのリストを並び替え、リストの要素が商談金額を基準に並び替えられていることを確認します。
1@isTest
2private class OpportunityWrapperTest {
3 static testmethod void test1() {
4 // Add the opportunity wrapper objects to a list.
5 OpportunityWrapper[] oppyList = new List<OpportunityWrapper>();
6 Date closeDate = Date.today().addDays(10);
7 oppyList.add( new OpportunityWrapper(new Opportunity(
8 Name='Edge Installation',
9 CloseDate=closeDate,
10 StageName='Prospecting',
11 Amount=50000)));
12 oppyList.add( new OpportunityWrapper(new Opportunity(
13 Name='United Oil Installations',
14 CloseDate=closeDate,
15 StageName='Needs Analysis',
16 Amount=100000)));
17 oppyList.add( new OpportunityWrapper(new Opportunity(
18 Name='Grand Hotels SLA',
19 CloseDate=closeDate,
20 StageName='Prospecting',
21 Amount=25000)));
22
23 // Sort the wrapper objects using the implementation of the
24 // compareTo method.
25 oppyList.sort();
26
27 // Verify the sort order
28 Assert.areEqual('Grand Hotels SLA', oppyList[0].oppy.Name);
29 Assert.areEqual(25000, oppyList[0].oppy.Amount);
30 Assert.areEqual('Edge Installation', oppyList[1].oppy.Name);
31 Assert.areEqual(50000, oppyList[1].oppy.Amount);
32 Assert.areEqual('United Oil Installations', oppyList[2].oppy.Name);
33 Assert.areEqual(100000, oppyList[2].oppy.Amount);
34
35 // Write the sorted list contents to the debug log.
36 System.debug(oppyList);
37 }
38}