Java Silver SE11 9章
黒本をもとに学んだことをアウトプットしていきます。
主に問題を解いていて、間違えた箇所もしくは知らなかった内容になります。
コレクション
何らかの集合のこと。
配列がこれに該当する。
配列には以下の制約がある。
- 同じ型もしくは、互換性のある型のみ扱える
- 要素数を最初に決める必要がある
- 要素にアクセスするには添字を使う
- 要素にアクセスするときは、要素数を超えないようにしなければならない
詳しくはJava Silver SE11 5章を参照
コレクションAPI or フレームワーク (collection framework)
java.utilパッケージに属する、データをまとめて扱うための入れ物としてのクラスのこと。
これらがAPIとして存在している。
例:List, Set, Map
特にjava.util.ArrayListクラスは、配列のように使うことができる。
ArrayListクラス
以下のような特徴をもっている。
- オブジェクトであれば、どのような型でも扱える
- 自由に要素数を増やせる
- 追加した順に並ぶ
- nullも追加できる
- 重複した値もOK
- スレッドセーフではない
スレッドセーフとは?
スレッド:プログラムの処理には、処理の順番がありこの流れのこと
並行処理:スレッドを複数作り動作する状態のこと、その名の通り処理を実行しながら他の処理を実行できる
コレクションAPIには2種類のクラスがある。
- スレッドセーフなクラス:遅くても安全に並行処理ができるクラス
- スレッドセーフでないクラス:安全な並行処理はできないが、高速な単一処理専用のクラス
ジェネリクス (< >)
コレクションに使用する型を指定することで、扱える型を制限する機能のこと。
コード内で「<>」に記述している型を、型パラメータと呼ぶ。
// Stting型しか扱えない
ArrayList<String> list = new ArrayList<String>();
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
ArrayList list = new ArrayList<>();
list.add("A");
list.add(10);
list.add('B');
for (Object obj: list) {
System.out.println(obj); // A 10 B
}
}
}
型変数を指定しなかった場合は、Object型を型変数に使用したと認識される。
addメソッドで追加された値は全てObject型として扱えるので、コンパイルエラーにならない。
addメソッド
引数に渡された値をリストの後ろに追加する。
またオーバーロードにより、追加する場所を指定することができる。
(追加する場所は、0番から初まる)
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("A");
list.add(2, "B");
list.add("C");
list.add("D");
for (String str: list) {
System.out.println(str); // 例外がスローされる
}
}
}
まだ1番目の値がない状態で、2番目の"B"を追加しようとしている。
文法的には問題ないが、例外がスローされる。
list.add(1, "B");
ならABCDと問題なく表示される。
setメソッド
第1引数にインデックス、第2引数に置き換える値を受け取ることで、値を上書きする。
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("A");
list.set(0, "B");
list.add("C");
list.set(1, "D");
for (String str: list) {
System.out.println(str); // B D
}
}
}
removeメソッド
リストから要素を削除するメソッド。
引数でObject型を受け取ると、equalsメソッドがtrueを戻す要素を同じもの(同値)と識別して削除する。削除対象が複数あった場合、インデックスの小さい方が1つだけ削除される。
public class Item {
private String name;
private int price;
public Item (String name, int price) {
this.name = name;
this.price = price;
}
public boolean equals(Object obj) {
// 同じインスタンスであればtrue
if (obj instanceof Item) {
Item tmp = (Item) obj;
if (tmp.name.equals(this.name)) {
return true;
}
}
return false;
}
public String getName() {
return this.name;
}
public int getPrice() {
return this.price;
}
}
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
ArrayList<Item> list = new ArrayList<>();
list.add(new Item("A", 100));
list.add(new Item("B", 200));
list.add(new Item("C", 300));
list.add(new Item("A", 100));
list.remove(new Item("A", 500));
for (Item item: list) {
System.out.println(item.getName()+ ":" + item.getPrice());
}
}
}
// B:200
// C:300
// A:100
Itemクラスのequalsメソッドは、フィールドのnameが同じ値の場合にtrueを返す。
したがって、nameが同じ値かつ最初のインスタンスが削除される。
Arrayクラス
配列を操作するためのメソッドが提供されている。
asListメソッド
配列から固定長のリストインスタンスを作成できる。
(他にもListインタフェースのofメソッドを使用することで作成できる。)
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
// listインタフェースにあるofメソッドにより、
// 固定長のリストを作成
var list1 = List.of(1,2,3);
// IntegerクラスでのArrayListを作成
var list2 = new ArrayList<Integer>();
// 配列型インスタンスを作成
// そこから固定長のリストを作成
var list3 = Arrays.asList(new Integer[] {1,2,3});
//list3.add(0); // 例外がスローされる
list3.set(0, 0);
for (int i : list3) {
System.out.println(i); // 0 2 3
}
// サイズを指定して初期化する
var list4 = new ArrayList<Integer>(3);
list4.add(0);
list4.add(1);
list4.add(2);
list4.add(3);
for (int i : list4) {
System.out.println(i); // 0 1 2 3
}
}
}
mismatchメソッド
引数で渡された2つの配列を先頭から順番に比較し、一致しない要素のインデックスを戻す。
比較対象 | 戻り値 |
---|---|
全て一致している | -1 |
違う箇所がある | 相違する最初のインデックス |
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
String[]a = {"a", "b", "c"};
String[]b = {"a", "b", "c"};
String[]c = {"a", "e", "c"};
String[]d = {"a", "b"};
System.out.println(Arrays.mismatch(a, b)); // -1
System.out.println(Arrays.mismatch(a, c)); // 1
System.out.println(Arrays.mismatch(a, d)); // 2
}
}
compareメソッド
2つの配列を辞書順に並べたときの並べ順を比較する。
(アルファベット順がわかりやすい。)
mport java.util.Arrays;
public class Main {
public static void main(String[] args) {
String[]a = {"A", "B"};
String[]b = {"A", "B"};
String[]c = {"B", "A"};
String[]d = {"A"};
// 全く同じ
System.out.println(Arrays.compare(a, b)); // 0
// 第1引数が先
System.out.println(Arrays.compare(a, c)); // -1
// 第2引数が先
System.out.println(Arrays.compare(c, a)); // 1
// 要素数が異なる場合
System.out.println(Arrays.compare(a, d)); // 1
System.out.println(Arrays.compare(d, a)); // -1
}
}
Listインタフェース removeifメソッド
引数で渡されたラムダ式がtrueの場合、コレクション内の要素を削除する。
対象のコレクションから直接削除される。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
// 1.String配列からコレクションを作成後
// 2.ArrayListを作成
List<String> list = new ArrayList<>(
Arrays.asList(new String[] {"A", "B", "C"})
);
list.removeIf(
(String s) -> {
return s.equals("B");
}
);
System.out.println(list); // [A, C]
}
}
Mapコレクション
java.util.Mapはキーでオブジェクトを管理するコレクション。
Mapはインタフェースであり、HashMapは実装クラスの1つに該当する。
特徴
- キーはオブジェクト型であれば使用できる
- 値の重複は問題ないが、キーの重複はできない
- キーでの検索ができなくなるため
- 同じキーで値が渡されると、後のものに上書きされる
- HashMapクラスはキー、値ともにnullが可能
public class Item {
private int id;
private String name;
public Item(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return this.id;
}
public String getName() {
return this.name;
}
}
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
Map<Integer, Item> map = new HashMap<Integer, Item>();
map.put(1, new Item(1, "A"));
map.put(2, new Item(2, "B"));
map.put(3, new Item(3, "C"));
map.put(1, new Item(1, "A"));
map.put(null, new Item(0, "default"));
System.out.println(map.size()); // 4
}
}
ラッパークラス
プリミティブ型に対応したクラスのことを、ラッパークラスと呼ぶ。
ラッパークラスは、プリミティブ型の値を扱うためのメソッドを持っている。
プリミティブ型に関しては、[Java Silver SE11 2章]
(https://qiita.com/yasuro/items/5c3f13901a4289254dec)を参照
以下に例を記載する。
プリミティブ型 | ラッパークラス |
---|---|
int | Integer |
double | Double |
boolean | Boolean |
char | Character |
public class Sample {
public static void main(String[] args) {
char a = '0';
int num = 0;
// 引数がアルファベットか調べる true or false
if (Character.isAlphabetic(a)) {
num++;
}
// 引数が数字か調べる true or false
if(Character.isDigit(a)) {
num++;
}
// 引数が小文字か調べる true or false
if(Character.isLowerCase(a)) {
num++;
}
System.out.println(num); // 1
}
}
// 数字の0は小文字に分類されていない
LocalDateクラス
日付を取り扱うクラスで、immutableであるため変更を加えても変更された新しいインスタンスへの参照が入る。
また以下のようなさまざなメソッドが用意されている。
メソッド | 内容 |
---|---|
of() | 日付を指定してインスタンスを作成 |
now() | 現在の日付でインスタンスを作成 |
parse() | 文字列の日付をLocalDateクラスに変換する |
import java.time.LocalDate;
public class Sample {
public static void main(String[] args) {
// 日付を指定
LocalDate a = LocalDate.of(2015, 1, 1);
// 文字列の日付をLocalDateクラスに変換
LocalDate b = LocalDate.parse("2015-01-01");
// 現在の日付
LocalDate c = LocalDate.now();
System.out.println(a.equals(b)); // true
System.out.println(a); // 2015-01-01
System.out.println(b); // 2015-01-01
System.out.println(c); // 2022-02-21
}
}