zenet_logo

-株式会社ゼネット技術ブログ-

ArrayListの処理をスマートに! Stream APIの魅力

 

 

はじめに

初めまして、社会人1年目の池澤です。

現在、会社でJava研修を受けています。

 

 

本題

今回は下記ようなArrayListの処理をする際にfor文が複雑化してしまいました。

  • タスク一覧から完了済みのタスクを取得する
  • 完了時刻が新しい2つのタスクを取得する
  • 空の要素が無いように配列のサイズを調整する

そこで、for文を使用せずにスマートに記述できないか調べましたので、簡単に紹介させていただきます。

 

Stream APIを使うことで、ArrayListの操作をスマートに行うことができます。

 

 

ソースコードの比較

実際に私が記述したStream APIとfor文を使用した際のソースコードで比較をさせていただきます。

 

  • Stream APIの場合

Task[] resultTasks = taskList.stream()
    .filter(task -> task.isCompletion())
    .sorted(Comparator.comparing(Task::getCompletionDate).reversed())
    .limit(maxSize)
    .toArray(Task[]::new);

上記のようにfor文と比較するとシンプルな記述ができます。

 

 

  • streamメソッド

ArrayListからStreamを生成するメソッドです。

このメソッドを呼び出すことでStream APIが使えるようになります。

そのため、Stream APIを使う上で最も重要なメソッドです。

 

 

  • filterメソッド

引数で渡された条件にヒットする要素を取得します。

例:20歳以上の人を取得する

Stream<Profile> stream = stream.filter(profile -> profile.age() >= 20);

 

 

  • sortedメソッド

引数で渡されたルールで要素をソートし、取得します。

例:年齢の昇順に並び変えて取得する

Stream<Profile> stream = stream.sorted(Comparator.comparing(Profile::age));

 

 

  • limitメソッド

引数で渡された数を上限としてStreamの要素を取得します。

例:5人分のプロフィールを取得する

Stream<Profile> stream = stream.limit(5);

 

 

  • toArrayメソッド

StreamをArrayListに変換します。

Stream APIを使った際に最後に使うメソッドです。

 

 

  • for文の場合

ArrayList<Task> tempTaskList = new ArrayList<Task>();
for (Task task : taskList) {
    if (task.isCompletion()) {
        tempTaskList.add(task);
    }
}
int count = 0;
Task[] tempTasks = new Task[maxSize];
tempTaskList.sort(Comparator.comparing(Task::getCompletionDate).reversed());
for (int i = 0; i < tempTaskList.size(); i++) {
Task task = tempTaskList.get(i);
if (count < maxSize) {
    tempTasks[i] = task;
    count++;
    }
}
Task[] resultTasks = Arrays.copyOf(tempTasks, count);

上記のように2回繰り返し文を記述したり、繰り返し文内で条件分岐を行ったりと複雑な処理になってしまいました。

 

今回使用したタスクを管理するためのクラスは下記の通りです。

タスクの追加、完了状況の確認、完了日の取得が簡単に行えます。

public class Task {
    private String content;
    private boolean completion = false;
    private Date completionDate = null;

    public Task(String content) {
        this.content = content;
    }

    public void Complete(Date completionDate) {
        completion = true;
        this.completionDate = completionDate;
    }

    public String getContent() {
        return content;
    }

    public boolean isCompletion() {
        return completion;
    }

    public Date getCompletionDate() {
        return completionDate;
    }
}

 

 

まとめ

Stream APIを使うことで、ArrayListの操作が簡潔になり、コードも読みやすくなります。

皆さんもぜひStream APIを使ってArrayListの処理をスマートに記述してみましょう!

 

参考文献

入門Javaのラムダ式とStream API #Java - Qiita

Stream (Java Platform SE 8)