前幾天想用scala統(tǒng)計(jì)一個(gè)字符串中一個(gè)字符出現(xiàn)的次數(shù),于是到scala官網(wǎng)上去搜String類的API,結(jié)果有點(diǎn)意外社证。在API DOCS如下一段:
Automatic imports
Identifiers in the scala package and the scala.Predef object are always in scope by default.
Some of these identifiers are type aliases provided as shortcuts to commonly used classes. For example, List is an alias for scala.collection.immutable.List.
Other aliases refer to classes provided by the underlying platform. For example, on the JVM, String is an alias for java.lang.String.
scala的String類其實(shí)就是java的String。作為JVM方言粤蝎,這也是情理之中的事窟扑。自然在scala官網(wǎng)上不會(huì)有String的API介紹喇颁。換個(gè)思路,統(tǒng)計(jì)字符次數(shù)的方法一般都叫count嚎货,于是用scala+string+count在網(wǎng)上一搜橘霎,很快就找到想要的東西。
scala> "hello".count(_=='l')
res0: Int = 2
轉(zhuǎn)念一想殖属,java的String類印象中沒有count方法啊姐叁。于是又到j(luò)ava官網(wǎng)查了String API,的確沒有洗显。
這是怎么回事呢外潜?讓我們先把scala華麗的外殼打開,看看里面到底發(fā)生了什么:
scala> :settings -Xprint:typer
scala> "hello".count(_=='l')
[[syntax trees at end of typer]] // <console>
package $line5 {
object $read extends scala.AnyRef {
def <init>(): $line5.$read.type = {
$read.super.<init>();
()
};
object $iw extends scala.AnyRef {
def <init>(): type = {
$iw.super.<init>();
()
};
object $iw extends scala.AnyRef {
def <init>(): type = {
$iw.super.<init>();
()
};
private[this] val res2: Int = scala.Predef.augmentString("hello").count(((x$1: Char) => x$1.==('l')));
<stable> <accessor> def res2: Int = $iw.this.res2
}
}
}
}
[[syntax trees at end of typer]] // <console>
package $line5 {
object $eval extends scala.AnyRef {
def <init>(): $line5.$eval.type = {
$eval.super.<init>();
()
};
lazy private[this] var $result: Int = _;
<stable> <accessor> lazy def $result: Int = {
$eval.this.$result = $line5.$read.$iw.$iw.res2;
$eval.this.$result
};
lazy private[this] var $print: String = _;
<stable> <accessor> lazy def $print: String = {
$eval.this.$print = {
$line5.$read.$iw.$iw;
"res2: Int = ".+(scala.runtime.ScalaRunTime.replStringOf($line5.$read.$iw.$iw.res2, 1000))
};
$eval.this.$print
}
}
}
res2: Int = 2
其中最關(guān)鍵的一句是:
val res2: Int = scala.Predef.augmentString("hello").count(((x$1: Char) => x$1.==('l')));
String對(duì)象hello并不是直接調(diào)用的count方法挠唆,而是經(jīng)過了一次轉(zhuǎn)換处窥。首先String類對(duì)象作為參數(shù)傳給了Predef.augmentString,然后再調(diào)用count方法玄组。
繼續(xù)到scala官網(wǎng)上看看Predef.augmentString是何方神圣:
implicit def augmentString(x: String): StringOps
原來是個(gè)隱式轉(zhuǎn)換函數(shù)滔驾,把String類轉(zhuǎn)成StringOps類。而StringOps類就有count方法:
def count(p: (Char) ? Boolean): Int
Counts the number of elements in the traversable or iterator which satisfy a predicate.
真相終于大白俄讹。