2017-02-28 28 views
0

我有一個用戶列表。Java:如何使用Stream API按條件對實體進行分組?

class User { 
    String name; 
} 

而且我需要按名稱對用戶進行分組。

List<Set<User>> groupedBy; 

的分組條件是名稱相似,它的一些比較

Comparator<User> p = new Comparator<User>() { 
    // some comparison logic 
}; 

通過類似的名字,我組的用戶如何使用Java 8流?

我試着使用partitioning,但它有一個不同的API比我更需要。

Map<Boolean, List<User>> collected = users.stream().collect(Collectors.partitioningBy(new Predicate<User>() { 
    @Override 
    public boolean test(User user) { 
     // ... 
    } 
}, Collectors.toList())); 
+0

你基於謂詞試圖'group'?聽起來像'分區'。 – Eugene

+0

對不起,基於名稱比較。 – Finkelson

+0

如果沒有流API,你會怎麼做?考慮到像萊文斯坦距離這樣的事情,它不會導致一個明確分離的集合,因爲它不是傳遞的。 –

回答

2

通常情況下,如果你通過一個簡單的屬性要組,你會使用

Map<String,Set<User>> m=users.stream() 
    .collect(Collectors.groupingBy(User::getName, Collectors.toSet())); 

但是,如果你有一個表示爲一個已經存在的Comparator,例如一個複雜的邏輯

Comparator<User> comparator=Comparator.comparing(u -> u.getName(), Collator.getInstance()); 

可以根據封裝在比較器邏輯使用

Map<User,Set<User>> m=users.stream().collect(
    Collectors.groupingBy(u -> u,() -> new TreeMap<>(comparator), Collectors.toSet())); 

到組。

在這兩種情況下,你會得到一個Map可以轉換到使用

List<Set<User>> groupedBy = new ArrayList<>(m.values()); 

你想要的清單還可以表示最後一步爲Collector的一部分,例如

List<Set<User>> groupedBy=users.stream().collect(
    Collectors.collectingAndThen(
     Collectors.groupingBy(u -> u,() -> new TreeMap<>(comparator), Collectors.toSet()), 
     m -> new ArrayList<Set<User>>(m.values()))); 
+0

是...爲什麼不只是將比較器提供給接受一個的地圖?一加 – Eugene

相關問題