세트가있는 목록에서 항목 발생 횟수를 계산하는 방법은 무엇입니까?

Nov 15 2020

List<Set<String>>다음과 같은 모양이 있다고 가정 해 보겠습니다 .

[A,B,C,D]
[B,C,D,E]
[C,D,E,F]
[D,E,F,G]

나는 각 각 값 (A, B, C, D, E, F, G)를 사용하려면 Set<String>한다는 점에서 List<Set<String>>그들 매핑하여 그 발생을 계산, 내가 그것을 구현하기위한 좋은 방법은 무엇입니까? 출력을 다음과 같이 만들고 싶습니다.

A: 1
B: 2
C: 3
D: 4
E: 3
F: 2
G: 1

답변

4 WJS Nov 16 2020 at 00:18

목록을 단일 스트림으로 평면화하고 groupingBy수집기를 사용하십시오 .

  • 먼저 목록을 스트리밍하십시오. 이것은 더 작은 목록의 스트림을 만듭니다.
  • 그런 다음 스트리밍해야합니다. 그러나 당신은 4 개의 편지 스트림을 원하지 않습니다. 16 자 (또는 모든 세트의 합계)의 스트림 하나를 원합니다. 그것이 flatMap이하는 일입니다. 여러 스트림을 하나로 병합합니다.
  • 그런 다음 주파수 계산을 원합니다. 따라서 자신을 키로 사용하여 문자를 그룹화하려고합니다. 기본적 groupingBy으로 목록을 만들고 목록에 충돌 (중복 키와 관련된 값)을 넣습니다.
  • 하지만 당신은 그것을 원하지 않습니다. 그래서 Collectors.counting()만약 당신이 이미 거기에있는 다른 키를 본다면, 그저 카운트를 유지하고 값을 1만큼 업데이트하십시오. 그래서 당신은 키의 발생을 세고 있습니다.
List<Set<String>> list = List.of(Set.of("A", "B", "C", "D"),
        Set.of("B", "C", "D", "E"),
        Set.of("C", "D", "E", "F"),
        Set.of("D", "E", "F", "G"));

Map<String, Long> freq =
        list.stream().flatMap(Set::stream).collect(Collectors
                .groupingBy(a -> a, Collectors.counting()));

freq.entrySet().forEach(System.out::println);

인쇄물

A=1
B=2
C=3
D=4
E=3
F=2
G=1

다음은 기본 groupingBy동작 의 간단한 예입니다 . 로 나눌 때 나머지 값을 기준으로 목록에 값을 넣습니다 10. 수집 할 개체 ( 이 경우)로 변환해야하는 IntStream스트림을 생성합니다 .int primitivesInteger

Map<Integer, List<Integer>> remainders =
        IntStream.range(0, 100).mapToObj(Integer::valueOf)
                .collect(Collectors.groupingBy(n -> n % 10));

remainders.entrySet().forEach(System.out::println); 

인쇄물

0=[0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
1=[1, 11, 21, 31, 41, 51, 61, 71, 81, 91]
2=[2, 12, 22, 32, 42, 52, 62, 72, 82, 92]
3=[3, 13, 23, 33, 43, 53, 63, 73, 83, 93]
4=[4, 14, 24, 34, 44, 54, 64, 74, 84, 94]
5=[5, 15, 25, 35, 45, 55, 65, 75, 85, 95]
6=[6, 16, 26, 36, 46, 56, 66, 76, 86, 96]
7=[7, 17, 27, 37, 47, 57, 67, 77, 87, 97]
8=[8, 18, 28, 38, 48, 58, 68, 78, 88, 98]
9=[9, 19, 29, 39, 49, 59, 69, 79, 89, 99]
3 VladL Nov 16 2020 at 00:20
        List<Set<String>> input = new ArrayList<>();
        input.add(Set.of("A", "B", "C", "D"));
        input.add(Set.of("B", "C", "D", "E"));
        input.add(Set.of("C", "D", "E", "F"));
        input.add(Set.of("D", "E", "F", "G"));

        input.stream()
                .flatMap(Collection::stream)
                .collect(groupingBy(Function.identity(), counting()))
                .entrySet()
                .forEach(System.out::println);

수입

import java.util.*;
import java.util.function.Function;

import static java.util.stream.Collectors.counting;
import static java.util.stream.Collectors.groupingBy;
2 AlexRudenko Nov 16 2020 at 00:16

Stream API를 사용하면 flatMap내부 세트를 사용하여 문자열 스트림을 가져와야하며 그 후에 주파수 맵이 작성됩니다.

        
List<Set<String>> data = Arrays.asList(
    Set.of("A", "B", "C", "D"),
    Set.of("B", "C", "D", "E"),
    Set.of("C", "D", "E", "F"),
    Set.of("D", "E", "F", "G")
);
        
data.stream()
    .flatMap(Set::stream)
    .collect(Collectors.toMap(s -> s, s -> 1, Integer::sum, LinkedHashMap::new))
    .entrySet()
    .forEach(System.out::println);

산출:

A=1
B=2
C=3
D=4
E=3
F=2
G=1