2016-06-08 3 views
-2

스트림 및 람다를 사용하여 여러 컬렉션을 단일 컬렉션으로 축소하려고합니다. 그러나 중복 된 히트가 발생한 곳이면 어디든 나타낼 필요가 있습니다. 기본적으로여러 개의 목록을 스트림 및 lambas와 결합하여 중복 위치를 나타내는 방법

나는 다음과 같은 상황이 : 고객의

컬렉션 1 (모든 사람) 종업원의 전망

Person 1 (Tom) 
Person 2 (Bob) 
Person 3 (Joe) 

컬렉션이

Person 1 (Mike) 
Person 2 (Wilbur) 
Person 3 (Joe) 

컬렉션 3

Person 1 (Mike) 
Person 2 (Tony) 
Person 3 (Sue) 
Person 4 (Joe) 

나는지도를 사용 할 수있는 새로운 분야 포함하는 컬렉션을 변환하고 싶습니다 - 최종 결과이

컬렉션 같은 것 있도록 평평하게하는 방법을 실제로 내가 잃어버린 얻고됩니다

Person 1 (Tom, "Customer") 
Person 2 (Bob, "Customer") 
Person 3 (Joe, "Customer, Prospect, Employee") 
Person 4 (Mike, "Prospect, Employee") 
Person 5 (Wilbur, "Prospect") 
Person 6 (Tony, "Employee") 
Person 7 (Sue, "Employee") 

나는 속한 영역을 시각적으로 나타 내기 위해 문자열 값을 만들 계획입니다.

고마워요!

[편집] 아래의 제안을 바탕으로

, 내가 솔루션이 방법을 테스트 할 수 있었다 ...

클래스 TestOutFlatMap { 공공 무효 시험() {

Map<String, Collection<Person>> map = new HashMap<>(); 

    Collection<Person> p1 = new ArrayList<>(); 
    p1.add(new Person("Mike")); 
    p1.add(new Person("Joe")); 
    p1.add(new Person("Tony")); 

    Collection<Person> p2 = new ArrayList<>(); 
    p1.add(new Person("Wilbur")); 
    p1.add(new Person("Joe")); 
    p1.add(new Person("Molly")); 

    Collection<Person> p3 = new ArrayList<>(); 
    p1.add(new Person("Wilbur")); 
    p1.add(new Person("Joe")); 
    p1.add(new Person("Bubba")); 

    map.put("Customer", p1); 
    map.put("Prospect", p2); 
    map.put("Employee", p3); 

    Map<Person, String> output = map 
     .entrySet() 
     .stream() 
     .flatMap(t -> t.getValue().stream().map(g -> new Pair<>(t.getKey(), g))) 
     .collect(Collectors.toMap(t -> t.getValue(), u -> u.getKey(), (x, y) -> x + ", " + y)); 

    output.keySet().stream().forEach(p -> { 
     System.out.println(p); 
     System.out.println(output.get(p)); 
    }); 

} 
class Person { 
    String name; 

    Person(String name){ 
     this.name = name; 
    } 

    public String toString() {return this.name;} 

@Override 
public int hashCode() { 
    int hash = 5; 
    return hash; 
} 

@Override 
public boolean equals(Object obj) { 
    if (this == obj) { 
     return true; 
    } 
    if (obj == null) { 
     return false; 
    } 
    if (getClass() != obj.getClass()) { 
     return false; 
    } 
    final Person other = (Person) obj; 
    if (!Objects.equals(this.name, other.name)) { 
     return false; 
    } 
    return true; 
} 

}; 

} 

그러나 내 결과는 기대와 달랐습니다. 그들은 다음과 같이 반환했습니다 :

Bubba 
Customer 
Molly 
Customer 
Wilbur Customer, Customer 
Tony Customer 
Joe Customer, Customer, Customer 
Mike Customer 

잘못 연결된 부분이 표시되지 않습니다.

답변

1

는이 같은 문자열로 그룹을 변환하는 다운 스트림 수집기, 그룹화를 시도 할 수 있습니다 :

 Map<Person, String> result = map 
     .entrySet() 
     .stream() 
     .flatMap(e -> e.getValue().stream().map(v -> new AbstractMap.SimpleEntry<>(v,e.getKey()))) 
     .collect(
      Collectors.groupingBy(Map.Entry::getKey,   // group Map.Entry by key 
       Collectors.mapping(Map.Entry::getValue,  // for each group, convert Map.Entry into the value 
        Collectors.joining(","))));    // convert the values into a comma-delimited String 

를이 같은 Person가 두 번 같은 범주 키 아래에 볼 수 있습니다 어떻게 든 가능하다면,

 Map<Person, String> result = map 
     .entrySet() 
     .stream() 
     .flatMap(e -> e.getValue().stream().map(v -> new AbstractMap.SimpleEntry<>(v,e.getKey()))) 
     .collect(Collectors.groupingBy(
       Map.Entry::getKey, 
       Collectors.mapping(Map.Entry::getValue, 
         Collectors.collectingAndThen(
           Collectors.toSet(), x -> String.join(",",x))))); 
: 당신은이 같은 Collectors.collectingAndThenStringSet를 변환 한 후 그룹 요소를 고유하게 만들기 위해 Set 각 그룹을 수집하고, 수, 각 Person에 대해 고유 한 범주를 싶습니다 다음과 같은 설정으로

,

 Map<String, Collection<Person>> map = new HashMap<>(); 
     Person person1 = new Person("Person1"); 
     Person person2 = new Person("Person2"); 
     map.put("Customer", Arrays.asList(person1, person2)); 
     map.put("Prospect", Arrays.asList(person1)); 
     map.put("Employee", Arrays.asList(person2, person2)); 

나는 사실이 작동하지 않았다

+0

팁 주셔서 감사합니다 - 불행히도 둘 다 나에게 "추론 변수 K가 호환되지 않는 경계를 가지고 있습니다"그리고이 하나의 유형 " (Collector )의 유형은 errorneous입니다"컴파일시 오류가 발생했습니다. –

+0

, @purringpigeon, 나는'map'에 대해 잘못된 유형을 가졌습니다. 내 대답을 수정했습니다 –

+0

이것은 이상한 일입니다 - 첫 번째 예제를 실행하면 동일한 결과를 얻습니다 ... 콜렉터는 동일한 문자열을 반복해서 반복합니다 ... Joe "Customer, Customer, Customer" Joe, "고객, 잠재 고객, 직원". 두 번째 예제는 "고객"이라고 말하기 위해 문자열을 접습니다. –

1

다른 유형의 컬렉션이 여러 개 있으므로 각 컬렉션에 대한 식별자가 있어야합니다. 컬렉션의지도로 입력을 표현하는 가장 좋은 방법입니다.지도의 핵심은 고객, 잠재 고객 및 직원과 같은 컬렉션 유형을 나타냅니다.

이제 Map<String, Collection<Person>>,이 있으면 콜렉션의 각 요소별로 그룹화하고 연결된 키를 추적해야합니다. 이를 위해서는 flatmap을 사용해야합니다. 다음 코드는 작동합니다 :

Map<String, Collection<Person>> map = new HashMap<>(); 
    map.put("Customer", ...); 
    map.put("Prospect", ...; 
    map.put("Employee", ...; 

    Map<Person, String> output = map 
     .entrySet() 
     .stream() 
     .flatMap(t -> t.getValue().stream().map(g -> new Pair<>(t.getKey(), g))) 
     .collect(Collectors.toMap(
       t -> t.getValue(), u -> u.getKey(), (x, y) -> x + ", " + y)); 

페어 (Pair) 클래스가 javafx.util.Pair에서 사용됩니다 유의하시기 바랍니다.

+0

{Person1=Customer,Prospect, Person2=Employee,Customer}를 얻을. 거의 효과가있었습니다. 예를 들어 Joe, "Customer, Customer, Customer"와 같은 결과가 있습니다. 키에 대한 맵에서 올바른 값을 얻었습니다. –

+0

코드가 잘못되었습니다. 당신은 3 개의 콜렉션 인 p1, p2, p3를 생성하고 있습니다. 그러나 항상 요소를 p1에 추가합니다. 그것을 바로 잡으십시오. 그러면 올바른 결과를 얻을 수 있습니다. – mks

+0

그래, 나는 다른 포스트에서 그 문제를 하루 종일 쫓아 냈다. 감사. –