JavaのList

Java本格入門でListについて読んだので、それのメモ。

List(java.util.List)

配列のように複数要素を扱うことができ、インデックスを指定して値の取得や設定ができる。

初期化方法

・要素なしの初期化

List<Integer> list = new ArrayList<>();

Listインターフェースの実装クラスを引数なしでnew。
ジェネリクスにIntegerを指定し、型を制限。


・asListを使った初期化

List<Integer> list2 = Arrays.asList(1,2,3);

1行でかけるが、要素の追加・削除ができない(固定サイズになっている)

// java.lang.UnsupportedOperationExceptionが発生
list2.add(4);

list2.set(0, 4)
System.out.println(list2);
→[4,2,3]
要素の上書きはOK


・コンストラクタを使う初期化

List<Integer> list3 = new ArrayList<>(Arrays.asList(1,2,3));

追加も削除もできる。

Listのメソッド
 List<Integer> list = new ArrayList<>();

//要素の追加
list.add(1);
System.out.println(list);
->[1]


//要素の追加2。インデックス1に2を入れる。
list.add(1, 2);
System.out.println(list);
->[1, 2]


//要素の追加3。2が後ろにずれる
list.add(1, 3);
System.out.println(list);
->[1, 3, 2]


//要素の取得
Integer num = list.get(1);
System.out.println(num);
->3


//要素の上書き。インデックスが2(この場合2)の要素を5に上書き。
list.set(2,5);
System.out.println(list);
->[1, 3, 5]

        
//要素の削除。インデックスが1(この場合3)の要素を削除
list.remove(1);
System.out.println(list);
->[1, 5]


//要素の数を取得
int size = list.size();
System.out.println(size);
->2


//インデックス番号を取得。5がlistのどこにあるのか
int index = list.indexOf(5);
System.out.println(index);
->1


//インデックス番号を取得。要素がない場合
int index2 = list.indexOf(34);
System.out.println(index2);
->-1


//値があるかどうかの確認。
boolean exists = list.contains(5);
System.out.println(exists);
->true
Listをソートする

java.util.Collectionsを使ってソートする。
第1引数にソート対象を、
第2引数にComparatorインターフェースを指定、

public class Main {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>(Arrays.asList(3,24,5,1,11,6,9));
        System.out.println(list);
        ->[3, 24, 5, 1, 11, 6, 9]

   //Comparatorインターフェース(関数型インターフェース)のcompareメソッドをラムダ式で実装。
        Comparator<Integer> c = (o1, o2) -> {return o2.compareTo(o1);};

        Collections.sort(list, c);
        System.out.println(list);
        ->[24, 11, 9, 6, 5, 3, 1]
    }
}

このように並び替えることができる。

Listの検索

binarySearch(リスト, 探す要素)で、要素のインデックスを取得できる

public class Main {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>(Arrays.asList(3,24,5,1,11,6,9));
        int index = Collections.binarySearch(list, 6);
        System.out.println(index);
        -> 5 
    }
}


ArrayListについて

・内部に配列を持つ
・要素のインデックスを指定して何かする、などの処理に向いている。
・内部に持つ配列の長さはコンストラクはで指定できる(デフォルトは10)
・配列のサイズ以上の要素を追加する場合、
「よりサイズの大きい配列を新たに生成して、元の配列から全ての要素をコピーする」
という処理が行われる
・なので、格納する要素数の目安がついているなら、最初にサイズを指定した方がいい。
・リストの途中で追加や削除をするとその後の要素を後ろにずらす必要があるので、中間要素の追加・削除処理は高速ではない。


LinkedListについて
・要素自信が前後の要素情報(ポインタ的な?)を持つ
・「A, B, C, D」といった要素の場合、AはBでのリンクを、BはAとCのリンクを、CはBとDのリンクを、DはCのリンクをもつ。
・BとCの間にEを入れる際、AとDのリンク情報は変わらない
・なので中間要素の追加・削除処理が高速
・インデックス指定の処理は、一旦先頭から順番を辿らないといけないので、サイズが大きいと時間がかかる。


CopyOnWriteArrayListについて

ArrayListをスレッドセーフはないので、複数のスレッドでListを扱いたい時にこのCopyOnWriteArrayListを使う。
ループ処理を行う際に、リストをコピーしてそのコピーした物に対してループ処理を行うので、
他のスレッドがリストの操作をしてもループ側に影響はない。


Listの実装クラスの使いわけ

・配列の途中で要素の追加・削除等をする場合

  • > LinkedList

・for文などを使った全体的な繰り返し処理が多い場合

・複数スレッドから同時にアクセスする場合

  • >CopyOnWriteArrayList
まとめ

ArrayListはよく使うが、LinkedListとかCopyOnWriteArrayListを使う機会が少ない気がする。
(自分の現場がそうなだけ?)


これからはもうちょっと意識して使い分けて見ようと思う。