高阶函数,是指以一个函数作为输入或输出的函数。我们常用的Curry化函数,就是输出一个函数的高阶函数。 在Scala中,容器包含了丰富的高阶函数,从经典的map-reduce,到晦涩的aggregate,应有尽有。虽然初看起来过于复杂, 但是它在提高代码重用性,以及封装并发性等方面,却有不可替代的作用,十分值得我们学习。
ListList类几乎包含了Scala集合框架中所有的高阶函数,所以我们使用它作为样例来分析高阶函数。 在它的文档中,可以看到所有List的所有方法。这里按照文档的顺序来一一说明其意义。 声明在前,这里所有的方法都是非破坏性方法,也就是说,它们不改变容器的内容。 aggregate
- 作用:一个比fold、reduce更加抽象的聚集操作,对集合分块,块中每一个元素执行一个操作,得到一个容器,在将这些容器进行聚集。
- 样例:
1
2
3
4
|
// 求容器所有元素mod之后的Set
val list = List(1, 4, 9)
list.aggregate(scala.collection.mutable.Set[Int]())(_ += _ % 8, _ ++ _)
// return: Set[Int] = Set(1, 4)
|
andThen
- 作用:把两个函数组合在一起,先调用第一个函数,再调用第二个。
- 样例:
1
2
3
4
5
6
|
// 先调用add2, 再调用add3
def add2(num: Int) = num + 2
def print(num: Int) = println(num)
val addAndPrint = add2 _ andThen print _
addAndPrint(2)
//return: 4
|
collect
- 作用:基于给定的偏函数,遍历容器,得到一个新的容器。(此函数十分强大)
- 样例:
1
2
3
4
|
// 找到列表中的奇数,乘以2
val list = List(1, 4, 9)
list collect { case item if item % 2 == 1 => item * 2 }
// return: List[Int] = List(2, 18)
|
collectFirst
- 作用:基于给定的偏函数,查找第一个满足此条件的元素。
样例:
1
2
3
|
// 找到第一个奇数,乘以2
val list = List(1, 4, 9)
list collectFirst { cast item if item % == 1 => item * 2} getOrElse 0
|
compose
- 作用:把两个函数组合在一起,形成一个新的函数。
- 样例:
1
2
3
4
5
6
|
// 把两个函数组合
def add2(num: Int) = num + 2
def add3(num: Int) = num + 3
val add5 = add2 _ compose add3 _
add5(1)
// return: Int = 6
|
corresponds
- 作用:测试两个容器所有相应的元素时候满足一定的关系。
- 样例:
1
2
3
4
5
|
// 判断两个列表的元素是否满足两倍的关系
val list1 = List(1, 4, 9)
val list2 = List(2, 8, 18)
list1.corresponds(list2){_ * 2 == _}
// return : Boolean = true
|
count
- 作用:计数满足条件的元素
- 样例:
1
2
3
4
|
// 计数偶数的个数
val list = List(1, 4, 9)
list.count(_ % 2 == 0)
// return : Int = 1
|
dropWhile
- 作用:以指定的条件删除满足条件的最长前缀
- 样例:
1
2
3
4
|
// 删除小于8 的前缀
val list = List(1, 4, 9)
list.dropWhile(_ < 8)
// return: List[Int] = List(9)
|
exists
- 作用:判断容器中是否存在满足条件的元素
- 样例:
1
2
3
4
|
// 判断是否存在偶数
val list = List(1, 4, 9)
list.exists(_ % 2 == 0)
// return : Boolean = true
|
filter
- 作用:以指定的条件过滤容器
- 样例:
1
2
3
4
|
// 返回偶数
val list = List(1, 4, 9)
list.filter(_ % 2 == 0)
//return : List[Int] = List(2)
|
filterNot
- 作用:反向过滤容器
- 样例:
1
2
3
4
|
// 返回奇数
val list = List(1, 4, 9)
list.filterNot(_ % 2 == 0)
// return : List[Int] = List(1, 9)
|
find
- 作用:在容器中查找元素
- 样例:
1
2
3
4
|
// 查找偶数
val list = List(1, 4, 9)
list.find(_ % 2 == 0)
// return : Option[Int] = Some(2)
|
flatten
- 作用:将容器扁平化
- 样例:
1
2
3
4
|
// 扁平化
val list = List(List(2, 3), List(4, 5))
list.flatten
// return: List[Int] = List(2, 3, 4, 5)
|
fold
- 作用:“折叠容器”,给定初始值,以及折叠方法。或称统计,一般用来统计某个特征。
- 样例:
1
2
3
|
// 求10的阶乘
(1 to 10).fold(1)(_ * _)
// return: Int = 3628800
|
forall
- 作用:测试容器中的每一个元素
- 样例:
1
2
3
|
val list = List(1, 4, 9)
list.forall(_ % 2 == 0)
//return : Boolean = false
|
foreach
- 作用:以容器中的每一个元素为参数调用函数,无返回值。
- 样例:
1
2
3
4
|
// 打印容器
val list = List(1, 4, 9)
list.foreach(println)
// return :
|
groupBy
- 作用:以指定的条件来对容器中的元素分组,得到一个Map。
- 样例:
1
2
3
4
|
// 以 mod 8 的结果来对容器的元素分组
val list = List(1, 4, 9)
list groupBy (_ % 8)
// return: scala.collection.ummutable.Map[Int, List[Int]] = Map(4 -> List(4), 1 -> List(1, 9))
|
indexWhere
- 作用:查找满足条件的元素的索引
- 样例:
1
2
3
4
|
// 查找第一个偶数的位置
val list = List(1, 4, 9)
list.indexWhere(_ % 2 == 0)
// return: Int = 1
|
map
- 作用:以容器中每一个元素为参数调用函数,返回新容器
- 样例:
1
2
3
4
|
// 将容器中的元素 * 2
val list = List(1, 4, 9)
list.map(_ * 2)
// return : List[Int] = List(2, 8, 18)
|
maxBy
- 作用:以指定的条件来衡量每个元素的价值,找价值最大的。
- 样例:
1
2
3
4
|
// 找mod 7之后最大的元素
val list = List(1, 4, 9)
list.maxBy(_% 7)
// return: Int = 4
|
minBy
- 作用:以指定的条件衡量每个元素的价值,找价值最小的。
- 样例:
1
2
3
|
// 找mod 7 之后最小的元素
val list = List(1, 4, 9)
// return: Int = 1
|
partition
- 作用:按照指定的条件,将容器分成两部分,前一部分满足条件,后半部分不满足。
- 样例:
1
2
3
4
|
// 将奇数和偶数分离
val list = List(1, 4, 9)
list.partition(_ % 2 == 0)
// return : (List[Int], List[Int]) = (List(4), List(1, 9))
|
prefixLength
- 作用:计算满足长度的最长前缀的长度
- 样例:
1
2
3
4
|
// 从前往后满足小于8的前缀的长度
val list = List(1, 4, 9)
list.prefixLength(_ < 8)
//return : Int = 2
|
reduce
- 作用:规约,对容器中的每两个元素进行一次二元操作,直到只剩下最后一个元素,其顺序不固定。
- 样例:
1
2
3
4
|
// 计算元素的和
val list = List(1, 4, 9)
list.reduce(_ + _)
// return: Int = 14
|
reduceOption
- 作用:规约,对容器中每两个元素执行二元操作,知道只剩下最后一个元素,返回Option。
- 样例:
1
2
3
4
|
// 计算元素的积
val list = List(1, 4, 9)
list.reduceOption(_ * _)
// return: Option[Int] = Some(36)
|
reverseMap
- 作用:逆序执行Map
- 样例:
1
2
3
4
|
// 逆序列表并乘以2
val list = List(1, 4, 9)
list.reverseMap(_ * 2)
// return: List[Int] = List(18, 8, 2)
|
runWith
- 作用:执行偏函数,当参数不在定义域内时,返回false,否则返回true,并执行action。
- 样例:
1
2
3
4
5
6
|
// 偏函数将奇数*2,然后打印结果
val pf: PartialFunction[Int, Int] = { case m: Int if m % 2 == 1=> m * 2 }
pf.runWtih(println)(3)
// return: Boolean = true
pf.runWith(println)(2)
// return: Boolean = false
|
scan
- 作用:折叠,与fold的动作类似,但会将每一次折叠的结果存放到另一个容器中,然后那个容器。
- 样例:
1
2
3
|
// 求1-10的阶乘
(1 to 10).scan(1)(_ * _)
//return :scala.collection.immutable.IndexedSeq[Int] = Vector(1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800)
|
sortWith
- 作用:用指定的函数排序
- 样例:
1
2
3
4
|
// 倒排
val list = List(1, 4, 9)
list.sortWith(_ > _)
// return: List[Int] = List(9, 4, 1)
|
span
- 作用:以指定的条件切分列表,满足条件的最长前缀和其余的部分作为一个元组返回。
- 样例:
1
2
3
4
|
// 查找小于8的前缀,以及剩下部分
val list = List(1, 4, 9)
list span(_ < 8)
// return : (List[Int], List[Int]) = (List(1, 4), List(9))
|
takeWhile
- 作用:以指定的条件截取最长的前缀
- 样例:
1
2
3
4
|
// 小于8的前缀
val list = List(1, 4, 9)
list.takeWhile(_ < 8)
// return: List[Int] = List(1, 4)
|
后记前后一共花了三天时间才搞定这个文档,从一开始对这些函数一无所知,翻阅各种文档,在StackOverFlow上找结果,最终还是搞定了这个文档。当然,这个函数创造的本意是提高效率,而不是为了学习这些函数而学习。目前还没有对容器中高阶函数的详细介绍,希望这个文档能对学习Scala的人有所帮助。 |