有人可以帮我理解这段代码吗?我对Scala一无所知,也没有听说过。
def maxSubseq(l: List[Int]) = l.scanRight(Nil : List[Int]) {
case (el, acc) if acc.sum + el < 0 => Nil
case (el, acc) => el :: acc
} max Ordering.by((_: List[Int]).sum)
def biggestMaxSubseq(l: List[Int]) = l.scanRight(Nil : List[Int]) {
case (el, acc) if acc.sum + el < 0 => Nil
case (el, acc) => el :: acc
} max Ordering.by((ss: List[Int]) => (ss.sum, ss.length))
def biggestMaxSubseq[N](l: List[N])(implicit n: Numeric[N]) = {
import n._
l.scanRight(Nil : List[N]) {
case (el, acc) if acc.sum + el < zero => Nil
case (el, acc) => el :: acc
} max Ordering.by((ss: List[N]) => (ss.sum, ss.length))
}
def linearBiggestMaxSubseq[N](l: List[N])(implicit n: Numeric[N]) = {
import n._
l.scanRight((zero, Nil : List[N])) {
case (el, (acc, _)) if acc + el < zero => (zero, Nil)
case (el, (acc, ss)) => (acc + el, el :: ss)
} max Ordering.by((t: (N, List[N])) => (t._1, t._2.length)) _2
}
这段代码可以用Java实现吗?
答案 0 :(得分:7)
当然,它可以用Java实现。但是,这需要更多的努力。我们在这里看一些观点。
def linearBiggestMaxSubseq[N](l: List[N])(implicit n: Numeric[N]) = {
这声明了一个接收List
N
和隐式参数Numeric[N]
的方法。隐式参数通常由编译器本身通过查找与所需参数匹配的声明的某些位置来派生 - 几乎就像依赖注入一样。
在这种情况下,Numeric[N]
是一个提供基本数学运算的类,并且标准库中提供了所有数值类型的实例。此方法在Numeric
中使用的唯一内容是plus
和zero
。
Java没有隐含,因此等效的Java API使用起来会更麻烦,需要传递一个额外的参数。
另外,我不记得Java中的任何等同于Numeric
的内容。 java.lang.Number
未提供BigInt
和BigDecimal
中的方法。您必须编写自己的等效Numeric
,然后编写实例以涵盖所有数字类型,然后客户端代码必须显式传递实例。如果在Java中有替代方法可以实现所有这些努力,我很乐意听到它。
import n._
所有这一切都允许代码执行acc + el
代替n.plus(acc, el)
,zero
代替n.zero
。它是如何做到的超出了这个问题的范围。
l.scanRight((zero, Nil : List[N])) {
Java中没有scanRight
等价物。您必须将其转换为while
循环,但这并不是特别难。 scanRight
将从右到左遍历列表(虽然我没有看到任何理由为什么代码从右到左执行而不是从左到右更简单有效)。
当它遍历列表(l
)时,它将调用一个传递两个参数的函数:当前元素和“累加器”。这里的累加器是一个Pair
,一个浅层对象,带有一对getter和setter,用于contains中的两个元素。第一次使用zero
和Nil
(空列表)初始化此对。
scanRight
调用的方法应该返回与累加器类型相同的东西 - 因此,传递Pair[N, List[N]]
时,它应该返回一个新的Pair[N, List[N]]
。
最后,scanRight
将创建一个集合,其中包含正在调用的方法的结果。
case (el, (acc, _)) if acc + el < zero => (zero, Nil)
case (el, (acc, ss)) => (acc + el, el :: ss)
此代码中存在大量匹配问题,必须由一系列if
/ else
语句替换。详细,但不是特别麻烦。
在这种特殊情况下,(el, (acc, _))
和(ec, (acc, ss))
只是传递的参数。他们可以体现测试,但是,在这里,他们没有。唯一的考验是acc + el < zero
。如果是,则返回(zero, Nil)
,否则返回(acc + el, el :: ss)
。正如我之前所说,Nil
是一个空列表。在此处,el :: ss
会返回一个新列表,其中el
位于列表ss
的前面。
} max Ordering.by((t: (N, List[N])) => (t._1, t._2.length)) _2
至少Java的数字类通常实现Comparable
,即使它们没有实现提供数字操作的接口。有许多Ordering.by
个实例,每个实例都需要Comparator
等效或其他临时解决方案。
无论如何,这将返回最大元素(max
),使用Ordering
(相当于Comparator
),首先考虑该对的第一个元素的值,以及该对的第二个元素的长度(这是一个列表)。
最后,_2
将丢弃该对的第一个元素并返回第二个元素。
这是所有方法中最复杂的。以前的更简单,代价是不那么通用和有效。
因此,Java版本肯定会更加冗长,但除了Numeric
问题之外,应该非常直接地编写。然后,Numeric
问题非常关键。