J2SE 5.0のコレクションの使い方を覚えるはじめに コレクションAPIは、これまでずっとJava開発キット(JDK)の最も重要な要素の1つでした。ほとんどすべてのJavaプログラムは、 ありがたいのは、学習曲線が緩やかになったことです。実際、J2SE 5.0のコレクションAPIは、多くの点で簡素化されています。また、J2SE 5.0で採り入れられたさまざまな変更によって、必要なコードの記述量は旧バージョンのJavaよりも少なくなっています。 コレクションに関わるJ2SE 5.0の新機能本稿では、コレクションAPIに影響を及ぼす新機能を紹介します。具体的には、次の機能について説明していきます。
これらの技術はコレクションAPIに影響を与えています。本稿では、この3つの技術を利用したコレクションクラスのサンプルを紹介します(ソースコードについてはダウンロードサンプルを参照してください)。ここで、新しいコレクションAPIの機能を詳しく説明する前に、ジェネリック型の基本的な部分を解説しておきましょう。 ジェネリック型 ジェネリック型は、コレクションAPIに追加された最も重要な要素です。拡張された import java.util.*; public class BasicCollection { public static void main(String args[]) { ArrayList list = new ArrayList(); list.add( new String("One") ); list.add( new String("Two") ); list.add( new String("Three") ); Iterator itr = list.iterator(); while( itr.hasNext() ) { String str = (String)itr.next(); System.out.println( str ); } } } これは、J2SE 5.0より前のJavaでよく見られるコレクションクラスのサンプルコードです。このクラスでは、 次に、
while( itr.hasNext() ) {
String str = (String)itr.next();
System.out.println( str );
}
このループは import java.util.*; public class GenericCollection { public static void main(String args[]) { ArrayList<String> list = new ArrayList<String>(); list.add( new String("One") ); list.add( new String("Two") ); list.add( new String("Three") ); //list.add( new StringBuffer() ); Iterator<String> itr = list.iterator(); while( itr.hasNext() ) { String str = itr.next(); System.out.println( str ); } } } ご覧のとおり、J2SE 5.0用に変更されたこのクラスは、元のコードからほんの数行しか変わっていません。最初の変更箇所は、
ArrayList<String> list = new ArrayList<String>();
このコードが、どのようにして型とコレクションの名前を結び付けているかに注意してください。ジェネリック型を指定するには、コレクション名のすぐ後ろに山カッコ(<>)を記述し、その中に型の名前を指定します。 次に、反復子(イテレータ)の宣言では、 Iterator<String> itr = list.iterator(); この行は、 String str = itr.next(); たしかにコードの記述量は減りますが、ジェネリック型は型変換を不要にするだけのものではありません。ジェネリック型を指定しておくと、 サポート外の型の一例として、
list.add( new StringBuffer() );
ここからがジェネリック型のすばらしいところですが、サポート外の型を c:collectionsGenericCollection.java:12: cannot find symbol symbol : method add(java.lang.StringBuffer) location: class java.util.ArrayList<java.lang.String> list.add( new StringBuffer() ); こうしたエラーをコンパイル時に検出できることは、バグのないコードを書こうとする開発者にとって非常に好都合です。J2SE 5.0より前のバージョンであれば、実行時になって 拡張されたforループの利用 これまでのJavaには、 この拡張されたforループは、J2SE 5.0の機能のなかでも最も期待されていたものの1つです。この機能を使えば、さきほど紹介したコードのIteratorがすっかり不要になるため、さらに簡潔なコードが得られます。拡張されたforループを使ってJ2SE 5.0用に変更したコードを以下に示します。 import java.util.*; public class EnhancedForCollection { public static void main(String args[]) { ArrayList<String> list = new ArrayList<String>(); list.add( new String("One") ); list.add( new String("Two") ); list.add( new String("Three") ); //list.add( new StringBuffer() ); for( String str : list ) { System.out.println( str ); } } } このコードでは、元のコードから
for( String str : list ) {
System.out.println( str );
}
拡張された
for( [collection_item_type] [item_access_variable] :
[collection_to_be_iterated] )
最初のパラメータである 2番目のパラメータ 3番目のパラメータ プリミティブデータ型とオートボクシングJ2SE 5.0に追加されたもう1つの重要な機能が、プリミティブデータ型のボクシングとアンボクシングを自動的に行う機能です。コレクションAPIでプリミティブデータ型の追加と参照を行うコードは複雑になりがちですが、このオートボクシング機能により、コードをかなり簡略化できます。 ボクシングとアンボクシングについて馴染みがない方は、J2SE 5.0について知る前に、Javaがプリミティブデータ型をどのように扱うかをまず知っておく必要があります。ここでは、本題のJ2SE 5.0に入る前に、コレクションAPIでプリミティブデータ型を利用する簡単なJavaアプリケーションを紹介しましょう。 import java.util.*; public class PrimitiveCollection { public static void main(String args[]) { ArrayList list = new ArrayList(); // box up each integer as they are added list.add( new Integer(1) ); list.add( new Integer(2) ); list.add( new Integer(3) ); //list.add( new StringBuffer() ); // now iterate over the collection and unbox Iterator itr = list.iterator(); while( itr.hasNext() ) { Integer iObj = (Integer)itr.next(); int iPrimitive = iObj.intValue(); System.out.println( iPrimitive ); } } } 上記のコードは、コレクションAPIでプリミティブ型を用いるために必要な2つの手順を示しています。コレクション型は、プリミティブ型ではなくオブジェクト型を格納するため、プリミティブ型の要素を格納したいときには、適切なラッパーオブジェクトにボクシングしなければなりません。たとえば、上記のコードでは、次のようにして list.add( new Integer(1) ); list.add( new Integer(2) ); list.add( new Integer(3) ); しかし、このボクシングを行うと、コードの後の部分で、コレクションに格納されたプリミティブ型の Iterator itr = list.iterator(); while( itr.hasNext() ) { Integer iObj = (Integer)itr.next(); int iPrimitive = iObj.intValue(); System.out.println( iPrimitive ); } この例の場合は、まずは各要素を J2SE 5.0のオートボクシングを使えば、コレクションでのプリミティブ型の格納と取り出しがとても容易になります。次に例を示します。 import java.util.*; public class AutoBoxCollection { public static void main(String args[]) { ArrayList<Integer> list = new ArrayList<Integer>(); // box up each integer as it’s added list.add( 1 ); list.add( 2 ); list.add( 3 ); //list.add( new StringBuffer() ); // now iterate over the collection for( int iPrimitive: list ) { System.out.println( iPrimitive ); } } } このオートボクシングのサンプルでは、最初に
ArrayList<Integer> list = new ArrayList<Integer>();
list.add( 1 ); list.add( 2 ); list.add( 3 ); この場合、それぞれの整数を for( int iPrimitive: list ) { System.out.println( iPrimitive ); } この例は、拡張された まとめJ2SE 5.0にジェネリック型が追加されたことで、コレクションに格納するデータの型を明確に指定できるようになりました。これによって、コレクションが正しい型のオブジェクトだけを受けとることがコンパイラによって保証され、コレクションで扱われる要素の型変換が不要になります。 また、ジェネリック型により、拡張された これまで、コレクションへのプリミティブデータ型の追加は、常に面倒なものでした。 こうした変更によって、J2SE 5.0のコレクションデータへのアクセス方法は必然的に変化し、コレクションAPIにアクセスするためのJavaコードもずっとシンプルなものになっています。 著者紹介Jeff Heaton(Jeff Heaton)
ライター、大学教員、コンサルタントとして活動中。4冊の著作があり、論文誌および雑誌で20を超える記事を発表。また、個人のWebサイトを管理し、人工知能とスパイダー/ボットプログラミングをはじめとする話題について情報発信を行っている。メールの宛先はjheaton@heatonresearch.com。
|