ビジネス課題への解決策(アイディア)と、新たな発想(+α)が見つかるIT情報メディア

Menu
  1. TOP
  2. データ活用
  3. Java 8のラムダ式とStream APIを使ってみる

Java 8のラムダ式とStream APIを使ってみる

  • LINEで送る
  • このエントリーをはてなブックマークに追加
Java 8からラムダ式とStream APIが新しく追加されますので、試しに使ってみます。

 

まず従来のJava 7ではListからフィルターして表示するのに、以下のような記述をします。

 

import java.util.Arrays;
import java.util.List;

public class Jdk7List {
public static void main(String[] args) {
String[] values = {"A001", "B001", "AB001", "BA001"};
List list = Arrays.asList(values);
for (String e : list) {
if (e.startsWith("A")) {
System.out.println(e);
}
}
}
}

 

実行するとA001とAB001が表示されます。

 

Java 8ではStream APIを使ってラムダ式を記述できます。

 

import java.util.Arrays;
import java.util.List;

public class Jdk8List {
public static void main(String[] args) {
String[] values = {"A001", "B001", "AB001", "BA001"};
List list = Arrays.asList(values);
list.stream()
.filter(e -> e.startsWith("A"))
.forEach(e -> System.out.println(e));
}
}

 

実行するとJava 7と同じくA001とAB001が表示されます。

 

今度はparallelStreamを使って、パフォーマンスを計測してみます。

 

SalesDataクラスを用意し、データを生成させる。

 

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

public class SalesData {
private Date date; // 売上日
private int salesAmount; // 売上金額
private String location; // 地域

public SalesData(Date date, int salesAmount, String location){
this.date = date;
this.salesAmount = salesAmount;
this.location = location;
}

public int getSalesAmount() {
return salesAmount;
}

public String getLocation() {
return location;
}

private static final int[] SALES_AMOUNTS = {
1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000
};
private static final String[] LOCATIONS = {
"東京", "千葉", "埼玉", "神奈川", "茨城", "栃木", "群馬"
};
public static List createSalesDateList() {
List salesDataList = new ArrayList();
// 2014/1/1のDateを生成
Calendar calendar = Calendar.getInstance();
calendar.clear();
calendar.set(2014, 1, 1);

// 1,000,000日分のデータを作成する
for (int i = 0; i < 1000000; i++) {
Date salesDate = calendar.getTime();
// 売上金額ごとのデータを作成する
for (int salesAmount : SALES_AMOUNTS) {
// 地域ごとのデータを作成する
for (String location : LOCATIONS) {
salesDataList.add(new SalesData(salesDate, salesAmount, location));
}
}
calendar.add(Calendar.DAY_OF_MONTH, 1); // 日付を1日加算
}
return salesDataList;
}
}

 

従来のloop、stream、parallelStreamの比較のため、5回実行する。

 

import java.util.List;

public class Main {
public static void main(String[] args) {
List salesDataList = SalesData.createSalesDateList();
for (int i=0; i<5; i++) loop(salesDataList);
for (int i=0; i<5; i++) stream(salesDataList);
for (int i=0; i<5; i++) parallelStream(salesDataList);
}
static void loop(List salesDataList) {
long start = System.currentTimeMillis();
int maxSalesAmount = -1;
for (SalesData salesData : salesDataList) {
// 地域が「東京」のもので絞る
if (salesData.getLocation().equals("東京")) {
// 最大の売り上げを取得する
if (maxSalesAmount < 0) {
maxSalesAmount = salesData.getSalesAmount();
} else if (maxSalesAmount < salesData.getSalesAmount()) {
maxSalesAmount = salesData.getSalesAmount();
}
}
}
long end = System.currentTimeMillis();
System.out.println("loop: time=" + (end - start) + "ms");
}
static void stream(List salesDataList) {
long start = System.currentTimeMillis();
int maxSalesAmount = salesDataList.stream()
.filter(salesData -> salesData.getLocation().equals("東京"))
.mapToInt(salesData -> salesData.getSalesAmount())
.max()
.getAsInt();
long end = System.currentTimeMillis();
System.out.println("stream: time=" + (end - start) + "ms");
}
static void parallelStream(List salesDataList) {
long start = System.currentTimeMillis();
int maxSalesAmount = salesDataList.parallelStream()
.filter(salesData -> salesData.getLocation().equals("東京"))
.mapToInt(salesData -> salesData.getSalesAmount())
.max()
.getAsInt();
long end = System.currentTimeMillis();
System.out.println("parallelStream: time=" + (end - start) + "ms");
}
}

 

実行結果はこちら

 

loop: time=315ms
loop: time=290ms
loop: time=284ms
loop: time=274ms
loop: time=273ms
stream: time=340ms
stream: time=296ms
stream: time=338ms
stream: time=330ms
stream: time=333ms
parallelStream: time=236ms
parallelStream: time=118ms
parallelStream: time=118ms
parallelStream: time=112ms
parallelStream: time=111ms

 

loopとstreamはほとんど変わらないかstreamの方が少し遅い。
parallelStreamの1回目はほとんど変わらないが、2回目以降に高速化していることが分かる。

 

【参考】
ラムダ式で本領を発揮する関数型インターフェースとStream APIの基礎知識 (3/3)

メールマガジンの登録はこちらから
メルマガ登録 お問い合わせ