Java에서 중복 키가있는 목록 그룹화 및 생성 [duplicate]

Nov 16 2020

변환하려고 List<Integer[]>Map<Integer, List<Integer>>.

따라서 이것은 List<Integer[]>아래의 예제에 대한 중복 키를 가지고 있습니다.

List<Integer[]> list = Arrays.asList(
    new Integer[] {1, 23},
    new Integer[] {2, 45},
    new Integer[] {3, 25},
    new Integer[] {1, 45},
    new Integer[] {2, 54}
);

요구 사항은 0 번째 인덱스로 그룹화하고 모든 값을 중복 키 아래에 다시 하위 목록에 넣는 아래 맵으로 변환하는 것입니다. 그래서 마지막으로 다음과 같습니다.

{1=[23, 45], 2=[45, 54], 3=[25]}

나는 현재 아래와 같은 스트림없이 이것을하고 있습니다. 그리고 그것이 스트림으로 어떻게 달성 될 수 있는지 확실하지 않습니다.

if (finalMap.containsKey(Integer.valueOf(dataList[0]))){
    List<Integer> currentList = finalMap.get(Integer.valueOf(dataList[0]));
    currentList.add(new Integer(Integer.valueOf(dataList[1])));
    List<Integer> newList = new ArrayList<>(currentList);
    finalMap.put(Integer.valueOf(dataList[0]), newList);
} else {
    finalMap.put(
        Integer.valueOf(dataList[0]), 
        new ArrayList<>(Arrays.asList(Integer.parseInt(dataList[1]))));
}

답변

2 NikolasCharalambidis Nov 16 2020 at 18:31

Collectors.groupingBy배열의 첫 번째 요소를 사용하여이를 달성 하고 매핑 수집기를 다운 스트림으로 사용하여 추가 값을 가져올 수 있습니다. 마지막으로 추가 다운 스트림 Collectors.toList이 값을 래핑합니다. AbstractMap.SimpleEntry배열 항목을 더 잘 조작하기 위해 사용 합니다.

이제,이 솔루션은 각 여부, 따라 Integer[]포함 정확히 2 항목 또는 2+ 항목 :


각 배열에 정확히 2 개의 항목

각각은 Integer[]항상 정확히 두 개의 항목을 포함 합니다 (예 :) new Integer[] {1, 23}. 사용 Collectors.mapping얻을 수 array[1]에 (항목의 값) 결과 List.

Map<Integer, List<Integer>> map = list.stream()
    .map(array -> new AbstractMap.SimpleEntry<>(array[0], array[1]))
    .collect(Collectors.groupingBy(
            AbstractMap.SimpleEntry::getKey, 
            Collectors.mapping(AbstractMap.SimpleEntry::getValue, Collectors.toList())));

실제로 SimpleEntry배열을 직접 처리 하면 사용법을 생략하고 전체 스트림을 단순화 할 수 있습니다.

Map<Integer, List<Integer>> map = list.stream()
    .collect(Collectors.groupingBy(
            array -> array[0],
            Collectors.mapping(array -> array[1], Collectors.toList())));

각 배열에 2 개 이상의 항목

각 항목 Integer[]에는 둘 이상의 항목이 포함될 수 있습니다 (예 :) new Integer[] {1, 23, 24}. 사용 Collectors.flatMapping얻을 array[1].. array[n]에 항목 (항목의 값) List. 올바른 그룹화를 수행하려면 먼저 배열을 분할해야합니다. 따라서 첫 번째 요소 array[0]는 키이고 array[1] .. array[n]값입니다. 이것이 플랫 매핑이 필요한 이유입니다.

Map<Integer, List<Integer>> map = list.stream()
    .map(array -> new AbstractMap.SimpleEntry<>(
            array[0], 
            Arrays.copyOfRange(array, 1, array.length)))
    .collect(Collectors.groupingBy(
            AbstractMap.SimpleEntry::getKey,
            Collectors.flatMapping(
                    i -> Arrays.stream(i.getValue()), 
                    Collectors.toList())));

다시 말하지만, SimpleEntry래퍼를 생략하면 전체 스트림을 단순화 할 수 있습니다 .

Map<Integer, List<Integer>> map = list.stream()
    .collect(Collectors.groupingBy(
            array -> array[0],
            Collectors.flatMapping(
                    array -> Arrays.stream(Arrays.copyOfRange(array, 1, array.length)),
                    Collectors.toList())));

결과적으로 빈 배열이 될 수있는 하위 배열을 가져옴 덕분에이 솔루션 은 배열에 요소가 하나 이상 있을 때도 작동합니다 Integer[]. new Integer[] {3}입력에 배열이 있는 결과는 다음과 같습니다.

{1=[23, 45], 2=[45, 54, 88], 3=[]}

3 JeroenSteenbeeke Nov 16 2020 at 18:20

Streams 사용 :

Map<Integer, List<Integer>> map =
        dataList.stream().collect(Collectors.toMap(i -> i[0], i -> List.of(i[1]), (a, b) -> {
            List<Integer> merged = new ArrayList<>(a);
            merged.addAll(b);
            return merged;
        }));

가독성을 위해 병합 작업을 별도의 방법으로 이동하는 것이 좋습니다. 동일한 결과 groupingBy를 얻을 수도 있지만 배열을 사용할 때 올바르게 가져 오기가 약간 까다 롭습니다.

3 Jabir Nov 16 2020 at 18:33

다음은 타사 API를 사용하지 않고 스트림을 사용하지 않는 솔루션입니다.

        Integer [] array1 = {1, 23};
        Integer [] array2 = {2, 45};
        Integer [] array3 = {3, 25};
        Integer [] array4 = {1, 45};
        Integer [] array5 = {2, 54};
        List<Integer[]> intlist = Arrays.asList( array1,array2,array3,array4,array5);
        
        Map<Integer, List<Integer>> grouped = intlist.stream()
                .collect(Collectors.groupingBy(arr -> arr[0], 
                         Collectors.mapping(arr -> arr[1], Collectors.toList())));
        
        System.out.println( grouped );

생산할 것이다

{1 = [23, 45], 2 = [45, 54], 3 = [25]}

필요에 따라.