2016-07-20 2 views
4

String을 키로하고 List를 값으로 매핑했습니다. 목록은 10 개의 고유 한 값을 가질 수 있습니다. 이지도를 정수로 키를 사용하여 List로 변환해야합니다. 아래 예 :Java8 스트림 : 목록을 값으로 매핑 바꾸기

입력 :

"버튼 1"1,2,3,4-

"키 -2-"2,3,4,5

"키 3"3,4,5,1

예상 출력 :

1 : "키-1", "키 3"

2 "키-1 ','키 - 2"

3 "키-1", "키-2", "키 -3-"

4 "키 1" "키 2", "키 3"

5 : "키 2", "키 3"

나는 루프를 사용하는 것은 내가이를 수 있다는 것을 알고하지만 난 캔을 알 필요가 이 작업은 java8의 streams/lamda를 통해 수행됩니다.

- 고맙습니다.

답변

2

그것은 무서운 조금 (나는 일반적으로 더 읽을 수 있도록 그것을 무너 뜨리는 시도)하지만 당신은 이런 식으로 할 수있다 :

Map<Integer, List<String>> transposeMap = new HashMap<>(); 

map.forEach((key, list) -> list.stream().forEach(
    elm -> transposeMap.put(elm, 
     transposeMap.get(elm) == null ? Arrays.asList(key) : (Stream.concat(transposeMap.get(elm).stream(), 
      Arrays.asList(key).stream()).collect(Collectors.toList()))))); 

Map<String, List<Integer>> map를 가정하면 트랜스하려는 원래의지도입니다. transposeMap에는 필요한 전치 된지도가 있습니다.

+1

스트림이 더 적합을 얻을 것이다

Map<SEX,List<Person>> 

내가 쓰는 것이 양식을 얻으려면 상태 비 저장 작업이 대답은 정확하지만 명령형에 더 적합합니다. 기본적으로 OP의 루프 전략이지만 대신 스트림의 forEach로 레이블을 다시 지정합니다. – 4castle

+1

forEach는'stream's에 속하지 않습니다. 그것은'Iterable','list.stream()에 선언되어 있습니다. forEach'는'list.forEach'이어야합니다. –

+1

@ Jean-François Savard : 스트림에는 약간 다른 의미가 있지만 'forEach' 메소드도 있습니다. – Holger

11

아이디어는이 값에 의해 원래지도의 모든 가치 키 쌍과 다음 그룹 키를 생성 할 수 :

import java.util.AbstractMap.SimpleEntry; 

import static java.util.stream.Collectors.groupingBy; 
import static java.util.stream.Collectors.mapping; 
import static java.util.stream.Collectors.toList; 

... 

Map<Integer, List<String>> transposeMap = 
    map.entrySet() 
     .stream() 
     .flatMap(e -> e.getValue().stream().map(i -> new SimpleEntry<>(i, e.getKey()))) 
     .collect(groupingBy(Map.Entry::getKey, mapping(Map.Entry::getValue, toList()))); 
4

Alexis’ answerflatMap과를 사용하여, 작업의 종류에 대한 일반적인 솔루션을 포함 키와 평평한 값의 조합을위한 임시 홀더.

Map<Integer, List<String>> mapT = map.entrySet().stream().collect(
    HashMap::new, 
    (m,e) -> e.getValue().forEach(
       i -> m.computeIfAbsent(i,x -> new ArrayList<>()).add(e.getKey())), 
    (m1,m2) -> m2.forEach((k,v) -> m1.merge(k, v, (l1,l2)->{l1.addAll(l2); return l1;}))); 
1

당신은 달성 할 수 임시 홀더 객체의 생성을 피할 수있는 유일한 대안은 groupingBy 콜렉터의 논리를 다시 구현 및 누적 기 함수로 값리스트 위에 로직을 루프를 삽입하는 것이다 이쪽으로

성별 및 나이를 가진 Person 클래스가 있다고 가정 해 보겠습니다. 나는 단순히

Map<SEX,List<Person>> map = personList.stream() 

          .collect(Collectors.groupingBy(Person::getGender)); 

이 나에게 다음과 같은 것을 (여러 값에 대한 하나의 키)

key:MALE 
age31sexMALE 
age28sexMALE 

key:FEMALE 
age40sexFEMALE 
age44sexFEMALE