栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

Java Lambda流Distinct()在任意键上?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java Lambda流Distinct()在任意键上?

该distinct操作是有状态的管道操作;在这种情况下,它是一个有状态过滤器。自己创建它们有点不方便,因为没有内置的东西,但是一个小助手类应该可以解决问题:

static class DistinctByKey<T,K> {    Map<K,Boolean> seen = new ConcurrentHashMap<>();    Function<T,K> keyExtractor;    public DistinctByKey(Function<T,K> ke) {        this.keyExtractor = ke;    }    public boolean filter(T t) {        return seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;    }}

我不知道你的域类,但是我认为,有了这个帮助器类,你可以像这样做:

BigDecimal totalShare = orders.stream()    .filter(new DistinctByKey<Order,CompanyId>(o -> o.getCompany().getId())::filter)    .map(Order::getShare)    .reduce(BigDecimal.ZERO, BigDecimal::add);

不幸的是,类型推断无法在表达式中得到足够的支持,因此我必须为DistinctByKey类明确指定类型参数。

这比Louis Wasserman所描述的收集器方法涉及更多的设置,但这具有以下优点:不同的项目会立即通过而不是被缓冲直到收集完成。空间应该是相同的,因为(不可避免地)两种方法最终都会累积从流元素中提取的所有不同密钥。

更新

可以摆脱K类型参数,因为除了存储在地图中之外,它实际上没有用于其他任何用途。这样Object就足够了。

static class DistinctByKey<T> {    Map<Object,Boolean> seen = new ConcurrentHashMap<>();    Function<T,Object> keyExtractor;    public DistinctByKey(Function<T,Object> ke) {        this.keyExtractor = ke;    }    public boolean filter(T t) {        return seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;    }}BigDecimal totalShare = orders.stream()    .filter(new DistinctByKey<Order>(o -> o.getCompany().getId())::filter)    .map(Order::getShare)    .reduce(BigDecimal.ZERO, BigDecimal::add);

这简化了一些事情,但是我仍然必须为构造函数指定type参数。尝试使用菱形或静态工厂方法似乎并没有改善。我认为困难在于,编译器无法在方法引用的实例表达式中推断出泛型类型参数(用于构造函数或静态方法调用)。那好吧。

(与此有关的另一种变体可能会简化

DistinctByKey<T> implements Predicate<T>
该方法,并将其重命名为eval。这将消除使用方法引用的需要,并可能会改善类型推断。但是,它不太可能像下面的解决方案一样好。)

更新2

不能停止思考。代替帮助器类,使用高阶函数。我们可以使用捕获的本地人来维护状态,因此我们甚至不需要单独的类!奖金,事情简化了,所以类型推断起作用了!

public static <T> Predicate<T> distinctByKey(Function<? super T,Object> keyExtractor) {    Map<Object,Boolean> seen = new ConcurrentHashMap<>();    return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;}BigDecimal totalShare = orders.stream()    .filter(distinctByKey(o -> o.getCompany().getId()))    .map(Order::getShare)    .reduce(BigDecimal.ZERO, BigDecimal::add);


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/456631.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号