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]));
ご意見ありがとうございます。
私はあなたが オーバーロード を探しているだけだと思うと、別の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
を使用する可能性もあります。実際のコードでは、コンテキストで安全である場合に留意してください。)
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()));
ここでは、当面のタスクを達成するためのわずかに異なるオプションを示します。
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));
オブジェクトのリストの例を次に示します
Map<String, Long> requirementCountMap = requirements.stream().collect(Collectors.groupingBy(Requirement::getRequirementType, Collectors.counting()));
StreamEx による簡単なソリューションを次に示します。
StreamEx.of(list).groupingBy(Function.identity(), Collectors.countingInt());
定型コードを減らす:collect(Collectors.
サードパーティのライブラリを使用する場合は、 Eclipse Collections のCollectors2
クラスを使用して、List
を使用してBag
をStream
に変換できます。 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}
この特定のケースでは、単にcollect
をList
から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のコミッターです。