Java 8 스트림 API에서 계산하여 그룹화


170

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]));

귀하의 의견에 감사드립니다.


1
여기서 무엇을 이루려고 노력하고 있습니까?
Keppil

2
매우 일반적인 경우입니다. 예를 들어 일정 기간 동안 오류가 발생 했으며이 기간 동안 매일 발생 횟수에 대한 통계를보고 싶습니다.
Muhammad Hewedy

답변:


340

나는 당신이 과부하 를 찾고 있다고 생각합니다. 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더 높은 효율성 을 위해 사용할 가능성도 있습니다. 실제 코드가 안전하다면 컨텍스트에서 염두에 두어야 할 것이 있습니다.)


1
완전한! ... javadoc에서and then performing a reduction operation on the values associated with a given key using the specified downstream Collector
Muhammad Hewedy

6
e-> e 대신 Function.identity () (정적 가져 오기 사용)를 사용하면 좀 더보기 좋습니다 : Map <String, Long> counted = list.stream (). collect (groupingBy (identity (), counting () ));
Kuchi

안녕하세요, 누군가가 코드의 Map 측면을 설명 할 수 있는지 궁금합니다 Map<String, Long> counted = list.stream() .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));.이 시점에서 정확히 무슨 일이 일어나고 있는지, 그리고 전송할 수있는 주제와 관련된 추가 설명이있는 링크
Blank

@Blank : 새로운 질문으로 가장 좋을 것 같은 느낌이 듭니다. 첫번째 이해합니다. 이해하지 못하는 비트를 모른 채 모든 측면을 살펴보면 시간이 오래 걸릴 것입니다.이 시점에서 5 세가 넘은 답변에 기꺼이 쓰는 것보다 더 많은 시간이 걸립니다. 이미 이해할 수 있습니다.
Jon Skeet

@ JonSkeet Cool, 나는 내 질문에서 이해하지 못하는 측면을 강조했지만 새로운 질문에 넣을 것입니다. 즉, 내가 추가 한 전체 코드 스 니펫.
공란

9
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));
collect.entrySet()
       .forEach(e -> System.out.println(e.getKey() + " - " + e.getValue().size()));

8

다음은 객체 목록의 예입니다.

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

8

현재 작업을 수행하기위한 약간 다른 옵션이 있습니다.

사용하여 toMap:

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

사용하여 Map::merge:

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

4

StreamEx 의 간단한 솔루션은 다음과 같습니다.

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

상용구 코드를 줄이십시오. collect(Collectors.


1
Java8 스트림에서 사용하는 이유는 무엇입니까?
Torsten Ojaperv

1

타사 라이브러리를 사용하여 열려 있다면, 당신은 사용할 수 Collectors2있는 클래스 이클립스 컬렉션을 을 변환하는 ListA가에 Bag사용 a Stream. A 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());

또한 Eclipse Collections 프로토콜 Bag을 사용 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");

A Bag<String>Map<String, Integer>내부적으로 키와 개수를 추적한다는 점에서 동일합니다. 그러나 Map포함하지 않은 키 를 요청하면 키가 반환 null됩니다. Bag키 를 요청하면 키가 포함되어 있지 않습니다.occurrencesOf 0을 반환합니다.

참고 : 저는 Eclipse Collections의 커미터입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.