java.utilパッケージにあるArraysクラスには、
任意オブジェクトの配列を操作するさまざまなメソッドが既に用意されています。
下のリンクで調べてみましょう。
右下のようなクラスがあり、それを使った実験用の配列を生成し、その配列を取得するため、以下のクラスがあるとします。
(配列は、キーとなるshoの商品コードがバラバラに並ぶように変更しました。)
このgetData()で取得できる配列を数量(フィールド名suu)で、昇順に整列後、
数量が10のレコードを探す2分探索のプログラムを示します。
package rec; import rec.Record2; import rec.Record3; public class Rec23Data{ //実験用の配列を生成し、その配列を戻り値とするメソッド public static Record2[] getData(){ Record2[] a = new Record2[]{ new Record3("A02", 2, 200), new Record2("A01", 1), new Record2("A03", 3), new Record3("B01", 10,1000), new Record3("B02", 20,2000), new Record2("A04", 4), new Record2("B02", 30), new Record3("B03", 30,300), }; return a; } // iStart から(iEnd-1)の添え字情報を表示 public static void display(Record2[] a,int iStart,int iEnd){ for (int i = iStart; i < iEnd; i++){ a[i].display(i); } } public static void main(String[] arg){ Record2[] a = Rec23Data.getData(); Rec23Data.display(a, 0, 8);//確認用表示 } } |
Comparatorインターフェイスのcompareメソッドは、
2つの引数を比較しします。
よって、Comparatorインターフェイスをimplementsするクラスは、Record2でなくてもよく、
任意のクラスで作れます。次のコードは以前に作成したRecSuuCmp.javaの内容で、
Record2のsuuで数量を比較するComparatorインターフェイス実装クラスです。
Comparatorインターフェイスでは、equalsメソッドの宣言もあるので、
それも実装するところですが、Objectクラスで、既に存在するメソッドなので、
作らなくてもエラーになりません。
(必要なら、compareの戻り値が0になるような比較をequalsで行った時、戻り値がtrueになるような
同じ種類の等価が調べられよう作るべきでしょう。)
package rec; import java.util.Comparator; public class RecSuuCmp implements Comparator{ // o1とo2の大小比較を行うComparatorインターフェイス実装メソッド public int compare(Object o1, Object o2){ Record2 r1 = (Record2)o1; Record2 r2 = (Record2)o2; return r1.suu - r2.suu; } //等価チェックするComparatorインターフェイス実装メソッド // 必要なら、以下のコメントを外し、オーバーライドします。 // Objectクラスのequalsと同じチェックでよい場合は、省略します。 //public boolean equals(Object obj) //{ // return this.equals(obj);//Objectクラスのequals呼び出し //} } |
このComparatorの実装オブジェクトを
java.util.Arrays.sortメソッドに引数指定することで、
その比較方法に従って並び替えます。
ここでは、数量の比較をさせるRecSuuCmpオブジェクトを指定するので
数量で並び替えます。
その後、
java.util.Arrays.binarySearchメソッドで2分探索しています。 |
D:\java>java Test 0番目レコード 商品コード:A01 数量:1 1番目レコード 商品コード:A02 数量:2 単価:200 2番目レコード 商品コード:A03 数量:3 3番目レコード 商品コード:A04 数量:4 4番目レコード 商品コード:B01 数量:10 単価:1000 5番目レコード 商品コード:B02 数量:20 単価:2000 6番目レコード 商品コード:B02 数量:30 7番目レコード 商品コード:B03 数量:30 単価:300 10 の数量は、次のように見つかりました 4番目レコード 商品コード:B01 数量:10 単価:1000 D:\java>h; |
import rec.Record2; import rec.RecSuuCmp; public class Test { public static void main(String[] arg){ //バラバラな配列取得 Record2 [] a = rec.Rec23Data.getData(); RecSuuCmp cmpObj = new RecSuuCmp();//比較方法 java.util.Arrays.sort(a, cmpObj);//cmpObjの方法で並び替え rec.Rec23Data.display(a, 0, a.length); //cmpObjのデータを2分探索 Record2 key = new Record2("", 10); int iFound = java.util.Arrays.binarySearch(a, key, cmpObj); if (iFound == -1){ System.out.println("見つかりません"); System.exit(0);//実行終了 } System.out.print("10 の数量は、"); System.out.println("次のように見つかりました"); a[iFound].display(iFound); } } |
なお、このプログラム JDK1.5 以上でコンパイルすると、次のような警告がでます。
D:\java>javac Test.java 注: .\any\ObjArray.java の操作は、未チェックまたは安全ではありません。 注: 詳細については、-Xlint:unchecked オプションを指定して再コンパイルしてください。 D:\java>javac -Xlint:unchecked Test.java Test.java:11: 警告: [unchecked] 無検査変換です 検出値 : rec.RecSuuCmp 期待値 : java.util.Comparator<? super rec.Record2> java.util.Arrays.sort(a, cmpObj);//cmpObjの方法で並び替え ^ Test.java:11: 警告: [unchecked] 無検査メソッド呼び出し: java.util.Arrays の <T>s ort(T[],java.util.Comparator<? super T>) は (rec.Record2[],rec.RecSuuCmp) に適用 されます。 java.util.Arrays.sort(a, cmpObj);//cmpObjの方法で並び替え ^ Test.java:17: 警告: [unchecked] 無検査変換です 検出値 : rec.RecSuuCmp 期待値 : java.util.Comparator<? super rec.Record2> int iFound = java.util.Arrays.binarySearch(a, key, cmpObj); ^ Test.java:17: 警告: [unchecked] 無検査メソッド呼び出し: java.util.Arrays の <T>b inarySearch(T[],T,java.util.Comparator<? super T>) は (rec.Record2[],rec.Record2 ,rec.RecSuuCmp) に適用されます。 int iFound = java.util.Arrays.binarySearch(a, key, cmpObj); ^ 警告 4 個 D:\java>
警告は出ますが、問題なくコンパイルできます。
実は、上記Comparatorインターフェイスの使い方が、JDK1.4 以下の作り方で、
JDK1.5以上では、避けるべき作り方であるためです。詳細は後述しますが、このような警告を避ける場合は、
次の指定でコンパイルください。
D:\java>javac -source 1.4 Test.java D:\java>javac Test.java
-source 1.4の指定で、ソースの書き方が1.4であることを指定しています。