ゴールドマン・サックス発のJavaコレクションフレームワーク、その7つの特徴と歴史とは:コレクション処理の万能道具箱Eclipse Collections入門(1)(1/3 ページ)
本連載では、ゴールドマン・サックス発のオープンソースJavaコレクションフレームワークであるEclipse Collectionsについて、その概要と歴史、機能を中心に紹介します。これまでのJavaやJava 8のStream APIと比較して何が違うのか。Eclipse Collectionsを例に、読者の皆さんがコレクション処理をより深く理解するための一助になればと思います。
ゴールドマン・サックスが開発し、オープンソースソフトウェア(OSS)として公開したJavaコレクションフレームワーク「GS Collections」が、Eclipse Foundationに移行し、「Eclipse Collections」として生まれ変わりました。本連載では、Java 8で導入されたStream APIを改良した使いやすさとパフォーマンスを誇るEclipse Collectionsについて、その概要と歴史、機能、習得するための教材である「Eclipse Collections Kata」の内容を中心に紹介します。
これまでのJavaやJava 8のStream APIと比較して何が違うのか。Eclipse Collectionsを例に、読者の皆さんがコレクション処理をより深く理解するための一助になればと思います。
Eclipse Collectionsとは
「Eclipse Collections」は機能が豊富なオープンソースJavaコレクションフレームワークです。JavaのプログラマーであればListやSet、Mapなどのコレクションにはなじみがあると思います。Java 8で導入されたStream APIとラムダ式によって、それまでfor文などで書いていたさまざまな処理をよりスマートに記述できるようになりました。Eclipse Collectionsを使うことでコレクション処理をさらに簡潔に、より良いパフォーマンスで実装できます。Stream APIでは提供されていない豊富な処理も活用することも可能です。
ちなみに、たまに勘違いされてしまうことがあるので念のため書いておきますが、Eclipse Collectionsは汎用的なJavaライブラリですので、Eclipse IDEでなくても使えます。IntelliJ IDEAやNetBeansでも当然使えますし、VimやEmacsでも書けます。
執筆時点の最新リリースバージョンである7.1.0はJava 5以上の環境であれば利用可能です。2016年8月にリリース予定のバージョン8.0.0からはJava 8との親和性を強化した機能が追加される予定で、サポートバージョンはJava 8以上となります。執筆時点でマイルストーンビルドが提供されているので、最新の機能を試したい方は8.0.0-M1を使用してみてください。
百聞は一見に如かずということで、連載第1回ではEclipse Collectionsの概要として下記の各ポイントを簡単な例を用いながら解説していきます(注:本記事において、JDKと記述のある箇所は特に記載がない限りはJDK 8時点での機能を前提としています)。
これらの利点を簡単に説明した後に、最後にEclipse Collectionsの歴史を追っていきます。
【1】簡潔なイテレーション処理
Java 8で導入されたラムダ式とStream APIは、Javaにおけるイテレーション処理に大きなパラダイムシフトをもたらしました。詳しくは、連載「Java 8はラムダ式でここまで変わる」をご参照いただければと思いますが、Stream APIとラムダ式やメソッド参照を組み合わせたスマートな処理方法を気に入っている読者の方も多いかと思います。
Eclipse Collectionsを使うと、さらに快適にコレクション処理を記述できます。早速例を見てみましょう。
Eclipse Collectionsの初期化
コレクションに対してある条件を満たすかどうかを判定したり、カウントしたり選択する処理を、Eclipse Collectionsを使用した方法で書いてみます。まずはコレクションを初期化します。
ImmutableList<Integer> integers = Lists.immutable.of(1, 2, 3, 4, 5, 6);
ここでは「ImmutableList」という不変リストを用いて1から6の整数を要素に持つリストを初期化しています。「不変」かどうかはここの例においてあまり重要ではないので、取りあえずImmutableListはいったん初期化したら変更できないリストだと考えておいてもらえればよいでしょう。不変リストについては本記事の後半で説明します。
Eclipse Collectionsを使ったイテレーション処理の例を3つ挙げます。
boolean anySatisfy = integers.anySatisfy(i -> i > 3);
int count = integers.count(i -> i > 3);
ImmutableList<Integer> select = integers.select(i -> i > 3);
いかがでしょう。非常に簡潔に記述できているのが分かるのではないでしょうか。同様の処理をJava 7以前の書き方や、Java 8のStream APIで書いてみて比べてみましょう。
Java 7以前
boolean anySatisfy; for(int i: integers){ if(i > 3) { anySatisfy = true; break; } } long count = 0; for(int i: integers){ if(i > 3) { count++; } } List<Integer> select = new ArrayList<>(); for(int i: integers){ if(i > 3) { select.add(i); } }
Java 7以前の書き方だとそもそも記述量が多いですし、処理の内容を読解するのにも少し時間がかかります。
Java 8 Stream API
それではStream APIで書くとどうなるでしょうか。
boolean anySatisfy = integers.stream().anyMatch(i -> i > 3); long count = integers.stream().filter(i -> i > 3).count(); List<Integer> select = integers.stream().filter(i -> i > 3).collect(Collectors.toList());
これはEclipse Collectionsの場合と非常に似ていますが、下記の点に注目してみてください。まずStream APIで記述する場合は全ての例でstream()メソッドを余計に呼ぶ必要があります。また、カウントの例であればfilter()、選択の例であればcollect(Collectors.toList())と、冗長な記述が見受けられます。
Stream APIはコレクション操作を便利にするものではありますが、現存するJCF(Javaコレクションフレームワーク)と整合性を保てるように導入されたため、上記のようにどうしても冗長に書かざるを得ないケースがあります。
単純な例なのでそこまで変わらないように感じるかもしれませんが、コレクションのフィルターをするようなコードは日常茶飯事のごとく読み書きするコードなので、メソッド呼び出しが数段減るだけでコーディングの快適度が大きく変わってきます(当然個人差はあると思いますが)。
このように、Eclipse Collectionsはコレクションの処理をJava 7以前の書き方やJava 8のStream APIと比較しても「より簡潔に」記述できます。この簡潔さこそが、コードを書く開発者、読む開発者、双方にとってうれしい第1の大きな利点です。
Copyright © ITmedia, Inc. All Rights Reserved.
関連記事
- 初心者のためのJavaラムダ式入門とJDKのインストール、IDEの環境構築
本連載では、今までJavaの経験はあっても「ラムダ式は、まだ知らない」という人を対象にラムダ式について解説していきます。初回は、ラムダ式の概要と利点、必要性、JDK 8のセットアップ、NetBeans、IntelliJ IDEA、Eclipseの環境構築について。 - キュー構造をJavaで実装してジェネリック型を理解する
これからプログラミングを学習したい方、Javaは難しそうでとっつきづらいという方のためのJavaプログラミング超入門連載です。最新のEclipse 3.4とJava 6を使い大幅に情報量を増やした、連載「Eclipseではじめるプログラミング」の改訂版となります - コレクションフレームワークを拡張するCollections