这个java流代码[distinctByKey]是如何执行的,它是无状态的吗?

xvw2m8pv  于 2023-01-11  发布在  Java
关注(0)|答案(1)|浏览(200)

我想通过主键区分一个列表,为什么Set<Object> seen = ConcurrentHashMap.newKeySet();只执行一次,而seen.add(keyExtractor.apply(t));对列表中的每个元素都执行?
方法distinctByKey是无状态的吗?

public static void main(String[] args) {
    List<UserInfo> list = new ArrayList<>();
    list.add(new UserInfo(1, "a"));
    list.add(new UserInfo(2, "b"));
    list.add(new UserInfo(2, "c"));
    List<UserInfo> result = list.stream()
            .filter(distinctByKey(userInfo -> userInfo.id))
            .collect(Collectors.toList());
    System.out.println(result);
}

private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
    Set<Object> seen = ConcurrentHashMap.newKeySet();
    return (t) -> {
        return seen.add(keyExtractor.apply(t));
    };
}
weylhg0b

weylhg0b1#

如果你想通过键区分,你可以使用 Package 器。Java流API不提供通过自定义规则区分的方法,它依赖于类的equals()和hashCode()方法。
如果我们想使用自定义区分,那么我们可以创建 Package 器类,在那里我们可以覆盖给定的方法:

public class Sample {

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    private static class UserInfo {
        private int id;
        private String name;
    }

    @AllArgsConstructor
    private static class UserInfoWrapper {
        private UserInfo userInfo;

        public static UserInfoWrapper wrap(UserInfo userInfo) {
            return new UserInfoWrapper(userInfo);
        }

        public UserInfo unwrap() {
            return userInfo;
        }

        @Override
        public boolean equals(final Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            final UserInfoWrapper that = (UserInfoWrapper) o;
            return Objects.equals(userInfo.id, that.userInfo.id);
        }

        @Override
        public int hashCode() {
            return Objects.hash(userInfo.id);
        }
    }

    public static void main(String[] args) {

        List<UserInfo> list = new ArrayList<>();
        list.add(new UserInfo(1, "a"));
        list.add(new UserInfo(2, "b"));
        list.add(new UserInfo(2, "c"));
        List<UserInfo> result = list.stream()
                .map(UserInfoWrapper::wrap)
                .distinct()
                .map(UserInfoWrapper::unwrap)
                .collect(Collectors.toList());
        System.out.println(result);

    }
}

输出:

[Sample.UserInfo(id=1, name=a), Sample.UserInfo(id=2, name=b)]

而且它肯定会是纯粹的无状态解决方案。

相关问题