java8 lambda表达式去重

在使用java8的stream流对List集合操作时,遇到了去重问题。原有的distinct()方法需要重写对象的equals()和hashCode()方法,比较麻烦,而且写在实体里比较难看。于是查阅资料,写了如下代码:

List<User> users = Lists.newArrayList(new User("aa",11),new User("bb",13),new User("aa",14) );
List<User> collect = users.stream().filter(distinctByKey(User::getName)).collect(Collectors.toList());
System.out.println(collect);

//去重函数
public <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
	Set<Object> set = ConcurrentHashMap.newKeySet();
	System.out.println("----------");
	return t -> set.add(keyExtractor.apply(t));
}
运行结果
----------
[User(name=aa, age=11), User(name=bb, age=13)]

巧妙的运用了set.add()方法返回boolean值来去重。根据这个思路我写了如下代码:
首先重写User类的equals()与hashCode()方法

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (!(o instanceof User)) {
            return false;
        }
        User user = (User) o;
        return Objects.equal(getName(), user.getName());
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(getName());
    }
        List<User> collect1 = users.stream().filter((user) -> {
                Set<User> set = ConcurrentHashMap.newKeySet();
                System.out.println("----------");
                return set.add(user);
            }).collect(Collectors.toList());
        System.out.println(collect1);
运行结果
----------
----------
----------
[User(name=aa, age=11), User(name=bb, age=13), User(name=aa, age=14)]

去重失败,结果打印了三次“-----”,说明new Set()被执行了三次,每次filter都new了一个Set。那为什么distinctByKey()方法中的 Set set = ConcurrentHashMap.newKeySet()只执行了一次呢?这里,我认为虽然distinctByKey()方法作为参数传递给了filter()方法,但distinctByKey()本身就是一个方法,在执行时也有自己的方法栈。filter()方法栈只是使用了distinctByKey()方法栈的boolean类型的返回值。每次filter(),将用user.getName()值传递进distinctByKey()方法栈,入栈计算后,将栈顶的boolean结果返回给filter()方法。因此,distinctByKey()方法栈只需在创建它自己的栈的时候执行一次 ConcurrentHashMap.newKeySet()操作。lambda表达式直接当做了filter()的变量进行入栈操作了,所以会执行多次。于是我改写了代码,将new Set()放在了lambda表达式外面。

        Set<User> set = ConcurrentHashMap.newKeySet();
        List<User> collect1 = users.stream().filter((user) -> {
                System.out.println("----------");
                return set.add(user);
            }).collect(Collectors.toList());
        System.out.println(collect1);
运行结果
----------
----------
----------
[User(name=aa, age=11), User(name=bb, age=13)]

在不重写User类的equals()与hashCode()方法时,这样写:

        Set<String> set = ConcurrentHashMap.newKeySet();
        List<User> collect1 = users.stream().filter((user) -> {
                System.out.println("----------");
                return set.add(user.getName());
            }).collect(Collectors.toList());
        System.out.println(collect1);
运行结果
----------
----------
----------
[User(name=aa, age=11), User(name=bb, age=13)]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章