Haskell の代数的データ型を比較、特定の基準でソート を試したので、ついでに Java でも。てゆうか、総称型が導入されてから、JDK で言うと 1.5 以降 Java を触ってないので API のドキュメントを読んでも隔世の感が。。 ^^;
「人」クラスの定義
前回と同様、「人」が「名前」「年齢」を持っているとして、
public class Person { private String name; private int age; Person(String name, int age) { this.name = name; this.age = age; } String getName() { return this.name; } int getAge() { return this.age; } @Override public String toString() { return this.name + ":" + this.age; } }
Comparable<T> を実装して比較可能に
Person クラスを比較可能にするには、Comparable インターフェイスを実装。
インタフェース Comparable<T>
- 型パラメータ:
T
- the type of objects that this object may be compared to
昔は <T> なんてなかったので、久しぶりに見ると混乱するなぁ~ (+_+)
Haskell で言うなら、
class Eq a => Ord a where
の型変数 a に相当するということか。
クラス宣言において、Comparable を implements するとき、後ろに <具体的なクラス名> を入れる。
public class Person implements Comparable<Person> {
Haskell なら、
instance Ord Person where
Comparable<Person> を実装するには、compareTo メソッドを書く必要がある。ここでは「人」の年齢が人の順序を決めるものとして扱う。総称型を利用することによって、Object クラスをキャストして使わなくて済むところが以前より楽。
public int compareTo(Person o) { return new Integer(this.age).compareTo(o.getAge()); }
これで Personクラスのオブジェクトを比較できるようになった。
System.out.println(new Person("Tarou", 10).compareTo(new Person("Saburou", 30))); // -1
ソート
次に上記で定義した比較によるソートを試す。リストを作成するには、Arrays の asList を使うのが書きやすい。
public static <T> List<T> asList(T... a)
このメソッドも随分様変りしてるなぁ。。。以前は、
public static List asList(Object[] a)(Arrays (Java 2 プラットフォーム SE v1.4.0) より)
引数の … は可変長の引数を表わすらしい。(cf. ライトニングJava (9) 可変長引数(3)) static の後の <T> は何を表わしているのか知らないけれど、とにかく使う分には、
List<Person> persons = Arrays.asList( new Person("Saburou", 30), new Person("Jiro", 20), new Person("Tarou", 10), new Person("Hanako", 30));
これをソートするには、Collections の sort を使う。
Collections.sort(persons); System.out.println(persons); // [Tarou:10, Jiro:20, Saburou:30, Hanako:30]
しかし、型を見ると、
public static <T extends Comparable<? super T>> void sort(List<T> list)
うげぇ (@_@;) ますます分からん。。
Comparator でソートする基準を変更
ソートする基準を変えたい場合は、Comparator を使う。
例えば、「年齢が同じ場合、名前順にしたい」なら、
Collections.sort(persons, new Comparator<Person>() { public int compare(Person o1, Person o2) { int c = new Integer(o1.getAge()).compareTo(o2.getAge()); if (c != 0) { return c; } else { return o1.getName().compareTo(o2.getName()); } } }); System.out.println(persons); // [Tarou:10, Jiro:20, Hanako:30, Saburou:30]
これも Comparator<Person> とクラスを指定すると、compare メソッドの引数のクラスが決まるようで、キャストが必要なくなっている。
あ~、Java の総称型は完全にスルーしていたので読めない。。パタッ(o_ _)o~†
しかし、これからは Scala の時代になっていくのかなぁ?
全体
0コメント:
コメントを投稿