Stream流根據屬性去重

zxxstar發表於2023-05-13

List根據屬性去重

建立一個user集合

 User user1 = new User("user1", 18, "AAA");
        User user2 = new User("user2", 18, "BBB");
        User user3 = new User("user3", 18, "AAA");
        User user4 = new User("user4", 75, "CCC");
        User user5 = new User("user5", 35, "AAA");

        ArrayList<User> list = new ArrayList<>();
        list.add(user1);
        list.add(user2);
        list.add(user3);
        list.add(user4);
        list.add(user5);

自定義Predict函式,使用filter()

寫一個Predict
public class DistinctKeyUtil {
    public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
        ConcurrentHashMap<Object, Boolean> map = new ConcurrentHashMap<>();
        return t -> map.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
    }
}
使用filter方法
/**
* 寫一個Predict進行屬性過濾
*/
//先過濾age在過濾hobby
List<User> result = list.stream()
.filter(DistinctKeyUtil.distinctByKey(n -> n.getAge()))
.filter(DistinctKeyUtil.distinctByKey(n -> n.getHobby()))
.collect(Collectors.toList());

result.forEach(System.out::println);
結果:
User{name='user1', age=18, hobby='AAA'}
User{name='user4', age=75, hobby='CCC'}
小結:

實質上是將每個元素都放到distinctByKey()中的ConcurrentHashMap作為key進行過濾,如果key不存在那麼就加上去,如果已經存在了就不加。所以這種方式的過濾只保留第一個重複元素。

利用TreeSet

        //過濾age
        ArrayList<User> result2 = list.stream().collect(
                Collectors.collectingAndThen(
                        Collectors.toCollection(
                                () -> new TreeSet<>(Comparator.comparing(o -> o.getAge()))), ArrayList::new));
								
        result2.forEach(System.out::println);

結果與上面的一樣

同時過濾兩個屬性

        //age和hobby一起過濾
        ArrayList<User> result1 = list.stream().collect(
                Collectors.collectingAndThen(
                        Collectors.toCollection(
                                () -> new TreeSet<>(Comparator.comparing(o -> o.getHobby() + ";" + o.getAge()))), ArrayList::new)
        );
        result1.forEach(System.out::println);
結果:
User{name='user1', age=18, hobby='AAA'}
User{name='user5', age=35, hobby='AAA'}
User{name='user2', age=18, hobby='BBB'}
User{name='user4', age=75, hobby='CCC'}
小結:

TreeSet儲存唯一的元素,並且按升序對元素進行排序。

Map:保證Key的唯一性

        /**
         * map 根據某屬性過濾
         */
        //  Function.identity() 相等於  o->o
        Map<String, User> map1 = list.stream().collect(Collectors.toMap(User::getHobby, Function.identity(), (t1, t2) -> t1));
        Set<Map.Entry<String, User>> entries1 = map1.entrySet();
        entries1.forEach(System.out::println);
結果:
AAA=User{name='user1', age=18, hobby='AAA'}
CCC=User{name='user4', age=75, hobby='CCC'}
BBB=User{name='user2', age=18, hobby='BBB'}
小結:

map可以選擇保留重複屬性中的前一條資料還是後一條:(t1, t2) -> t1)

相關文章