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> |