背景
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 +
'}';
}
}
}
执行结果如下:
Book{name='Core Java', price=200}
Book{name='Learning Freemarker', price=150}
Book{name='Spring MVC', price=200}
Book{name='Hibernate', price=300}
网友评论