[TOC]
1、Scala中的集合体系主要包括:Iterable
、Seq(IndexSeq)
、Set(SortedSet)
、Map(SortedMap)
。其中Iterable是所有集合trait的根trait。实际上Seq、Set、和Map都是子trait
Seq
是一个有先后次序的值的序列,比如数组或列表。IndexSeq允许我们通过×××的下表快速的访问任意元素。举例来说,ArrayBuffer是带下标的,但是链表不是。
Set
是一组没有先后次序的值。在SortedSet中,元素以某种排过序顺序被访问。
Map
是一组(键、值)对偶。SortedMap按照键的排序访问其中的实体。
2、 Scala中的集合是分成可变和不可变两类集合的,其中可变集合就是说,集合的元素可以动态修改,而不可变集合的元素在初始化之后,就无法修改了。分别对应scala.collection.mutable
和scala.collection.immutable
两个包。
3、Seq下包含了Range
、ArrayBuffer
、List
等子trait。其中Range就代表了一个序列,通常可以使用“1 to10”这种语法来产生一个Range。 ArrayBuffer就类似于Java中的ArrayList。
1、在Scala中,列表要么是Nil(及空表),要么是一个head元素加上一个tail,而tail又是一个列表
scala> val list = List(1, 2, 3, 4, 5)
list: List[Int] = List(1, 2, 3, 4, 5)
scala> list.head
res29: Int = 1
scala> list.tail
res30: List[Int] = List(2, 3, 4, 5)
scala> list.isEmpty
res31: Boolean = false
scala> list == Nil
res32: Boolean = false
下面是一个使用递归求list集合中和的例子:
def recursion(list:List[Int]):Int = {
if(list.isEmpty) {
return 0 // 使用return显式结束程序的运行,否则0只是该if语句的返回值,并不会结束程序的运行,当然如果用else不用return也行
}
list.head + recursion(list.tail)
}
//增
/* A.++(B) --> 在列表A的尾部对添加另外一个列表B,组成一个新的列表
* A.++:(B) --> 在列表A的首部对添加另外一个列表B,组成一个新的列表
* A.:::(B) --> 在列表A的首部对添加另外一个列表B,组成一个新的列表
* ------
* A.:+ (element) -->在列表A的尾部添加一个element,组成一个新的集合
* A.+: (element) -->在列表A的首部添加一个element,组成一个新的集合
* A.:: (element) -->在列表A的首部添加一个element,组成一个新的集合
*/
测试如下:
scala> val left = List(1, 2, 3, 4)
left: List[Int] = List(1, 2, 3, 4)
scala> val right = List(5, 6, 7)
right: List[Int] = List(5, 6, 7)
scala> left.++(right)
res33: List[Int] = List(1, 2, 3, 4, 5, 6, 7)
scala> left.++:(right)
res34: List[Int] = List(5, 6, 7, 1, 2, 3, 4)
scala> left.:::(right)
res35: List[Int] = List(5, 6, 7, 1, 2, 3, 4)
scala> left.:+(10)
res36: List[Int] = List(1, 2, 3, 4, 10)
scala> left.+:(10)
res38: List[Int] = List(10, 1, 2, 3, 4)
scala> left.::(10)
res39: List[Int] = List(10, 1, 2, 3, 4)
drop(n) --->删除list的前n个元素(首部开始删除)
dropRight(n) --->删除list的后n个元素(尾部开始删除)
dropWhile(p: A => Boolean) --->逐个匹配去除符合条件的元素,直到不符合条件,之后的元素不再判断
测试如下:
scala> val list = List(1, 2, 3, 4, 5, 6, 7)
list: List[Int] = List(1, 2, 3, 4, 5, 6, 7)
scala> list.drop(2)
res52: List[Int] = List(3, 4, 5, 6, 7)
scala> list.dropRight(3)
res53: List[Int] = List(1, 2, 3, 4)
scala> list.dropWhile(_ <= 3)
res54: List[Int] = List(4, 5, 6, 7)
scala> list.dropWhile(_ > 3) // 第一个元素就不符合条件,后面的不再判断,所以一个也没有删除
res55: List[Int] = List(1, 2, 3, 4, 5, 6, 7)
scala> val list = List(1, 2, 3, 4, 5, 6, 7)
list: List[Int] = List(1, 2, 3, 4, 5, 6, 7)
scala> list(0)
res57: Int = 1
scala> list(0) = 10
<console>:9: error: value update is not a member of List[Int]
list(0) = 10
^
默认的List是在:
scala> List
res59: scala.collection.immutable.List.type = scala.collection.immutable.List$@3e98fd35
所以不能修改,但是尝试导入可修改的List也不能进行导入:
scala> import scala.collection.mutable.List
<console>:8: error: object List is not a member of package scala.collection.mutable
import scala.collection.mutable.List
原因如下:
Scala 列表类似于数组,它们所有元素的类型都相同,但是它们也有所不同:
列表是不可变的,值一旦被定义了就不能改变,其次列表 具有递归的结构(也就是链接表结构)而数组不是。
scala> val list = List(1, 2, 3, 4, 5, 6, 7)
list: List[Int] = List(1, 2, 3, 4, 5, 6, 7)
scala> list.take(5)
res60: List[Int] = List(1, 2, 3, 4, 5)
scala> list.takeWhile(_ <= 3)
res61: List[Int] = List(1, 2, 3)
scala> list.takeWhile(_ > 3)
res62: List[Int] = List()
scala> list.mkString
res63: String = 1234567
scala> list.count(_ % 2 == 0)
res64: Int = 3
scala> val fruit = "apples" :: ("oranges" :: ("pears" :: Nil)) // ::操作符从给定的头和尾部创建一个新的列表
fruit: List[String] = List(apples, oranges, pears)
scala> val list1 = List(1, 2, 3)
list1: List[Int] = List(1, 2, 3)
scala> val list2 = List(4, 5, 6)
list2: List[Int] = List(4, 5, 6)
scala> list1 ++ list2 // ++两个集合之间的操作
res70: List[Int] = List(1, 2, 3, 4, 5, 6)
scala> list1.sum
res72: Int = 6
1、数据集是不重复元素的集合。尝试将已有元素加入进来是没有效果的。比如
def setOps:Unit ={
(Set(2,0,1) + 1).foreach(println(_))
}
2、Set不保留元素插入的顺序。缺省情况下,集是以哈希集实现的,其元素根据hashCode方法的值进行组织。
Set(1,2,3,5,7,8).foreach(println(_))
3、链式哈希集可以记住元素被插入的顺序。它会维护一个链表来达到这个目的。
val weeks= scala.collection.mutable.LinkedHashSet("Mo","Tu","We","Th","Fr")
weeks.foreach(println(_))
4、按照已排序的顺序来访问其中的元素
scala.collection.immutable.SortedSet(1,2,3,4,5,6).foreach(println(_))
直接看下面的测试代码及注释:
package cn.xpleaf.bigdata.p4.collection
import scala.collection.mutable.SortedSet
object _02CollectionOps {
def main(args: Array[String]): Unit = {
setOps1
}
/**
* 关于scala集合顺序的说明
* 测试1:按照年龄进行升序,年龄相等,姓名降序
* 测试2:要按照姓名升序比较,按照年龄升序比较
* SortedSet在添加普通对象Person之类,报错
* No implicit Ordering defined for Person
* 要想在有序集合中添加元素,必须要让元素具备比较性,要和给集合提供比较器
* 在java中前者是要类实现Comparator,后者需要给集合提供一个比较器Comparator
* 在scala中,前者需要让类扩展Ordered的特质,后者给集合传递一个Ordering比较器
*
* 当两个比较都实现的话,优先使用集合的比较器
*/
def setOps1: Unit = {
var set = SortedSet[Person]()(new Ordering[Person] {
override def compare(x: Person, y: Person):Int = {
var ret = x.getName.compareTo(y.getName)
if(ret == 0) {
ret = x.getAge.compareTo((y.getAge))
}
ret
}
})
set.+= (new Person("王立鹏", 19))
set.+= (new Person("冯 剑", 18))
set.+= (new Person("刘银鹏", 15))
set.+= (new Person("李小小", 19))
// println(set)
set.foreach(println(_))
}
}
class Person extends Ordered[Person] {
private var name:String = _
private var age:Int = _
def this(name:String, age:Int) {
this()
this.name = name
this.age = age
}
def getAge = age
def getName = name
override def toString: String = {
s"[$name, $age]"
}
/**
* 按照年龄进行升序,年龄相等,姓名降序
* 升序:前面比后面
* 降序:后面比前面
*/
override def compare(that: Person) = {
var ret = this.age.compareTo(that.age)
if(ret == 0) {
ret = that.name.compareTo(this.name)
}
ret
}
}
输出结果如下:
[冯 剑, 18]
[刘银鹏, 15]
[李小小, 19]
[王立鹏, 19]
1、集合的函数式编程非常之重要,这是我们以后工作中每天都在使用的编程方式。
2、必须完全掌握和理解Scala的高阶函数是什么意思,Scala的集合类的map、flatMap、reduce、reduceLeft、foreach等这些函数,就是高阶函数,因为可以接收其他函数作为参数(部分高阶函数可以参考前面整理的函数式编程笔记)
3、高阶函数的使用,也是Scala与Java最大的一点不同!!!因为Java在1.8之前是没有函数式编程的,也肯定没有高阶函数,也肯定无法直接将函数传入一个方法,或者让一个方法返回一个函数
4、对Scala高阶函数的理解、掌握和使用,可以大大增强你的技术,而且也是Scala最有诱惑力、最有优势的一个功能。
5、在Spark源码中,有大量的函数式编程,所以必须掌握,才能看懂spark源码。
scala> val names = List("Peter","Paul","Mary")
names: List[String] = List(Peter, Paul, Mary)
scala> names.map(_.toUpperCase).foreach(println(_))
PETER
PAUL
MARY
scala> List("Peter","Paul","Mary").map(_ + "===>name").foreach(println(_))
Peter===>name
Paul===>name
Mary===>name
scala> List("Peter Glad","Paul Hello","Mary Your").flatMap(_.split(" ")).foreach(println)
Peter
Glad
Paul
Hello
Mary
Your
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。