Java에서 중복 키가있는 목록 그룹화 및 생성 [duplicate]
변환하려고 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]))));
}
답변
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=[]}
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
를 얻을 수도 있지만 배열을 사용할 때 올바르게 가져 오기가 약간 까다 롭습니다.
다음은 타사 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]}
필요에 따라.