リスト
Listは,順序づけられた,連続したデータを格納するためのコレクションである.addメソッドを使って,データを順に追加していくことができる.
リスト構造を使うために用意されているものを確認する.Listをリファレンスで確認する.Listはインタフェースである.
インタフェースList
Listインタフェースは,Collection<E>, Iterable<E >のサブ・インタフェースである.
Listインタフェースは次のように定義されている.
public interface List<E> extends Collection<E>
さらに,Collectionインターフェースは次のように定義されている.
public interface Collection<E> extends Iterable<E>
既知の実装されているクラスとしてArrayListクラスがある.では,実際インスタンスとして使うクラスをArrayListとしよう.ArrayListクラスを型としてもよいが,すでに上位のインタフェースで定義されているメソッドの範囲で十分であるので,List型にする.
このとき,<E>でリストで扱うデータの型を指定する.例えば,リストに格納するデータの型が文字列である場合は「String」クラスを<String>のように指定する.自分で定義したクラスでもよい.なお,Eはelementを意味する.
コレクションを使うときの特徴として,格納するデータの型を表すクラスを指定してインスタンス化することである.具体的には,「<>」で囲まれた部分であり,以下の場合には,Stringクラスのデータを格納することを意味している.このような「型」を指定して構成できるしくみをジェネリクス(Generics)と呼ぶ.これによって,リストに含まれるデータの型が一定になるため,持っているメソッドやフィールドが約束される.
Listインタフェースに定義されているメソッドを確認する.(参照:List (Java Platform SE 8))
修飾子と型 | メソッド | 説明 |
boolean | add(E e) | 指定された要素をこのリストの最後に追加します(オプションの操作)。 |
E | get(int index) | このリスト内の指定された位置にある要素を返します。 |
int | size() | このリスト内にある要素の数を返します。 |
これを使って,リストデータ構造を利用する.
import java.util.ArrayList; import java.util.List; public class Main { public static void main(String args[]) { List<String>vegitableList = new ArrayList<String>(); vegitableList.add("なす"); vegitableList.add("きゅうり"); vegitableList.add("とまと"); for(int i=0;i<vegitableList.size();i++) { System.out.println(i + ":" +vegitableList.get(i)); } vegitableList.set(1, "かぼちゃ"); for(int i=0;i<vegitableList.size();i++) { System.out.println(i + ":" +vegitableList.get(i)); } } }
0:なす 1:きゅうり 2:とまと 0:なす 1:かぼちゃ 2:とまと
Listインターフェースには,ソートするメソッドが定義されている.sortメソッドを用いることで,簡単にソートすることができる.(参照:List (Java Platform SE 8))
修飾子と型 | メソッド | 説明 |
default void | sort(Comparator<? super E> c) | 指定されたComparatorが示す順序に従って、このリストをソートします。 |
単純なデータ型である時には,ソートのルールを指摘せずとも,自然順序で並べ替えが行われる.まずは,何もルールを指定しない,「null」を渡して,ソートがなされることを確認する.
import java.util.ArrayList; import java.util.Collections; import java.util.List; public class Main { public static void main(String args[]) { List<String> vegitableList = new ArrayList<String>(); vegitableList.add("なす"); vegitableList.add("きゅうり"); vegitableList.add("とまと"); //追加した順に表示する for(int i=0;i<vegitableList.size();i++) { System.out.println(i + ":" +vegitableList.get(i)); } //特定の順番のデータを変更する vegitableList.set(1, "かぼちゃ"); for(int i=0;i<vegitableList.size();i++) { System.out.println(i + ":" +vegitableList.get(i)); } //データをソートする vegitableList.sort(null); System.out.println(vegitableList); } }
0:なす 1:きゅうり 2:とまと 0:なす 1:かぼちゃ 2:とまと [かぼちゃ, とまと, なす]
格納するデータ型として,独自のクラスを設定することもできる.ここでは,YasaiクラスをListに格納される型として定義する.YasaiクラスのオブジェクトをvegitableListリストに順に格納している.
import java.util.ArrayList; import java.util.List; public class Main { public static void main(String args[]) { List<Yasai> vegitableList = new ArrayList<Yasai>(); vegitableList.add(new Yasai("なす")); vegitableList.add(new Yasai("きゅうり")); vegitableList.add(new Yasai("とまと")); for(int i=0;i < vegitableList.size();i++) { System.out.println(i + ":" + vegitableList.get(i).getName()); } vegitableList.set(1, new Yasai("かぼちゃ")); for(int i=0;i < vegitableList.size();i++) { System.out.println(i + ":" +vegitableList.get(i).getName()); } } } class Yasai { String name; Yasai(String name) { setName(name); } public String getName() { return name; } public void setName(String name) { this.name = name; } }
0:なす 1:きゅうり 2:とまと 0:なす 1:かぼちゃ 2:とまと
このとき,sortメソッドで,自然順序で並べ替えを行おうとしても(sort(nulll)),うまくいかない.これは,データがクラスで定義されていて複雑であるため,何を基準に並へ変えを行えばよいかわからないからである. そこで,並べ替えのルールを明確に決める.自然順序でない,独自のルールでソートすることもできる.
例えば,Yasaiクラスが,野菜名と,100gあたりのカロリーを持つとする.このとき,カロリーで並べ替えをしたいときには,カロリーの値で大小関係を定義してあげることで,並べ替えのルールを与えることができる.並べ替えのルールそのものも,オブジェクトであるため,クラスとして定義して,インスタンス化してsortメソッドに渡している.
sortのルールとしての役割を果たすためには,指定された要件を満たしている必要がある.その要件は,インターフェースとして指定されている.すなわち,指定されたインターフェースを実装することで,ソートに必要なルールセットを満たすことが約束される.ここでは,Comparatorインタフェースが指定されているので,それを実装することで,並べ替えのルールが完成する.
Comparatorインターフェースを実装したオブジェクトで並べ替えのルールを定義して,インスタンスを渡すことで,指定した並べ替えを行うことができる. Comparatorインターフェースを見る.compareメソッドを実装する必要がありそうである.その仕様は以下のようになっている.
compare |
順序付けのために2つの引数を比較します。最初の引数が2番目の引数より小さい場合は負の整数、両方が等しい場合は0、最初の引数が2番目の引数より大きい場合は正の整数を返します。 前述の説明では、sgn(expression)という表記は数学関数signumを示し、expressionの値(負の数、ゼロ、正の数)に応じて、-1、0、1のどれかを返します。 |
import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; public class Main { public static void main(String args[]) { List<Yasai> vegitableList = new ArrayList<Yasai>(); vegitableList.add(new Yasai("なす",22)); vegitableList.add(new Yasai("きゅうり",14)); vegitableList.add(new Yasai("とまと",19)); vegitableList.add(new Yasai("かぼちゃ",93)); for(int i=0;i<vegitableList.size();i++) { System.out.println(i + ":" + vegitableList.get(i).getName() + ":" + vegitableList.get(i).getCalorie()); } vegitableList.sort(new CalorieComparetor()); for(int i=0;i<vegitableList.size();i++) { System.out.println(i + ":" + vegitableList.get(i).getName() + ":" + vegitableList.get(i).getCalorie()); } } } class Yasai { String name; int calorie; Yasai(String name, int calorie) { setName(name); setCalorie(calorie); } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getCalorie() { return calorie; } public void setCalorie(int calorie) { this.calorie = calorie; } } class CalorieComparator implements Comparator<Yasai> { public int compare(Yasai yasai1, Yasai yasai2) { int calorie1 = yasai1.getCalorie(); int calorie2 = yasai2.getCalorie(); if(calorie1 > calorie2) { return 1; } else if(calorie1 == calorie2) { return 0; } else //(calorie1 < calorie2) { return -1; } } }
0:なす:22 1:きゅうり:14 2:とまと:19 3:かぼちゃ:93 きゅうり:14 とまと:19 なす:22 かぼちゃ:93
ジェネリクス補足
List<Number> numberList = new ArrayList<>(); List<Integer> integerList = new ArrayList<>();
//Numberクラスを継承したクラスの型である仮宣言 List<? extends Number> wildNumberExtendsList = new ArrayList<>(); wildNumberExtendsList = numberList; //OK:NumberクラスはNumberも含むので許容される wildNumberExtendsList = integerList; //OK:IntegerクラスはNumberクラスを継承しているので許容される
//Integerクラスを継承したクラスの型である仮宣言 List<? extends Integer> wildExtendsIntegerList = new ArrayList<>(); wildExtendsIntegerList = integerList; //OK:IntegerクラスはNumberクラスを継承しているので許容される //wildExtendsIntegerList = numberList; //NG:NumberクラスはIntegerクラスのスーパークラスなので許容されない
//Integerクラスをサブクラスに持つスーパークラスの型になる仮宣言 List<? super Integer> wildSuperIntegerList = new ArrayList<>(); wildSuperIntegerList = integerList;//OK:IntegerはIntegerクラスも含むので許容される wildSuperIntegerList = numberList;//OK:NumberクラスはIntegerクラスのスーパークラスなので許容される
//Numberクラスをサブクラスに持つスーパークラスの型になる仮宣言 List<? super Number> wildSuperNumberList = new ArrayList<>(); //wildSuperNumberList = integerList;//NG:IntegerクラスはNumberのスーパークラスではないので許容されない wildSuperNumberList = numberList;//OK:NumberクラスはNumberクラスそのものなので許容される