如果你做了Scala
scala> var st = "test"
st: java.lang.String = test
你得到一个java String。
但如果你这样做,你会得到一个Scala
scala> var st:String = "test2"
st: String = test2
问题:在Java字符串置换方法中,您只看到String类型,但在Scala中,您会看到List的示例(“a”,“b”,“c”)。有什么区别?
例如,在Java中,您可以对字符串排列执行此操作:
private static void permutation(String prefix, String str) {
int n = str.length();
//one-char string has only one permutation
if (n == 1)
System.out.println(prefix + str);
else {
//recursive case
for (int i = 0; i < n; i++) {
char ch = str.charAt(i);
String rest = str.substring(0, i) + str.substring(i + 1);
permutation(prefix + ch, rest);
}
}
然而,在Scala中,它更多地是关于List:
def permutations[A](xs: List[A]) : List[List[A]] = xs match {
case Nil => List(Nil)
case x::xs => permutations(xs).flatMap(inserts(x, _))
}
def inserts[A](x: A, ys: List[A]) : List[List[A]] = ys match {
case Nil => List(List(x))
case y::ys => (x::y::ys) :: inserts(x, ys).map(y::_)
}
答案 0 :(得分:7)
当您查看Predef.scala
时,您会发现以下定义:
type String = java.lang.String
这意味着String
只是java.lang.String
的类型同义词。没有区别。
在Scala中有所谓的“pimp my library”模式(这个名称似乎在此期间已经改变,但这是原始名称)。此模式允许您向现有类型添加其他行为(不更改类型)。它是使用隐式转换实现的。这意味着在编译期间,编译器将在必要时注入一个将现有类型更改为新类型的函数。然后,这种新类型可以提供新的行为,通常是一些方便的方法。使用所谓的value classes时,此转换带有零运行时成本。
Predef.scala
为字符串提供了这种隐式转换:
@inline implicit def augmentString(x: String): StringOps = new StringOps(x)
此函数将类型为String
的对象(即Java字符串)转换为类型为StringOps
的对象。 StringOps
提供了一些便利功能,特别是对于字符串(例如stripMargin
)和一些使字符串行为像字符序列的函数(例如map
)。
每当您在Java字符串上访问其中一个函数时,编译器将插入augmentString
的函数调用,以将您的普通Java字符串转换为Scala StringOps。
Scala有一个非常强大的API,称为monadic API。此API允许您使用通用结构过滤,转换和组合许多不同类型。因此,您可以使用相同的API来访问,例如类型为List
的对象以及类型为Future
的对象。将此API也提供给字符串非常方便。
使用JSR 335,Java中也会有一个monadic API。但这需要一些时间,直到普通的Java stings也会获得开箱即用的monadic API。
虽然将字符串转换为字符序列没有运行时间成本,但相反的方式可能更昂贵。当你有一系列字符并希望它转换为字符串时,通常没有隐式转换。您必须使用mkString
明确地执行此操作。
示例:
List('a','b','c').map(_.toUpper).mkString
StringOps
有一些特殊的优化,即对于被视为字符序列的字符串。它们确实会自动转换回字符串。 StringOps
中的方法在可能的情况下直接返回字符串作为结果,例如
def map[B](f: (A) ⇒ B): String[B]
def filter(p: (Char) ⇒ Boolean): String
对于这些函数,直接创建字符串通常与创建中间序列作为结果一样便宜。
当没有额外费用时,Scala会自动在字符序列和字符串之间进行转换。当成本很高时,您必须进行明确的转换。在所有常见用例中,您不必担心这一点,因为Scala会自动执行正确的操作。在所有其他情况下,知道幕后发生的事情可能是有用的。