Группа путем подсчета в Java 8 stream API
Я пытаюсь найти простой способ в Java 8 stream 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]));
Я ценю ваш вклад.
6 ответов:
Я думаю, что вы просто ищете перегрузка что делает еще один
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()));
вот простое решение от StreamEx
StreamEx.of(list).groupingBy(Function.identity(), Collectors.countingInt());уменьшить шаблонный код:
collect(Collectors.
вот пример для списка объектов
Map<String, Long> requirementCountMap = requirements.stream().collect(Collectors.groupingBy(Requirement::getRequirementType, Collectors.counting()));
здесь немного разные варианты для выполнения поставленной задачи.
используя
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));
если вы открыты для использования сторонней библиотеки, вы можете использовать
Collectors2класс Коллекции Eclipse преобразование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}в данном конкретном случае, вы можете просто
collecttheListнепосредственно вBag.Bag<String> counted = list.stream().collect(Collectors2.toBag());вы также можете создать
Bagбез использованияStreamпо адаптацииListс протоколами коллекций Eclipse.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");A
Bag<String>какMap<String, Integer>в том, что он внутренне отслеживает ключи и их количество. Но, если вы спроситеMapдля ключа, который он не содержит, он вернетсяnull. Если вы спроситеBagдля ключа он не содержит, используяoccurrencesOf, это возвратит 0.Примечание: я коммиттер для коллекций Eclipse.
Comments