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)]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章