9
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

PLISEAdvent Calendar 2019

Day 12

意外と知らないMapの便利な使い方

Last updated at Posted at 2019-12-05

コレクションの利用

Javaでプログラミングを行う際には List, Map, Set などのコレクションを利用するのはほぼ必須といっても過言ではないかと思います。
その中でもMap はキー・バリュー形式でデータ管理を行えるため、データを事前に取得してMapに詰め込んでおき再利用するといったシーンで多く使われます。

特にJava8 から Stream API や ラムダ式、Optional 等が追加されコレクションがより使いやすくなりました。
ただこれらの追加機能の陰に隠れて実は便利なメソッドがたくさん追加されているのはご存知でしょうか。
今回はそんな便利なメソッドをいくつか紹介します。

データが取得できない時に初期値をゲット! (getOrDefaut)

会員コード毎にお店で使えるポイントを保持するMapがあったとします。

Map<String, Integer> pointMap = new HashMap<>();

ある会員がポイントを保持していない場合0ポイントを返したいといったロジックの場合以下のように記述し取得することができます。

int point = 0;

// ポイントを保持している場合ポイントを取得
if (pointMap.containsKey(code)) {
    point = pointMap.get(code);
}

いちいち判定するのは面倒だし美しくないですね。
そこで getOrDefault の出番です。

int point = pointMap.getOrDefault(code, 0);

すっきりと1行で書けましたね。
マップに値が入っていない場合にはある値を取得したいという時にこのようなコードを書くことができます。

値を保持していない場合のみセット! (putIfAbsent)

先程のポイント情報に対して、まだポイントを保持していない会員のみポイントを付与するというロジックを書くとします。

// ポイントを保持していない場合ポイントを付与
if (!pointMap.containsKey(code)) {
    pointMap.put(code, point);
}

これを Java8からは以下のように書くことができます。

pointMap.putIfAbsent(code, point);

このコードでは会員に紐づくポイントが無い場合にのみ point をセットする形になります。

値を保持していない場合初期値をセット! (computeIfAbsent)

ある学生のテストの点数の履歴を追加して保持するMapがあったとします。

Map<String, List<Integer>> scoreMap = new HashMap<>();

既に点数が保持されている学生がいる場合は、その点数の後に履歴として新しい点数を加えていきます。

List<Integer> scores = scoreMap.get(code);

// 学生の点数がまだ記録されていない場合
if (scores == null) {
    // 新しい履歴用のリストを作成
    scores = new ArrayList<>();
    scoreMap.put(code, scores);
}

scores.add(score);

Mapから取得できなかった場合にいちいちListをセットし、そのListに点数を追加する必要があります。
これを computeIfAbsent を使うと以下のように書くことができます。

scoreMap.computeIfAbsent(code, k -> new ArrayList<>()).add(score);

もし学生のテスト結果が1件も保持されていない場合には新しいListを作成し、既に結果がある場合は既にあるListを返します。
そのまま返されたListに点数を追加しているため1行で書くことができるようになります。

値が保持されている場合に値を操作! (computeIfPresent)

授業に参加した学生の出席日数を保持するMapがあり、履修する生徒の学生コードと出席日数0がそれぞれ初期値で入っているとします。

Map<String, Integer> attendanceMap = new HashMap<>();

授業を履修していないが学生が来た場合は無視し、履修している学生は出席日数を1増やすとします。

if (attendanceMap.containsKey(code)) {
    attendanceMap.put(code, attendanceMap.get(code) + 1) ;
}

これを computeIfPresent を使用すると以下のように書くことができます。

attendanceMap.computeIfPresent(code, (k, v) -> v + 1);

computeIfPresent では学生コードに該当する出席日数が存在しない場合には何も処理をせず、該当する学生がいる場合のみ値(出席日数)を増やすことができます。

まとめ

Java8から Stream や ラムダ式など大きく機能が追加されましたが、実は便利な機能がその他にもたくさん増えていっています。
必要な時に必要なAPIをネットで探すのもよいですが、辞書を読んでみるように公式のAPIドキュメントを読んでみるのも面白いですよ。

9
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?