背景
Java8使用Stream
編寫出來的代碼相當簡潔, 有時候需要使用distinct()
方法去重, 針對比較復雜的對象的時候, distinct()
就沒法工作了.
解決方案
定義一個輔助方法:
private static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
Set<Object> seen = ConcurrentHashMap.newKeySet();
return t -> seen.add(keyExtractor.apply(t));
}
然后通過如下調用:
list.stream().filter(distinctByKey(Book::getName)).forEach(System.out::println);
完整代碼如下
package com.github.stream;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
public class DistinctByProperty {
public static void main(String[] args) {
List<Book> list = new ArrayList<>();
list.add(new Book("Core Java", 200));
list.add(new Book("Core Java", 300));
list.add(new Book("Learning Freemarker", 150));
list.add(new Book("Spring MVC", 200));
list.add(new Book("Hibernate", 300));
list.stream().filter(distinctByKey(Book::getName)).forEach(System.out::println);
}
private static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
Set<Object> seen = ConcurrentHashMap.newKeySet();
return t -> seen.add(keyExtractor.apply(t));
}
static class Book {
private String name;
private int price;
public Book(String name, int price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public int getPrice() {
return price;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
}
}
執(zhí)行結果如下:
Book{name='Core Java', price=200}
Book{name='Learning Freemarker', price=150}
Book{name='Spring MVC', price=200}
Book{name='Hibernate', price=300}