2016-12-22 1 views
0

나는 <String, List<T>>의 맵을 가지며 각 항목의 값에 대한 스트림을 작성하고자하는데 최대 요소는 List<T>이고 해당 맵 다음에 찾을 수 있습니다. <String, List<T>> ~ <String, T>. 어떻게해야합니까? 알아 내려고하는 데 3 시간 이상을 소비했습니다. Collector.toMap와 그것없이 내가없는 방식에 대해 가장 궁금 :값으로 목록을 포함하는 맵 항목의 각 키에 대한 스트림

업데이트 내가 그것을 두 가지 방법을하라는 것을 알려 잊으.

내가 붙어있어 단계는 다음과 같습니다

employees.stream() 
      .flatMap(e -> e.getJobHistory().stream() 
        .map(j -> new PersonPositionDuration(e.getPerson(), j.getPosition(), j.getDuration()))) 
      .collect(Collectors.groupingBy(p -> p.getPosition())) 
      .entrySet(). 

employeesEmployee 객체의 목록이며, 각각뿐만 아니라 List입니다 jobHistory 속성을 가지고 있으며 각 항목은 employer 속성이 있습니다 String. 그래서 List<Employee>Map<String, List<PersonPositionDuration>>으로 바꿉니다. 여기에서 key는 emploer이고 value는 클래스에 대한 정보이며 사람에 대한 정보와이 emploer의 직원으로 일한 기간을 포함합니다. 키는 고유하지 않습니다.

내가 원하는 것은 가장 긴 지속 시간 인 PersonPositionDuration을 찾으려면 getDuration()으로 가져올 수 있습니다. 내가 진입하고 진입 후 어떻게해야 하나?

또한 Collectors.maxByCollectors.collectingAndThen을 사용하는 것이 좋습니다.하지만 어떻게해야할지 모르겠습니다. 당신이 이와 같은 방법으로 코드를 포장 할 수 있습니다 (두 값의 최대 값을 산출 할 수 있어야하기 때문에) T 구현을 Comparable 가정

+3

이미 시도한 작업을 보여주십시오. – mangotang

답변

3

는 :

public <T extends Comparable<T>> Map<String, T> convert(Map<String, List<T>> data) { 
    // variable for readability, you can return it right away if you prefer 
    Map<String, T> result = data.entrySet().stream().collect(Collectors.toMap(
      // for each key in our map... 
      e -> e.getKey(), 
      // ... we determine the maximum and store it as new value 
      e -> Collections.max(e.getValue()) 
    )); 

    return result; 
} 

그것은 Set<Map.Entry<String, List<T>>> 생성하는 당신이 할 수의 Comparable.compareTo을 사용하는 값 ​​유형을 Collections.max()으로 변환하여 두 개의 오브젝트를 비교하고 둘 중 어느 것이 더 큰지를 판별하여 Map<String, T>으로 변환 된 Stream을 작성하십시오. Integer 또는 Double (및 그 이상)과 같은 박스형의 경우 그대로 사용하면됩니다. 모두 Comparable을 구현합니다. 당신의 map 유형 <String, List<Integer>>의 경우

+0

'toMap'없이는 어떻게 할 수 있습니까? –

+3

@LeonidBor 여기에 맵핑을 사용하는 것이 잘못된 이유는 무엇입니까? –

+0

@TagirValeev 선생님이지도 작성 여부와 상관없이 양방향으로 작업하도록 요청했습니다. 나는 함께 시험해 보았고 위대한 작품이다. 도움을 주셔서 감사합니다. 그러나 두 번째 방법은 여전히 ​​나에게 불분명하다. –

2

은이

Map<String, List<Integer>> map = new HashMap<>(); 
map.put("a", Arrays.asList(5, 3, 7)); 
map.put("b", Arrays.asList(1, 5)); 
map.put("c", Arrays.asList(45, 2)); 
map.put("d", Arrays.asList(4, 6, 2, 34)); 

map.entrySet().stream().collect(Collectors.toMap(Entry::getKey, entry -> { 
    return entry.getValue().stream().max(Integer::compareTo).orElse(0); 
})); 

출력으로 수행 할 수 있습니다

{a=7, b=5, c=45, d=34} 

당신은 유형 T 또는 클래스 유형에 대한 비교와 entry.getValue().stream().max(Integer::compareTo).orElse(0)을 수정할 수 있습니다.

0

달성하고자하는 것이나 데이터 구조가 어떻게 보이는지 분명하지 않습니다. 당신이 작성한 코드와 보여준 코드가 일치하지 않습니다. 그들은 매우 다른 것들을 성취합니다.

그러나 Collectors.maxBy을 사용하고 Collectors.toMap을 사용하지 않고 해결책을 원했습니다. 다른 대답은 그런 해결책을 제공하지 못했습니다. 그러므로 나는 하나를 주려고 노력할 것이다.


귀하의 데이터 : 데이터 구조로

난 당신이 각각 다수의 직원을 고용 고용주가 가정합니다. 모든 직원은 몇 가지 개인 정보, 그가 근무하는 위치 및 그가 알 수있을 때까지이 직위에서 근무한 기간을가집니다.

예 (지도 employerEmployeeMap)의 경우 :

CompanyA: [{Max, Developer, 5.4}, {Mari, Designer, 6.8}, {Paul, Manager, 1.2}] 
CompanyB: [{Lea, CEO, 7.1}, {Tom, Admin, 4.5}, {Ria, Marketing, 0.4}] 
CompanyC: [{Alex, Secretary, 1.5}, {Lisa, Developer, 3.3}, {Mia, Developer, 2.7}] 
당신이 무엇을 달성하고자하는

:

당신은 시간이 가장 긴 PersonPositionDuration을 갖고 싶어. 모든 고용주 또는 각 고용주에 대해 가장 긴 기간을 가진 사람 만 원하면 확실하지 않았습니다. 따라서 여러 솔루션을 제공 할 것입니다. maxBy와


솔루션

당신은 당신이 바로 직원 반복 가장 높은 기간과 하나 얻을 수있는 모든 고용주를 통해 시간이 가장 긴 사람하려면 다음

Optional<PersonPositionDuration> maxDurationPerson = employerEmployeeMap.values().stream() 
       .flatMap(List::stream) 
       .collect(maxBy(comparing(PersonPositionDuration::getDuration))); 

이것은 다음과 같습니다.

Optional<PersonPositionDuration> maxDurationPerson = employerEmployeeMap.values().stream() 
       .flatMap(List::stream) 
       .max(comparing(PersonPositionDuration::getDuration)); 
01 23,414,결과 : {Lea, CEO, 7.1}

당신이 가장 높은 기간 만 사람을 원하지만 고용주 정보를 잃고 싶지 않는 경우 :

Optional<Pair<String, PersonPositionDuration>> maxDurationPersonCompany = employerEmployeeMap.entrySet().stream() 
       .flatMap(entry -> entry.getValue().stream().map(p -> new Pair<>(entry.getKey(), p))) 
       .max(comparing(entry -> entry.getValue().getDuration())); 

결과 : CompanyB: {Lea, CEO, 7.1}

당신은 가장 높은 가진 사람을 원하는 경우

Map<String, Optional<Pair<String, PersonPositionDuration>>> maxDurationPerCompany = employerEmployeeMap.entrySet().stream() 
       .flatMap(entry -> entry.getValue().stream().map(p -> new Pair<>(entry.getKey(), p))) 
       .collect(groupingBy(Pair::getKey, maxBy(comparing(entry -> entry.getValue().getDuration())))); 

결과 :다음 작업을 수행 할 수있는 모든 회사의 지속 시간

CompanyA: {Mari, Designer, 6.8} 
CompanyB: {Lea, CEO, 7.1} 
Companyc: {Lisa, Developer, 3.3} 

귀하의 질문과 필요 사항이 모두 포함되기를 바랍니다. 그렇지 않은 경우, 누락 된 것이 있거나 불분명 한 것이있는 경우 언제든지 의견을 말하십시오.


전체 작업 예 :

import javafx.util.*; 

import java.util.*; 

import static java.util.Comparator.comparing; 
import static java.util.stream.Collectors.*; 

public class Main { 

    public static void main(String[] args) { 
     class PersonPositionDuration { 
      private final String person; 
      private final String position; 
      private final Double duration; 

      public PersonPositionDuration(String person, String position, Double duration) { 
       this.person = person; 
       this.position = position; 
       this.duration = duration; 
      } 

      public Double getDuration() { 
       return duration; 
      } 
     } 

     Map<String, List<PersonPositionDuration>> employerEmployeeMap = new HashMap<>(); 
     employerEmployeeMap.put("CompanyA", Arrays.asList(new PersonPositionDuration("Max", "Developer", 5.4), new PersonPositionDuration("Mari", "Designer", 6.8), new PersonPositionDuration("Paul", "Manager", 1.2))); 
     employerEmployeeMap.put("CompanyB", Arrays.asList(new PersonPositionDuration("Lea", "CEO", 7.1), new PersonPositionDuration("Tom", "Admin", 4.5), new PersonPositionDuration("Ria", "Marketing", 0.4))); 
     employerEmployeeMap.put("CompanyC", Arrays.asList(new PersonPositionDuration("Alex", "Secretary", 1.5), new PersonPositionDuration("Lisa", "Developer", 3.3), new PersonPositionDuration("Mia", "Developer", 2.7))); 

     Optional<PersonPositionDuration> maxDurationPerson = employerEmployeeMap.values() 
       .stream() 
       .flatMap(List::stream) 
       .max(comparing(PersonPositionDuration::getDuration)); 

     Optional<Pair<String, PersonPositionDuration>> maxDurationPersonCompany = employerEmployeeMap.entrySet() 
       .stream() 
       .flatMap(entry -> entry.getValue() 
         .stream() 
         .map(p -> new Pair<>(entry.getKey(), p))) 
       .max(comparing(entry -> entry.getValue() 
         .getDuration())); 

     Map<String, Optional<Pair<String, PersonPositionDuration>>> maxDurationPerCompany = employerEmployeeMap.entrySet() 
       .stream() 
       .flatMap(entry -> entry.getValue() 
         .stream() 
         .map(p -> new Pair<>(entry.getKey(), p))) 
       .collect(groupingBy(Pair::getKey, maxBy(comparing(entry -> entry.getValue() 
         .getDuration())))); 
    } 
} 
관련 문제