集合

List

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/**
* List
* 列表类似于数组,它们所有元素的类型都相同,但是它们也有所不同:
* 列表是不可变的,值一旦被定义了就不能改变,
* 其次列表具有递归的结构(也就是链接表结构)而数组不是
*/
object TestList {
def main(args: Array[String]): Unit = {
// 不可变List
// 声明不可变List
// 字符串列表,两种方式
val strs = List("a","b","c","d")
val strs2 = "a"::("b"::("c"::("d"::Nil)))
// 整型列表,两种方式
val nums = List(1,2,3,4)
val nums2 = 1::(2::(3::(4::Nil)))
// 空列表,两种方式
val empty = List()
val empty2 = Nil
// 二维列表,两种方式
val dim = List(
List(1,1,1),
List(2,2,2),
List(3,3,3)
)
val dim2 = (1::(1::(1::Nil)))::(2::(2::(2::Nil)))::(3::(3::(3::Nil)))::Nil
// 遍历
for (i <- dim2){
println(i)
}
// 列表基本操作
// head 返回列表第一个元素
// tail 返回一个列表,包含除了第一元素之外的其他元素
// isEmpty 在列表为空时返回true
println(strs.head)
println(strs.tail)
println(empty.isEmpty)
// 连接列表
// 1. 使用 ::: 运算符
val str = strs:::strs2
// 2. 使用List.:::() 方法
val num = nums.:::(nums2)
// 3. 使用concat方法
val tem = List.concat(strs,strs2)
// List.fill()
// 我们可以使用 List.fill() 方法来创建一个指定重复数量的元素列表
val remem = List.fill(3)("ok")
// List.tabulate()
// 通过给定的函数来创建列表,第一个参数为元素的数量
// 第二个参数为指定的函数,我们通过指定的函数计算结果并返回值插入到列表中,起始值为 0
val squares = List.tabulate(6)(n => n * n)
// List.reverse
// 将列表的顺序反转
strs.reverse
val list = List(1)
// 添加元素
val list2 = 2 :: list
println(list2)
// List函数操作
val data = List("hello","Mike")
// map,把元素中的每个元素转成List
println(data.map(_.toList));
// flatMap,将list元素分成多个list元素,再重新合成新的List元素
println(data.flatMap(_.toList))
val lnum = List(1,2,3,4)
// sum,求和
println(lnum.sum)
// filter,过滤
println(lnum.filter(_ %2 == 0))
// partition,分区即根据条件分成两个list
println(lnum.partition(_ %2 == 0))
// groupBy,根据条件分组,返回Map集合
println(lnum.groupBy(i => i))
// slice,返回(first,end]区间的值
println(lnum.slice(1,4))
// splitAt,从第n个元素开始切开,分成两部分
println(lnum.splitAt(2))
// reduce,合并
println(lnum.reduce(_+_))
// fold,合并,有初始值
println(lnum.fold(10)(_+_))
// find,返回第一个符合的值(Option类型)
println(lnum.find(_ % 3 == 0).get)
// takeWhile,返回符合条件的List
println(lnum.takeWhile(_ < 3))
// dropWhile,删除符合条件的元素,返回剩下元素的List
println(lnum.dropWhile(_ < 3))
// span,和partition类似,符合条件的返回一个List,不符合条件的返回另一个List
println(lnum.span(_ < 4))
// sortWith,排序
println(lnum.sortWith(_ < _))
println(lnum.sortWith(_ > _))
// sorted排序
println(lnum.sorted)
// range
println(List.range(2,10,3))
// zip,unzip
val zipped = "abcd".toList.zip("123")
println(zipped)
println(zipped.unzip)
println(zipped.unzip._1)
// 变形集合,开启多个线程
val morelist:List[Int] = (1 to 100).map(i => 1).toList
println(morelist.par.fold(10)(_+_))
// view,惰性化计算
val seq = Seq(1,2,3)
val listS = seq.toList.map(i => println("A")).map(j => println("B"))
val listS2 = seq.view.toList.map(i => println("A")).map(j => println("B"))
// println("***"+listS)
// ListBuffer
// 可变列表
val lBuffer = scala.collection.mutable.ListBuffer(1,2,3,4)
// 追加元素
lBuffer += 5
println(lBuffer)
}
}

Set

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
/**
* Set
* Scala Set(集合)是没有重复的对象集合,所有的元素都是唯一的。Scala 集合分为可变的和不可变的集合。
* 默认情况下,Scala 使用的是不可变集合,如果你想使用可变集合,需要引用 scala.collection.mutable.Set包
*/
object TestSet {
def main(args: Array[String]): Unit = {
// 不可变Set
// 声明不可变Set
val s = Set(1,2,3)
// 添加元素,返回新的Set
val s1 = s.+(4)
println(s1)
// 连接集合,两种方式
var s2 = s ++ s1
var s3 = s.++(s1)
println(s3)
// 最大值,最小值
println(s3.max)
println(s3.min)
// 交集,两种方式
val num1 = Set(1,2,3,4)
val num2 = Set(3,6,9)
val num3 = num1.&(num2)
val num4 = num1.intersect(num2)
println(num4)
// 可变Set
// 声明可变Set
val set = scala.collection.mutable.Set(0,1,2)
// 添加元素
set.add(3)
set += 4
// 删除元素
set.remove(0)
set -= 1
println(set)
// 清除所有元素
set.clear()
println(set)
println(set.getClass.getName) // mutable
// 将可变集合转化为不可变集合
val set2 = set.toSet
println(set2.getClass.getName) // immutable
}
}

Map

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
/**
* Map
* Map有两种类型,可变与不可变,区别在于可变对象可以修改它,而不可变对象不可以。
* 默认情况下Scala使用不可变 Map。如果你需要使用可变集合,你需要显式的引入
* import scala.collection.mutable.Map类。在Scala中你可以同时使用可变与不可变Map,
* 不可变的直接使用Map,可变的使用mutable.Map。
*/
object TestMap {
def main(args: Array[String]): Unit = {
// 不可变Map
// 声明不可变Map
val map1 = Map(1 -> 1,2 -> 2)
val map11 = Map((1,1),(2,2),(3,3))
// 添加键值对
val map2 = map1 + (4->4)
println(map2)
// 基本操作
// 返回Map所有的键(key)
println(map2.keys)
// 返回Map所有的值(value)
println(map2.values)
// 在Map为空时返回true
println(map2.isEmpty)
// Map合并,两种方式
val map3 = map1 ++ map2
val map4 = map1.++(map2)
// 遍历输出Map的key和value,方式一
map3.keys.foreach{
i => println("key:"+i)
println("value:"+map3(i))
}
// 遍历输出Map的key和value,方式二
for((key,value) <- map3){
println("key:"+key+" ==> value:" + value);
}
// 查看map中是否有对应的key
if (map2.contains(2))
println("存在")
else
println("不存在")
// 可变Map
// 声明可变Map
val mapDyn = scala.collection.mutable.Map(1 -> "张三",2 -> "李四")
// 添加元素
mapDyn += (3 -> "王五")
mapDyn(4) = "赵六"
// 删除元素
mapDyn -= (1)
// 遍历k-v
for ((k,v) <- mapDyn) println("k:"+k+" v:"+v)
// Mapp排序
// SortedMap
val sortedScore = scala.collection.immutable.SortedMap("Scala"->7,"Hadoop"->10,"Spark"->12)
for ((k,v) <- sortedScore) println("k:"+k+" v:"+v)
}
}

Queue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
* Queue
* 队列
*/
object TestQueue {
def main(args: Array[String]): Unit = {
// 不可变队列
// 声明不可变队列
val queue = scala.collection.immutable.Queue(1,2,3)
// 添加元素,返回一个新的队列
val queue2 = queue.enqueue(List(1,2,3))
println(queue2)
// dequeue,将quenue2拆分成两部分:第一个元素,和剩下的一个元素组成Queue两部分
// 相当于先进先出,拿走一个元素
val (first,others) = queue2.dequeue
println(first+"|"+others)
// 可变队列
// 声明可变队列
val queue3 = scala.collection.mutable.Queue(1,2,3)
// 追加元素
queue3 += 4
// 追加集合
queue3 ++= List(5,6)
println(queue3)
// dequeue,可变的Queue只返回第一个元素,并且把第一个元素从Queue中删除
println(queue3.dequeue)
}
}

Stack

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* Stack
* 栈
*/
object TestStack {
def main(args: Array[String]): Unit = {
// 不可变栈
// 声明不可变栈
val stack = scala.collection.immutable.Stack(1,2,3)
println(stack)
// 入栈,往栈顶添加元素,返回新的对象
val stack2 = stack.push(4)
println(stack2)
// 可变栈
// 声明不可变栈
val stack3 = scala.collection.mutable.Stack(1,2,3)
// 入栈往栈顶添加元素
stack3.push(4)
println(stack3)
// 返回栈顶元素
println(stack3.top)
// 出栈,返回并删除栈顶元素
stack3.pop()
println(stack3)
}
}

Tree

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* TreeSet
* TreeMap
* 返回的结果都是已经排好序的
*/
object TestTree {
def main(args: Array[String]): Unit = {
// 不可变TreeSet
val treeSet = scala.collection.immutable.TreeSet(1,4,2,9,5,2,7)
// 添加元素,返回新的对象
val treeSet3 = treeSet + 50
println(treeSet3)
// 可变TreeSet
val treeSet2 = scala.collection.mutable.TreeSet(1,4,2,9,5,2,7)
// 添加元素
treeSet2 += 100
println(treeSet2)
// 不可变TreeMap
val treeMap = scala.collection.immutable.TreeMap("book" -> "ok","others" -> "no")
// 添加元素,返回新的对象
val treeMap3 = treeMap + ("food" -> "ok")
println(treeMap3)
// 可变TreeMap,不存在的
}
}

泛型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/**
* 泛型类、泛型函数
* 泛型用于指定方法或类可以接受任意类型参数
* 参数在实际使用时才被确定
* 泛型可以有效地增强程序的适用性
* 使用泛型可以使得类或方法具有更强的通用性
*/
object TestGeneric {
def main(args: Array[String]): Unit = {
// 泛型类
class GenericClass[F, S, T](val f: F, val s: S, val t: T)
// 实例化方式1:类型推导
val gc = new GenericClass("xj", 22, 'C')
// 实例化方式2:类型声明
val gc2 = new GenericClass[String, String, Int]("xj", "lj", 22)
// 泛型函数
def getData[T](list: List[T]) = list(list.length - 1)
println(getData(List('b', "bj", 26, 2.0)))
// 获得getData的引用,必须指定泛型类型
val t = getData[Int] _
println(t(List(1, 2, 3, 4, 5)))
// 类型变量界定
// 通过编译,为范型T增加了约束,限定上界为Comparable[T]
// 范型类型T也就具有了Comparable[T]中的compareTo(T)方法,类似于java中的继承
def typeVariable[T <: Comparable[T]](a: T, b: T) = {
if (a.compareTo(b) > 0)
1
else
-1
}
// 正确运行,String有上界Comparable[T]
println(typeVariable("a", "b"))
// Int类型运行错误,Int没有上界Comparable[T],但是为何编译不报错?
// 如果想成功运行的话,就需要进行一次隐式转换,
// 将Int类型转换成支持Comparable[T]的类型,此时应该改用视图界定<%
// 视图界定帮我们进行了隐式转换,将Int转换成了支持Comparable[T]的RichInt类型
// println(typeVariable(1,2))
// 视图界定
// <% 泛型视图界定符,表示把传入不是Comparable[T]类型的 隐式传换 为Comparable[T]类型
// a之所以能使用方法compareTo,是因为a被隐式传换为Comparable[T]类型
def viewBound[T <% Comparable[T]](a: T, b: T) = {
if (a.compareTo(b) > 0)
a
else
b
}
// Int类型被隐式转换成了支持Comparable[T]的RichInt类型
println(viewBound(1, 2))
// 上下文界定
class PairOrdering[T: Ordering](val first: T, val second: T) {
// compareTo方法进行比较,如果大于0返回first
def bigger(implicit ordered: Ordering[T]) = {
if (ordered.compare(first, second) > 0) first else second
}
}
// 函数调用
var pair = new PairOrdering("Spark", "Hadoop")
// 执行结果:Spark
println(pair.bigger)
// 多重界定
// 一个类型参数有多个类型约束,比如:
// T >: A <: B 表示T所允许的范围是A的父类 或者是B的子类
// T: A: B 表示作用域必须同时满足存在A[T]和B[T]隐式值
// T <% A <% B表示作用域必须同时满足T到A和T到B的隐式转换
class Animal{
def speak():Unit={
println("666")
}
}
class Person extends Animal{}
class Student extends Person{}
def showAll[T >: Person <: Person](str:T) ={
str.speak()
}
// Manifest关键字
// 数组在声明时必须要求指定具体的类型,在函数泛型是无法知道具体类型,
// 通过Manifest关键字使得运行时可以根据这个Manifest参数做更多的事情
def arrayMake[T: Manifest](first: T, second: T) = {
val r = new Array[T](2);
r(0) = first;
r(1) = second;
// 返回r
r;
}
// val array = arrayMake("a","b")
// for (i <- array) println(i)
arrayMake("a","b").foreach(println)
// ClassTag关键字
// ClassTag[T]保存了泛型擦除后的原始类型T,提供给被运行时的
def mkArray[T:ClassTag](elems:T*) = Array[T](elems:_*)
mkArray(42,13).foreach(println)
mkArray("Japan","Brazil","Germany").foreach(println)
// 类型约束
// 类型约束提供给你的是另外一个限定类型的方式,总共有三种关系可供使用
// T =:= U 表示测试T 是否等于U类型
// T <:< U 表示测试T 是否为U的子类型
// T <%< U 表示是否存在T到U 的转换
// 协变,逆变
// 协变[+T]
// 只有满足指定类型或者指定类型子类才可以被兼容,即使是指定类型的父类也不会被兼容,
// 通俗地讲,只要是你或者你的子类我都可以编译通过
// 逆变[-T]
// 只有满足指定类型或者指定类型父类才可以被兼容,即使是指定类型的子类也不会被兼容
// 通俗地讲,只要是你或者你的父类我都可以编译通过
}
}

最后更新: 2018年10月08日 18:25

原始链接: https://www.lousenjay.top/2018/10/07/Scala入门详解(三)/