2016-06-08 39 views
-2

我正試圖使用​​流和lambdas將多個集合減少爲單個集合。不過,我需要指出發生重複點擊的位置。如何將多個列表與流和lambas結合,指示哪裏有重複

基本上我有以下情況:客戶的

系列1(人人)員工的前景

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

系列2

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可以在同一類別鍵兩次被發現,願與您獨特的類別爲每個Person,你可以收集各組一個Set使族元素獨特的,然後轉換SetStringCollectors.collectingAndThen這樣的:

 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))))); 

通過以下設置,

 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)); 

我得到{Person1=Customer,Prospect, Person2=Employee,Customer}

+0

感謝您的提示 - 不幸的是,這兩個給我一個編譯錯誤在收集「推理變量K有不兼容的界限」,這一「收集(收藏家」?超T,A,R>)的類型是錯誤的「 –

+0

謝謝,@purringpigeon,我的地圖類型錯誤。我更正了我的答案 –

+0

這很奇怪 - 當我運行第一個例子時,我得到了相同的結果...收集器反覆連接了同一個字符串... Joe「Customer,Customer,Customer」,而不是我所期待的喬,「客戶,展望,員工」。第二個例子將字符串摺疊爲只是說「客戶」。 –

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)); 

請注意,對類是從javafx.util.Pair使用。

+0

其實這沒有奏效。它幾乎奏效。例如,我得到了以下結果:Joe,「客戶,客戶,客戶」。我沒有在地圖上得到正確的值。 –

+0

那麼,你的代碼是不正確的。您正在創建3個集合,p1,p2,p3。但總是將元素添加到p1中。嘗試糾正它,你會得到正確的輸出。 – mks

+0

是的 - 我看到在另一個帖子上 - 整天追逐這個問題。謝謝。 –

相關問題