java.utilパッケージにあるArraysクラスには、Comparatorインターフェイスを利用した sortやbinarySearchのメソッドが、用意されており、それを利用します。
右下のようなクラスがあり、それを使った実験用の配列を生成し、その配列を取得するため、
以下のクラスがあるとします。
(配列は、キーとなるsuuの数量がバラバラに並ぶように変更しました。)
このgetData()で取得できる配列を数量で、昇順に整列後、4の数量のレコードを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インターフェイスを実装した配列要素にする必要があります。
JDK 1.5以上のGenerics版Comparatorインターフェイスは次のようになっています。これ以前(JDK 1.4以下)の
コードと比較ください。(java.utilパッケージです)
public interface Comparator<T> { int compare(T o1, T o2); boolean equals(Object obj); }
このcompareメソッドは、
2つの引数を比較しします。(一般にo1からo2を引いたイメージの整数を戻り値にします)
よって、Comparatorインターフェイスをimplementsするクラスは、Record2でなくてもよく、
任意のクラスで作れます。また、equalsメソッドの宣言もあるので、
それも実装する必要がある所ですが、Objectクラスで、既に存在するメソッドなので、
作らなくてもエラーになりません。
(作る場合はcompareの戻り値が0になるような比較をequalsで行った時、戻り値がtrueになるように作るべきです。)
この比較専用クラスをRecSuuCmpの名前で作った例を以下に示します。
上記<T>を利用する時の
<具体的名前>として、以下で<Record2>を指定しています。
同時にこれは、Record2を作る時の、
<総称的名前>として使っていることになります。
以前に紹介した前のRecSuuCmp.javaコードと比較して見ましょう。(キャストが無いです)
package rec; import java.util.Comparator; public class RecSuuCmp implements Comparator <Record2> { // o1とo2の大小比較を行うComparatorインターフェイス実装メソッド public int compare(Record2 o1, Record2 o2){ |
このComparatorが実装されたオブジェクトは、この比較方法に従って、
既にある
java.util.Arrays.sortメソッドで昇順に並び替えることができ、
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 の商品コードは、次のように見つかりました 3番目レコード 商品コード:A04 数量:4 D:\java> |
import rec.Record2; import rec.RecSuuCmp; public class Test { public static void main(String[] arg){ //バラバラな配列取得 Record2[] a = rec.Rec23Data.getData(); //10の値を探せて、2つのRecord2を比較するオブジェクト //RecSuuCmp suuComp = new RecSuuCmp(10); java.util.Comparator<Record2> suuComp = new RecSuuCmp(); java.util.Arrays.sort(a, suuComp);//並び替え rec.Rec23Data.display(a, 0, a.length); Record2 key = new Record2("", 4); //探索 int iFound = java.util.Arrays.binarySearch(a, key, suuComp); if (iFound == -1){ System.out.println("見つかりません"); System.exit(0);//実行終了 } System.out.print("10 の商品コードは、"); System.out.println("次のように見つかりました"); a[iFound].display(iFound); } } |
java.utilパッケージ内のArraysクラスのsortメソッド
やbinarySearchメソッドは、Comparatorを引数とするメソッドがオーバーロードされており、
すぐに利用できます。
Arraysインターフェイスを
下のリンクで確認しましょう。(インターフェイスもクラスと同じように調べることができます)
以下にメソッドの宣言を示します。
static <T> void sort(T[] a, int fromIndex, int toIndex, Comparator<? super T> c) static <T> int binarySearch(T[] a, T key, Comparator<? super T> c)
ここで、<? super T>の表現がありますが、これは
『指定されたクラス・インターフェース自身か、その親クラスであることを示す』という意味の
下限境界ワイルドカード(lower bounded wildcard)”指定と呼ばれるものです。
(利用するだけなら、単純にComparatorの実装オブジェクトを指定するだけです。)
これらメソッドを利用して、文字列の配列を逆順に並べ、"wxyz"を検索する例を、以下に示します。
import java.util.Arrays; public class Test { public static void main(String[] arg) { String[] a = { "wxyz", "ab", "abc", "opqrstu", "あいう", "いう", "123", }; RevStrCmp cmp = new RevStrCmp(); Arrays.sort(a, cmp);//逆の並びで、並び替え for (int i = 0; i < a.length; i++) { System.out.println(i + " :" + a[i]); } int iFound = Arrays.binarySearch(a, "wxyz", cmp);//2分探索 System.out.println("wxyzは、" + iFound + "番目です"); } } class RevStrCmp implements java.util.Comparator <String> { public int compare(String s1, String s2){ return s2.compareTo(s1); } } |
D:\java>java Test 0 :いう 1 :あいう 2 :wxyz 3 :opqrstu 4 :abc 5 :ab 6 :123 wxyzは、2番目です D:\java> |