回顾Java 8stream
API设计时,我对stream.reduce()
参数的泛型不变性感到惊讶:
<U> U reduce(U identity,
BiFunction<U,? super T,U> accumulator,
BinaryOperator<U> combiner)
同一个API的一个看起来更通用的版本可能已经在对u
的单独引用上应用了协方差/逆方差,例如:
<U> U reduce(U identity,
BiFunction<? super U, ? super T, ? extends U> accumulator,
BiFunction<? super U, ? super U, ? extends U> combiner)
这将允许当前不可能的以下操作:
// Assuming we want to reuse these tools all over the place:
BiFunction<Number, Number, Double> numberAdder =
(t, u) -> t.doubleValue() + u.doubleValue();
// This currently doesn't work, but would work with the suggestion
Stream<Number> stream = Stream.of(1, 2L, 3.0);
double sum = stream.reduce(0.0, numberAdder, numberAdder);
解决办法是使用方法引用将类型“强制”为目标类型:
double sum = stream.reduce(0.0, numberAdder::apply, numberAdder::apply);
C#没有这个特殊的问题,因为func(T1,T2,TResult)
定义如下,使用声明-站点方差,这意味着任何使用func
的API都可以免费获得这个行为:
public delegate TResult Func<in T1, in T2, out TResult>(
T1 arg1,
T2 arg2
)
与建议的设计相比,现有的设计有什么优势(以及可能的,决策的原因)?
或者,不同的问题是,我可能会忽略的建议设计的注意事项是什么(例如,类型推断困难、并行化约束,或者特定于约简操作的约束,例如,关联性、对双函数
的未来Java声明站点差异的预期,...)?
在lambda开发的历史中爬行并分离出这个决定的“”原因是很困难的--所以最终,我们将不得不等待其中一个开发人员回答这个问题。
一些提示可能如下:
>
流接口经历了几次迭代和重构。在stream
接口的最早版本之一中,有专门的reduce
方法,而与问题中的reduce
方法最接近的那个方法当时仍称为stream#fold
。这一个已接收到BinaryOperator
作为Combiner
参数。
有趣的是,有一段时间,lambda建议包含了一个专用接口组合器
。与直觉相反的是,它没有用作流#reduce
函数中的组合器
。相反,它被用作reducer
,这似乎就是现在所说的accumulator
。但是,在后来的版本中,组合器
接口被双功能
所取代。
与这里的问题最惊人的相似点是在邮件列表中关于stream#flatmap
签名的一个线程中发现的,然后这个线程就变成了关于stream方法签名的变化的一般问题。他们把这些固定在一些地方,例如
正如Brian纠正我:
而不是:
而且
可选
因为他们使用了“binaryoperator”,所以无法修复,但是如果使用了“bifunction”,那么我们就有了更多的灵活性
而不是:
U reduce(U恒等式,bifunction
累加器,binaryoperator
组合器);
关于“BinaryOperator”的相同注释
问题内容: 回顾Java 8 API设计,我对参数的通用不变性感到惊讶: 同一API的看似更通用的版本可能对的单个引用应用了协方差/协方差,例如: 目前,这将允许以下操作(不可能): 解决方法,使用方法引用将类型“强制”为目标类型: C#没有使用声明位置方差定义如下的特定问题,这意味着使用此方法的任何API 都可以免费获得此行为: 与建议的设计相比,现有设计有哪些优势(可能还有进行EG决策的原因)
我想知道为什么不使用这个明显简洁的表达呢?
问题内容: 我需要在循环中对数据库进行SQL查询: 更好的方法是:保持原样或循环后移动: 或者是其他东西 ? 问题答案: 整个要点是直到函数返回才执行,因此将其放置在要关闭的资源打开后的适当位置。但是,由于要在循环内创建资源,因此根本不要使用defer- 否则,在函数退出之前,您不会关闭在循环内创建的任何资源,因此它们会堆积直到然后。相反,您应该在每次循环迭代结束时关闭它们, 而无需 :
本文向大家介绍了解事件代理吗,这样做有什么好处?相关面试题,主要包含被问及了解事件代理吗,这样做有什么好处?时的应答技巧和注意事项,需要的朋友参考一下 参考回答: 事件代理/事件委托:利用了事件冒泡,只指定一个事件处理程序,就可以管理某一类型的事件, 简而言之:事件代理就是说我们将事件添加到本来要添加的事件的父节点,将事件委托给父节点来触发处理函数,这通常会使用在大量的同级元素需要添加同一类事件的
问题内容: 我只是看了一下新的Java 8 函数包,想知道为什么会有类似的接口 … 这也 不会 延长。这是否意味着我将无法通过要求a的地方,反之亦然?这同样适用于,和。 我看到的优点是,不必在返回原语时进行检查,但是缺点列表似乎要长得多 问题答案: 此问题与以下事实有关:Java中的原始类型未统一为可替代,并且具有通用类型擦除。 使用代替而不是最后一个满足时有两个缺点: 每个返回的内容都用盒装-意
关于函数的Perl6网站说 强制类型可以帮助您在例程中拥有特定类型,但可以接受更广泛的输入。调用例程时,参数将自动转换为较窄的类型。 这里Int是参数将被强制的目标类型,Cool是例程接受作为输入的类型。 但潜艇的意义何在?不就是一个?为什么要限制调用者为参数实现? 这个例子让我倍感困惑,因为已经