web-dev-qa-db-ja.com

Java 8ストリームAPIでカウントしてグループ化する

Java 8ストリームAPIでグループ化を行う簡単な方法を見つけようとしましたが、この複雑な方法を思いつきました!

List<String> list = new ArrayList<>();

list.add("Hello");
list.add("Hello");
list.add("World");

Map<String, List<String>> collect = list.stream().collect(
        Collectors.groupingBy(o -> o));
System.out.println(collect);

List<String[]> collect2 = collect
        .entrySet()
        .stream()
        .map(e -> new String[] { e.getKey(),
                String.valueOf(e.getValue().size()) })
        .collect(Collectors.toList());

collect2.forEach(o -> System.out.println(o[0] + " >> " + o[1]));

ご意見ありがとうございます。

132
Muhammad Hewedy

私はあなたが オーバーロード を探しているだけだと思う​​と、別のCollectorが各グループで何をするかを指定します...そしてCollectors.counting()を数えます:

import Java.util.*;
import Java.util.stream.*;

class Test {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();

        list.add("Hello");
        list.add("Hello");
        list.add("World");

        Map<String, Long> counted = list.stream()
            .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));

        System.out.println(counted);
    }
}

結果:

{Hello=2, World=1}

(効率を高めるためにgroupingByConcurrentを使用する可能性もあります。実際のコードでは、コンテキストで安全である場合に留意してください。)

284
Jon Skeet
    List<String> list = new ArrayList<>();

    list.add("Hello");
    list.add("Hello");
    list.add("World");

    Map<String, List<String>> collect = list.stream().collect(
            Collectors.groupingBy(o -> o));
    System.out.println(collect); 
    collect.entrySet().forEach(e -> System.out.println(e.getKey() + " >> " + e.getValue().size()));
6
Sivakumar

ここでは、当面のタスクを達成するためのわずかに異なるオプションを示します。

toMapを使用:

list.stream()
    .collect(Collectors.toMap(Function.identity(), e -> 1, Math::addExact));

Map::mergeを使用:

Map<String, Integer> accumulator = new HashMap<>();
list.forEach(s -> accmulator.merge(s, 1, Math::addExact));
4
Aomine

オブジェクトのリストの例を次に示します

Map<String, Long> requirementCountMap = requirements.stream().collect(Collectors.groupingBy(Requirement::getRequirementType, Collectors.counting()));
4
fjkjava

StreamEx による簡単なソリューションを次に示します。

StreamEx.of(list).groupingBy(Function.identity(), Collectors.countingInt());

定型コードを減らす:collect(Collectors.

3
user_3380739

サードパーティのライブラリを使用する場合は、 Eclipse CollectionsCollectors2クラスを使用して、Listを使用してBagStreamに変換できます。 Bagカウント用に構築 のデータ構造です。

Bag<String> counted =
        list.stream().collect(Collectors2.countBy(each -> each));

Assert.assertEquals(1, counted.occurrencesOf("World"));
Assert.assertEquals(2, counted.occurrencesOf("Hello"));

System.out.println(counted.toStringOfItemToCount());

出力:

{World=1, Hello=2}

この特定のケースでは、単にcollectListからBagに直接入れることができます。

Bag<String> counted = 
        list.stream().collect(Collectors2.toBag());

BagをEclipse Collectionsプロトコルに適合させることにより、Streamを使用せずにListを作成することもできます。

Bag<String> counted = Lists.adapt(list).countBy(each -> each);

またはこの特定の場合:

Bag<String> counted = Lists.adapt(list).toBag();

バッグを直接作成することもできます。

Bag<String> counted = Bags.mutable.with("Hello", "Hello", "World");

Bag<String>は、キーとそのカウントを内部的に追跡するという点でMap<String, Integer>に似ています。ただし、Mapに含まれていないキーを要求すると、nullが返されます。 Bagを使用して、occurrencesOfに含まれていないキーを要求すると、0が返されます。

注:私はEclipse Collectionsのコミッターです。

1
Donald Raab