IntSummaryStatistics の活用 — 集計情報取得の便利型
IntSummaryStatistics は「int の集計情報」をひとまとめに持つユーティリティです。件数・合計・最小値・最大値・平均を一発で計算・保持でき、Stream と相性抜群。レポートや検証に使うとコードがスッキリします。
しくみと特徴
- 保持する情報:
- 件数(count)、合計(sum)、最小値(min)、最大値(max)、平均(average)
- 取得メソッド:
- getCount(), getSum(), getMin(), getMax(), getAverage()
- 利用場面:
- Stream の summarizingInt と組み合わせる/自前で accept して集計する
基本コード例(すぐ試せる)
Stream で統計を一発取得
import java.util.*;
import java.util.stream.*;
public class IntStatsBasic {
public static void main(String[] args) {
List<Integer> nums = List.of(10, 20, 30, 40);
IntSummaryStatistics stats =
nums.stream()
.collect(Collectors.summarizingInt(Integer::intValue));
System.out.println("count=" + stats.getCount());
System.out.println("sum=" + stats.getSum());
System.out.println("min=" + stats.getMin());
System.out.println("max=" + stats.getMax());
System.out.println("avg=" + stats.getAverage());
}
}
Java自前で累積(accept を使う)
IntSummaryStatistics stats = new IntSummaryStatistics();
for (int n : new int[]{3, 7, 2}) {
stats.accept(n); // 値を投入
}
System.out.println(stats); // IntSummaryStatistics{count=3, sum=12, min=2, average=4.0, max=7}
Java例題で理解する
例題1: 学生の点数統計
record Student(String name, int score) {}
List<Student> students = List.of(
new Student("Tanaka",80),
new Student("Sato",55),
new Student("Ito",90)
);
IntSummaryStatistics stats =
students.stream()
.collect(Collectors.summarizingInt(Student::score));
System.out.printf("人数=%d 合計=%d 最小=%d 最大=%d 平均=%.1f%n",
stats.getCount(), stats.getSum(), stats.getMin(), stats.getMax(), stats.getAverage());
Java例題2: 商品価格の統計レポート文字列
record Product(String name, int price) {}
List<Product> products = List.of(
new Product("A",100),
new Product("B",250),
new Product("C",160)
);
IntSummaryStatistics stats =
products.stream()
.collect(Collectors.summarizingInt(Product::price));
String report = String.format(
"価格統計: 件数=%d, 合計=%d, 最小=%d, 最大=%d, 平均=%.2f",
stats.getCount(), stats.getSum(), stats.getMin(), stats.getMax(), stats.getAverage());
System.out.println(report);
Java例題3: ファイルから読み込んだ数値の統計(行ごとに int)
import java.nio.file.*;
import java.io.IOException;
Path path = Paths.get("numbers.txt");
try (var lines = Files.lines(path)) {
IntSummaryStatistics stats =
lines.mapToInt(Integer::parseInt)
.summaryStatistics();
System.out.println(stats);
}
Java応用パターン(組み合わせが効く)
- groupingBy × summarizingInt(カテゴリ別統計)
record Item(String category, int value) {}
List<Item> items = List.of(
new Item("A", 10),
new Item("A", 25),
new Item("B", 5)
);
Map<String, IntSummaryStatistics> byCat =
items.stream()
.collect(Collectors.groupingBy(
Item::category,
Collectors.summarizingInt(Item::value)
));
byCat.forEach((cat, stats) -> System.out.println(cat + " -> " + stats));
Java- partitioningBy × summarizingInt(条件で二分統計)
Map<Boolean, IntSummaryStatistics> passStats =
students.stream()
.collect(Collectors.partitioningBy(
s -> s.score >= 60,
Collectors.summarizingInt(Student::score)
));
System.out.println("合格側: " + passStats.get(true));
System.out.println("不合格側: " + passStats.get(false));
Java- map 経由で派生値の統計
IntSummaryStatistics lengthStats =
Stream.of("Java", "Stream", "Stats")
.mapToInt(String::length)
.summaryStatistics();
Javaテンプレート集(そのまま使える)
- 基本統計(int)
IntSummaryStatistics stats =
stream.collect(Collectors.summarizingInt(x -> 値));
Java- プリミティブストリームで統計
IntSummaryStatistics stats =
IntStream.of(値1, 値2, 値3).summaryStatistics();
Java- カテゴリ別の統計
Map<K, IntSummaryStatistics> map =
stream.collect(Collectors.groupingBy(kFn, Collectors.summarizingInt(vFn)));
Java- 条件二分の統計
Map<Boolean, IntSummaryStatistics> map =
stream.collect(Collectors.partitioningBy(cond, Collectors.summarizingInt(vFn)));
Java- 自前投入(外部ループから)
IntSummaryStatistics stats = new IntSummaryStatistics();
list.forEach(n -> stats.accept(n));
Java落とし穴と回避策
- 空データ: count=0、sum=0、minは Integer.MAX_VALUE、maxは Integer.MIN_VALUE、average は NaN。出力前に件数チェックや
Double.isNaNを使う。 - オーバーフロー: sum は int。合計が大きくなり得るなら LongSummaryStatistics を検討。
- 型変換の負荷: Boxed の Integer を扱うより、
mapToIntやIntStreamを使ってオートボクシングを避けると効率的。 - 並列処理:
summaryStatistics()やsummarizingIntは並列ストリームでも安全に集約される。副作用のある外部更新は避ける。 - NPE 対策: 元データが null を含むなら事前に
filter(Objects::nonNull)を挟む。
まとめ
- IntSummaryStatistics は「件数・合計・最小・最大・平均」をひとまとめに管理できる便利型。
- summarizingInt、summaryStatistics と組み合わせるだけで、単純からカテゴリ別・二分統計まで一気に書ける。
- 空データやオーバーフローに注意しつつ、プリミティブストリームを活用すれば高速・安全なレポートが作れる。
👉 練習課題: 売上レコードから「店舗別の売上統計(件数・合計・最小・最大・平均)」を groupingBy + summarizingInt で作り、平均が NaN の店舗は「データなし」と表示してみてください。
