这里的奇怪的事情是,你正在使用Java的HashSet
- 没有012 Scala中的- 而且没有必要。
因此,我要评论各种设计决策以及它们与Java到Scala的不同之处。首先,
val pathKeys = HashSet[PathKey]()
自定义Scala通常不会引用实现接口的类,因为接口有一个工厂。所以你通常只使用Set[PathKey]()
。此外,这显然是一个斯卡拉工厂,因为没有new
关键字 - 这意味着其他代码将无法正常工作,因为Scala的Set
中没有addAll
。
pathKeys.addAll(targetPath.getRequiredPathKeys)
在这里,您不使用targetPath.getRequiredPathKeys
直接因为Java的Set
是可变的。默认的Scala Set
是不可变的,这使得它无用 - 您可以使用targetPath.getRequirePathKeys
作为基本集合,而不必将其元素添加到另一个集合。
性能方面,斯卡拉般的功能语言 - 在其不可变集合实现中使用persistent datastructures。这意味着它会重用一个数据结构的一部分来创建派生数据结构,而不是在每次创建新数据结构时都复制所有内容。这是唯一可能的,因为不变性保证。
在任何情况下,你可能只是这样做:
val pathKeys = targetPath.getRequiredPathKeys
接下来,
for (accessTemp <- accessPaths) {
pathKeys.addAll(accessTemp.getRequiredPathKeys)
}
首先,推导的习惯用法是返回一个值,即,对于收益。上面的使用应该仅限于代码的副作用部分。为了更清楚,上面可以分两个步骤来完成:
// Get all required Path Keys
val requiredPathKeys = for {
accessPath <- accessPaths
requiredPathKey <- accessPath.getRequiredPathKeys
} yield requiredPathKey
// Then add them
pathKeys.addAll(requiredPathKeys)
然而,由于你不addAll
东西Scala的Set
,你要么需要做pathKeys
一个var
,或使用可变数据结构,或简单地改变的顺序:
val requiredPathKeys = for {
accessPath <- accessPaths
requiredPathKey <- accessPath.getRequiredPathKeys
} yield requiredPathKey
val pathKeys = targetPath.getRequiredPathKeys ++ requiredPathKeys
但是请注意,在的getRequiredPathKeys
重复。功能程序员厌恶重复。有时过于所以,在我看来,不过,在这种情况下,它可以很容易地删除:
val pathKeys = for {
accessPath <- accessPaths + targetPath
requiredPathKey <- accessPath.getRequiredPathKeys
} yield requiredPathKey
上面的代码提出另一种改进。如果你看到this question关于Scala的用于解析,你会看到,上面是相当于
val pathKeys = (accessPaths + targetPath).flatMap(accessPath =>
accessPath.getRequiredPathKeys.map(requiredPathKey => requiredPathKey))
的map
末是多余的,因为它没有做任何事情。实际上,只要yield
只返回一个简单的标识符,表达式中就有一个冗余map
。删除它给我们:
val pathKeys = (accessPaths + targetPath).flatMap(accessPath =>
accessPath.getRequiredPathKeys)
或者,使用Scala的匿名函数参数语法,
val pathKeys = (accessPaths + targetPath).flatMap(_.getRequiredPathKeys)
最后,
return pathKeys
斯卡拉关键字return
用于指定在一个异常工作流程 - 该方法执行被终止而不是结束的一个点。不是说这不是没有用,但是,像例外本身一样,不应该没有原因地使用它。在这里,你应该使用
pathKeys
但是,在这一点上,你的代码变得只有这两条线:
val pathKeys = (accessPaths + targetPath).flatMap(_.getRequiredPathKeys)
pathKeys
这使得val
分配完全redudant。你可以把它从而减少:
(accessPaths + targetPath).flatMap(_.getRequiredPathKeys)
因此该方法变得
def getAllRequiredPathKeys: Set[PathKey] = {
(accessPaths + targetPath).flatMap(_.getRequiredPathKeys)
}
现在,我知道我说“终于”回到那里,但有斯卡拉公约的一个更珍闻申请。每当一个方法包含单个表达式而不是多个语句时,约定就是忽略大括号。换句话说,这样做:
def getAllRequiredPathKeys: Set[PathKey] =
(accessPaths + targetPath).flatMap(_.getRequiredPathKeys)
或者,如果空间允许的话,把所有东西放在一行上。事实上,如果您删除getAllRequiredPathKeys
类型,它将很好地适合。另一方面,鼓励公开方法明确的回报类型。
所以这会给你一个斯卡拉不可变的Set
。假设您的输入和输出必须是Java的Set
。在这种情况下,除非您愿意在Java和Scala集之间进行转换,否则我没有看到任何可以简化代码的操作。你可以是这样做的:
trait PathTemplate {
def getRequiredPathKeys:java.util.Set[PathKey]
}
import scala.collection.JavaConverters._
class MyClass(accessPaths:java.util.Set[PathTemplate], targetPath:PathTemplate){
def getAllRequiredPathKeys: java.util.Set[PathKey] =
(accessPaths.asScala + targetPath).flatMap(_.getRequiredPathKeys.asScala).asJava
}
然而,这使用Scala的可变Set
,这意味着每个操作创建一个新的Set
将复制旧Set
所有内容。
你可以使用flatMap使它更短。 – 2011-05-13 11:54:12
真棒谢谢:)我已经非常接近,但平坦的方法是失踪的位! – Paul 2011-05-13 12:29:57