今月も先月に引き続き、今月もJava SE 7におけるコアライブラリの変更点について紹介していきます。

 今回取りあげるのは次の4つのカテゴリです。

  • コレクション
  • Concurrency Utilities
  • Logging API
  • Management

 これ以外にもjava.util.zipパッケージなどの変更がありますが、今回は省略させていただきました。

コレクション

 コレクションでは、使いやすさやパフォーマンス向上が図られています。また、Concurrency Utilitiiesに関連したコレクションクラスが追加されていますが、それはConcurrency Utilitiesの章で紹介します。

空のイテレータ

 Collectionsクラスに空のイテレータを返すメソッドが追加されました。

  • emptyIterator
  • emptyListIterator
  • emptyEnumeration

 空のイテレータは使い道がないように感じますが、コレクションクラスを自作した場合などに使えそうです。

イテレータのパフォーマンス向上

 ArrayListクラスなどのクラスはLinkedListクラスなどに比べて、イテレーションが遅いというのが今までの通説でした。しかし、それもJava SE 7で覆されるようです。

 例えば、ArrayListクラスで返されるIteratorインタフェースの実装クラスのnextメソッドは次のようになっています。

リスト1●ArrayListクラスのイテレータのnextメソッド (Java SE 7)
    public E next() {
        checkForComodification();
        int i = cursor;
        if (i >= SubList.this.size)
            throw new NoSuchElementException();
        Object[] elementData = ArrayList.this.elementData;
        if (offset + i >= elementData.length)
            throw new ConcurrentModificationException();
        cursor = i + 1;
        return (E) elementData[offset + (lastRet = i)];
    }

 これに対し、Java SE 6でのnextメソッドはAbstractListクラスとArrayListクラスの両方にまたがって実装されています。見やすいように一緒に示しました。

リスト2●ArrayListクラスのイテレータのnextメソッド (Java SE 6)
    private void RangeCheck(int index) {
        if (index >= size)
            throw new IndexOutOfBoundsException(
                "Index: "+index+", Size: "+size);
    }
    
    public E get(int index) {
        RangeCheck(index);

        return (E) elementData[index];
    }
    
    public E next() {
        checkForComodification();
        try {
            E next = get(cursor);
            lastRet = cursor++;
            return next;
        } catch (IndexOutOfBoundsException e) {
            checkForComodification();
            throw new NoSuchElementException();
        }
    }

 両方のコードを見比べてみると、すぐにわかるのが例外処理がなくなっているということです。Java SE 6ではRangeCheckメソッドでレンジのチェックをし、IndexOutOfBoundsException例外スローします。nextメソッドではこの例外をキャッチし、新たにNoSuchElement例外をスローしています。しかし、これは無駄な例外処理です。

 また、Java SE 7はnextメソッドの中で、Java SE 6のgetメソッド、RangeCheckメソッドに相当する処理を行ってしまっています。これはメソッドをインライン展開したことになり、ここでも処理速度の向上を見込めます。

 小さな変更ではありますが、このような変更を積み重ねることでパフォーマンスを向上させているのです。

 これまではパフォーマンスが気になって拡張for文を使わなかった方たちにも、拡張for文が受け入れられていくのではないでしょうか。

ソートのパフォーマンス向上

 CollectionsクラスとArraysクラスのsortメソッドもパフォーマンスが向上しました。

 Javaでは、ソートのアルゴリズムとしてマージソートが採用されてきました。これに対し、Java SE 7ではDual-Pivot Quicksortに変更されています。

 Dual-Pivot Quicksortのコードを実装したのは、 Vladimir Yaroslavskiy氏とJoshua Bloch氏です。

 また、オブジェクトのソートにはTimsortが採用されています。こちらもJoshua Bloch氏が実装を行っています。

 Dual-Pivot QuicksortはQuicksortを改良したソートで、Timsortはマージソートを改良したソートです。ここではソートのアルゴリズムの詳細は示しませんが、既存のソートに比べて2倍以上のパフォーマンスが向上しているようです。

 ソートのアルゴリズムに関してはDual-Pivot Quicksort、およびWikipediaのTimsortの項を参照してください。