在scala中连接包含在一组对象中的集合
我刚刚开始使用scala,我正在将一些java代码转换成scala,并试图使其美观、功能优雅 我有以下代码,其中包含一个方法(getRequiredUploadPathKeys),该方法提供MyClass中所有可用路径模板所需的所有路径键的并集在scala中连接包含在一组对象中的集合,scala,scala-collections,Scala,Scala Collections,我刚刚开始使用scala,我正在将一些java代码转换成scala,并试图使其美观、功能优雅 我有以下代码,其中包含一个方法(getRequiredUploadPathKeys),该方法提供MyClass中所有可用路径模板所需的所有路径键的并集 trait PathTemplate { def getRequiredPathKeys:Set[PathKey] } class MyClass(accessPaths:Set[PathTemplate], targetPath:PathTe
trait PathTemplate {
def getRequiredPathKeys:Set[PathKey]
}
class MyClass(accessPaths:Set[PathTemplate], targetPath:PathTemplate){
def getAllRequiredPathKeys: Set[PathKey] = {
val pathKeys = HashSet[PathKey]()
pathKeys.addAll(targetPath.getRequiredPathKeys)
for (accessTemp <- accessPaths) {
pathKeys.addAll(accessTemp.getRequiredPathKeys)
}
return pathKeys
}
}
trait路径模板{
def GetRequiredPathKey:设置[PathKey]
}
类MyClass(AccessPath:Set[PathTemplate],targetPath:PathTemplate){
def GetAllRequiredPathKey:设置[PathKey]={
val pathKeys=HashSet[PathKey]()
addAll(targetPath.getRequiredPathKeys)
对于(accessTemp您是指:
def getAllRequiredPathKeys = (accessPaths map { _.getRequiredPathKeys }).flatten ++ targetPath.getRequiredPathKeys
或与
def getAllRequiredPathKeys =
for(path <- accessPaths + targetPath;
key <- path.getRequiredPathKeys) yield key
def getAllRequiredPathKeys=
对于(path来说,这里的奇怪之处在于,您使用的是Java的HashSet
——Scala中没有addAll
——也不需要这样做
因此,我将对各种设计决策以及它们在Java和Scala之间的差异进行评论
val pathKeys = HashSet[PathKey]()
惯用的Scala通常不引用实现接口的类,因为接口有一个工厂
。此外,这显然是一个Scala工厂,因为没有new
关键字——这意味着其余的代码将无法工作,因为Scala的集合中没有addAll
pathKeys.addAll(targetPath.getRequiredPathKeys)
这里您不直接使用targetPath.getRequiredPathKeys
,因为Java的Set
是可变的。默认的ScalaSet
是不可变的,这使得它毫无用处——您只需使用targetPath.getRequiredPathKeys
作为基集,而不必将其元素添加到另一个集合中
就性能而言,Scala——与函数语言一样——在其不可变集合实现中使用。这意味着它重用一个数据结构的一部分来创建派生数据结构,而不是每次创建新数据结构时都复制所有内容。这只有在不可变性保证的情况下才可能实现
无论如何,您可以这样做:
val pathKeys = targetPath.getRequiredPathKeys
其次,
但是,请注意,getRequiredPathKeys
的重复。函数式程序员讨厌重复。在我看来,有时候重复得太多了,但在这种情况下,它可以很容易地删除:
val pathKeys = for {
accessPath <- accessPaths + targetPath
requiredPathKey <- accessPath.getRequiredPathKeys
} yield requiredPathKey
末尾的map
是多余的,因为它什么都不做。事实上,每当yield
只返回一个简单标识符时,表达式中就有一个多余的map
。删除它会给我们带来:
val pathKeys = (accessPaths + targetPath).flatMap(accessPath =>
accessPath.getRequiredPathKeys)
或者,使用Scala的匿名函数参数语法
val pathKeys = (accessPaths + targetPath).flatMap(_.getRequiredPathKeys)
最后,
return pathKeys
Scala中的关键字return
用于指定工作流中的异常——在该点上,方法的执行被中止,而不是一直执行到结束。这并不是说它没有用处,而是像异常本身一样,它不应该无缘无故地被使用。在这里,您应该使用
pathKeys
但是,此时,您的代码变成了这两行:
val pathKeys = (accessPaths + targetPath).flatMap(_.getRequiredPathKeys)
pathKeys
这使得val
赋值完全冗余。因此,您可以将其减少为:
(accessPaths + targetPath).flatMap(_.getRequiredPathKeys)
因此,该方法成为
def getAllRequiredPathKeys: Set[PathKey] = {
(accessPaths + targetPath).flatMap(_.getRequiredPathKeys)
}
现在,我知道我在后面说了“finally”,但还有一点Scala约定需要应用。每当一个方法包含一个表达式而不是多个语句时,约定是使用大括号。换句话说,执行以下操作:
def getAllRequiredPathKeys: Set[PathKey] =
(accessPaths + targetPath).flatMap(_.getRequiredPathKeys)
或者,如果空间允许,将所有内容放在一行上。事实上,如果删除getAllRequiredPathKeys
type,它将非常适合。另一方面,鼓励在public方法上使用显式返回类型
因此,这将为您提供一个Scala的不可变集
。假设您的输入和输出必须是Java的集
。在这种情况下,我看不到任何可以简化代码的方法,除非您愿意在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的可变集
,这意味着创建新集
的每个操作都将复制旧集的所有内容您可以使用flatMap将其缩短。非常感谢:)我已经非常接近了,但是扁平化方法是缺少的一点!哇,这太神奇了。我仍然在消化所有的内容,但这是对解决方案演变的一个很好的描述。谢谢:)这是一个很好的演练,非常适合Java难民!谢谢!
pathKeys.addAll(targetPath.getRequiredPathKeys)
(accessPaths + targetPath).flatMap(_.getRequiredPathKeys)
def getAllRequiredPathKeys: Set[PathKey] = {
(accessPaths + targetPath).flatMap(_.getRequiredPathKeys)
}
def getAllRequiredPathKeys: Set[PathKey] =
(accessPaths + targetPath).flatMap(_.getRequiredPathKeys)
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
}