1.

Java ArrayList 要素数カウント完全ガイド

編集
この記事の要点
  • ArrayList の要素数は list.size()。内部で int フィールドを返すだけなので O(1)
  • 配列は arr.length(メソッドではなくフィールド)、Map は map.size()、Set も set.size()
  • 条件付きカウントは Stream で list.stream().filter(条件).count() (戻り値は long)
  • 特定値の出現回数は Collections.frequency(list, value)
  • null 要素もカウントに含まれる。null だけ数えるなら list.stream().filter(Objects::isNull).count()

結論: 一行で数える

import java.util.*;

List<String> list = new ArrayList<>(List.of("a", "b", "c", "b", null));

int n = list.size();                // 5
System.out.println(n);

ArrayList#size() は内部に保持している int size フィールドを返すだけなので、常に O(1)。100 万件あっても 1 億件あっても同じ速度です。

コレクション種別ごとの要素数

対象取得方法計算量備考
配列 int[] / String[]arr.lengthO(1)メソッドではなくフィールド。括弧なし
ArrayList / LinkedListlist.size()O(1)内部カウント変数
HashMap / TreeMapmap.size()O(1)キーの数
HashSet / TreeSetset.size()O(1)重複排除後の数
String の文字数s.length()O(1)サロゲートペア注意
Stream の要素数stream.count()O(N)全要素を消費
Iteratorカウンタを自前で増やしてループO(N)専用メソッド無し
File 行数Files.lines(path).count()O(N)全行読み込み

条件付きカウント (Stream)

import java.util.stream.*;

List<Integer> nums = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

// 偶数の個数
long evens = nums.stream().filter(n -> n % 2 == 0).count();   // 5
System.out.println(evens);

// 文字列リストで長さ 3 以上の数
List<String> words = List.of("a", "ab", "abc", "abcd");
long longWords = words.stream().filter(s -> s.length() >= 3).count();  // 2

// User オブジェクトで age >= 20 の数
long adults = users.stream()
    .filter(u -> u.getAge() >= 20)
    .count();

// 注意: count() の戻り値は long
int adultsInt = (int) adults;   // int への変換に注意

特定の値の出現回数

import java.util.*;

List<String> list = List.of("apple", "banana", "apple", "orange", "apple");

// 方法1: Collections.frequency (推奨、シンプル)
int n = Collections.frequency(list, "apple");      // 3

// 方法2: Stream
long n2 = list.stream().filter("apple"::equals).count();   // 3

// 全要素の出現回数を Map で
Map<String, Long> counts = list.stream()
    .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
// {apple=3, banana=1, orange=1}

System.out.println(counts);

null 要素のカウント

List<String> list = Arrays.asList("a", null, "b", null, "c");

// 全体の数 (null も含む)
int total = list.size();                                          // 5

// null の数
long nulls = list.stream().filter(Objects::isNull).count();       // 2

// null でない数
long nonNulls = list.stream().filter(Objects::nonNull).count();   // 3

// Collections.frequency でも null を数えられる
int nulls2 = Collections.frequency(list, null);                   // 2

2 次元・ネストされた要素の合計

// 二重リスト
List<List<Integer>> matrix = List.of(
    List.of(1, 2, 3),
    List.of(4, 5),
    List.of(6, 7, 8, 9)
);

// 全要素の合計数
int total = matrix.stream().mapToInt(List::size).sum();   // 9

// flatMap で平坦化してから count
long total2 = matrix.stream().flatMap(List::stream).count();   // 9

// Map<String, List<X>> の値合計
Map<String, List<Order>> byUser = ...;
int totalOrders = byUser.values().stream().mapToInt(List::size).sum();

パフォーマンス比較

方法計算量適用場面
list.size()O(1)全要素数
arr.lengthO(1)配列
stream().count()O(N)Stream の終端操作
stream().filter(...).count()O(N)条件付き
Collections.frequency(c, v)O(N)特定値の出現回数
ループでカウンタ++O(N)古典的 / Iterator しか取れないとき

注意点

1. ArrayList の size() は同期化されていない

// マルチスレッドで add しながら size() を呼ぶと一貫性が崩れる
// → CopyOnWriteArrayList / Collections.synchronizedList / 専用ロック を使う

List<String> safe = Collections.synchronizedList(new ArrayList<>());
int n;
synchronized (safe) {
    n = safe.size();   // この瞬間の値
}

2. Iterator では size() が無い

Iterator<String> it = list.iterator();

// ❌ size() メソッドは存在しない
// int n = it.size();

// ✅ ループで自前カウント
int count = 0;
while (it.hasNext()) {
    it.next();
    count++;
}
// この後 it は使い切られている (再利用不可)

3. Stream は一度しか消費できない

Stream<String> s = list.stream();

long n = s.count();              // OK
// long m = s.count();           // ❌ IllegalStateException: stream has already been operated upon or closed

// 再度数えたいなら list から新しい Stream を作る
long n2 = list.stream().count();   // OK

FAQ

Q: list.length() と書けるか?
A: 書けません。配列だけが .length (フィールド)、List / Set / Map は .size() (メソッド)、String は .length() (メソッド)。Java の歴史的な不統一です。

Q: 1000 万件の ArrayList で size() は遅い?
A: O(1) なので件数に関係なく一瞬。LinkedList でも size() は O(1)(内部カウントを持つ)。ただし「N 番目の要素取得」は LinkedList で O(N)。

Q: int vs long のカウント値
A: list.size()int (最大 21 億)、stream().count()long。21 億超のデータでは int ではオーバーフロー。

編集
Post Share
子ページ

子ページはありません

同階層のページ

同階層のページはありません

最近更新/作成されたページ