scala集合与数据结构

1、数据结构特点

Scala同时支持可变集合和不可变集合,不可变集合从不可变,可以安全的并发访问。

两个主要的包:

不可变集合:scala.collection.immutable

可变集合: scala.collection.mutable

Scala优先采用不可变集合,对于几乎所有的集合类,Scala都同时提供了可变和不可变的版本。

不可变集合继承层次:

可变集合继承层次:

2、数组

2.1、定义定长数组

我们可以定义一个固定长度大小和类型的定长数组


//定义一个数组长度为10,类型为Int的固定大小数组

val array = new Array[Int](10)

array(1) = 10

array(2) = 20

//访问数组当中的某一个下标元素值

println(array(1))

//直接使用apply方法进行生成一个数组

val array2 = Array(1,2,3)

//访问数组的元素

println(array2(2))

2.2、变长数组

我们也可以通过ArrayBuffer来定义一个变长数组


val array3 = new ArrayBuffer[Int]()

array3.append(20)

val array4 =  ArrayBuffer[String]()

array4.append("helloworld")

2.3、定长数组与变长数组的相互转换


//定长数组转换成变长数组

val toBuffer = array.toBuffer

toBuffer.append(50)

//变长数组准换成定长数组

val toArray = array3.toArray

2.4、多维数组

我们可以通过Array的ofDim方法来定义一个多维的数组,多少行,多少列,都是我们自己定义说了算


val dim = Array.ofDim[Double](3,4)

dim(1)(1) = 11.11

println(dim.mkString(","))

2.5、scala当中数组的遍历


val array5 = ArrayBuffer(1,2,3,4,5,6)

for(x <- array5){

println(x )

}

2.6、数组的常见算法


val array6 = Array(1,2,3,4,5,6)

//求和

array6.sum

//求最大值

array6.max

//排序

array6.sorted

3、元组tuple

在scala当中提供元组tuple的数据类型,可以理解tuple为一个容器,可以存放各种不同的数据类型的数据,例如一个Tuple当中既可以存放String类型数据,同时也可以存放Int类型的数据

注意:注意元组一旦创建之后,就是不可变的,也就是说元组当中没有添加和删除元素这一说

3.1、创建元组

创建元组,直接使用小括号,小括号当中存放我们元组当中各种类型的元素即可


val tuple1 = ("hello",1,5.0f)

println(tuple1)

3.2、元组数据的访问

访问元组当中的数据直接使用_加角标即可,但是要注意,元组当中的数据角标是从1开始的


val tuple1 = ("hello",1,5.0f)

println(tuple1)

val tuple1Result = tuple1._1

println(tuple1Result)

3.3、元组的遍历


val tuple1 = ("hello",1,5.0f)

println(tuple1)

val tuple1Result = tuple1._1

println(tuple1Result)

//第一种方式遍历元组


for(x <- tuple1.productIterator){

println(x)

}

//第二种方式遍历元组

tuple1.productIterator.foreach( x => println(x))

4、映射Map

scala当中的Map集合与java当中的Map类似,也是key,value对形式的

4.1、不可变映射


val map1 = Map("hello" ->"world","name" -> "zhangsan","age" -> 18)

4.2、可变映射及其操作


val map2 = scala.collection.mutable.Map("hello" ->"world","name" -> "zhangsan","age" -> 18)

//可变map添加元素

map2.+=("address" ->"地球")

println(map2)

//可变map删除元素.注意,删除元素是返回一个删除元素之后的map,原来的map并没有改变

val map3 = map2.-("address")

println(map2)

println(map3)

//可变map更新元素

map2("address") ="火星"

println(map2)

//或者使用覆盖key的方式来更细元素

map2 += ("address" -> "北京")

println(map2)

//或者使用 + 来进行更新元素

//注意,map当中没有phonNo这个key,则不能更细

map2 +("address" ->"上海","phonNo" -> "13688886666")

println(map2)

4.3、获取map当中指定的key值


//通过key来进行取值

map2.get("address")

//通过key来进行取值,如果没有这个key,就用后面给定的默认值

map2.getOrElse("address","非洲")

//通过key来进行取值,真的没有这个key,那么就用后面给定的默认值

map2.getOrElse("phoNo","13133335555")

4.4、遍历Map当中的元素


//遍历key与value

for((k,v) <- map2){

println(k)

println(v)

}

//遍历获取所有的key

for(k <- map2.keys) {

println(k)

}

//遍历获取所有的value

for(v <- map2.values) {

println(v)

}

//打印key,value对

for(kv <- map2){

println(kv)

}

4.5、将对偶的数组转变为map


//将对偶的元组转变为map

val arrayMap = Array(("name","zhangsan"),("age",28))

val toMap = arrayMap.toMap

println(toMap)

5、列表(List)

scala当中也提供有与java类似的List集合操作

5.1、创建列表

注意:列表当中的元素类型可以是不同的,这一点与我们元组类似,但是列表当中的元素是可以删减的


val list1 = List("hello",20,5.0f)

println(list1)

5.2、访问列表当中的元素


//访问列表当中的元素

val list1Result = list1(0)

println(list1Result)

5.3、列表当中添加元素

我们可以从列表头部或者尾部添加元素


val list2 = list1:+50

val list3 = 100+:list1

println(list2)

println(list3)

5.4、List的创建与追加元素

Nil是一个空的List,定义为List[Nothing]


//尾部添加了Nil,那么就会出现List集合里面装List集合的现象

val list4 = 1::2 ::3 :: list1 ::Nil

println(list4)

//尾部没有添加Nil的值,那么所有的元素都压平到一个集合里面去了

val list5 = 1::2::3::list1

println(list5)

5.5、变长List的创建与使用


val list6 = new ListBuffer[String]

list6.append("hello")

list6.append("world")

println(list6.mkString(","))

val list7 = list6.toList

println(list7)

5.6、List操作延伸阅读

Scala是函数式风格与面向对象共存的编程语言,方法不应该有副作用是函数风格编程的一个重要的理念。方法唯一的效果应该是计算并返回值,用这种方式工作的好处就是方法之间很少纠缠在一起,因此就更加可靠和可重用。另一个好处(静态类型语言)是传入传出方法的所有东西都被类型检查器检查,因此逻辑错误会更有可能把自己表现为类型错误。把这个函数式编程的哲学应用到对象世界里以为着使对象不可变。

前面一章介绍的Array数组是一个所有对象都共享相同类型的可变序列。比方说Array[String]仅包含String。尽管实例化之后你无法改变Array的长度。因此,Array是可变的对象。

说到共享相同类型的不可变对象类型,Scala的List类才是。和数组一样,List[String]包含的仅仅是String。Scala的List不同于Java的java.util.List,总是不可变的(Java的List是可变)。更准确的说法,Scala的List是设计给函数式风格的编程用的。

(1)List类型定义以及List的特点:


//字符串类型List

scala> val fruit=List("Apple","Banana","Orange")

fruit: List[String] = List(Apple, Banana, Orange)

//前一个语句与下面语句等同

scala> val fruit=List.apply("Apple","Banana","Orange")

fruit: List[String] = List(Apple, Banana, Orange)

//数值类型List

scala> val nums=List(1,2,3,4,5)

nums: List[Int] = List(1, 2, 3, 4, 5)

//多重List,List的子元素为List

scala> val list = List(List(1, 2, 3), List("adfa", "asdfa", "asdf"))

list: List[List[Any]] = List(List(1, 2, 3), List(adfa, asdfa, asdf))

//遍历List

scala> for(i <- list; from=i; j<-from)println(j)

1

2

3

adfa

asdfa

asdf

(2)List与Array的区别:

1、List一旦创建,已有元素的值不能改变,可以使用添加元素或删除元素生成一个新的集合返回。

如前面的nums,改变其值的话,编译器就会报错。而Array就可以成功


scala>nums(3)=4

<console>:10: error: value update is not a member of List[Int]

nums(3)=4

^

2、List具有递归结构(Recursive Structure),例如链表结构

List类型和气他类型集合一样,它具有协变性(Covariant),即对于类型S和T,如果S是T的子类型,则List[S]也是List[T]的子类型。

例如:


scala>var listStr:List[Object] = List("This", "Is", "Covariant", "Example")

listStr:List[Object] = List(This, Is, Covariant, Example)

//空的List,其类行为Nothing,Nothing在Scala的继承层次中的最底层

//,即Nothing是任何Scala其它类型如String,Object等的子类

scala> var listStr = List()

listStr:List[Nothing] = List()

scala>var listStr:List[String] = List()

listStr:List[String] = List()

(3)List常用构造方法


//1、常用::及Nil进行列表构建

scala> val nums = 1 :: (2:: (3:: (4 :: Nil)))

nums: List[Int] = List(1, 2, 3, 4)

//由于::操作符的优先级是从右向左的,因此上一条语句等同于下面这条语句

scala> val nums = 1::2::3::4::Nil

nums:List[Int] = List(1, 2, 3, 4)

至于::操作符的使用将在下面介绍

(4)List常用操作


//判断是否为空

scala> nums.isEmpty

res5: Boolean = false

//取第一个元素

scala> nums.head

res6: Int = 1

//取列表第二个元素

scala>nums.tail.head

res7: Int = 2

//取第三个元素

scala>nums.tail.tail.head

res8: Int = 3

//插入操作

//在第二个位置插入一个元素

scala>nums.head::(3::nums.tail)

res11: List[Int] = List(1, 3, 2, 3, 4)

scala> nums.head::(nums.tail.head::(4::nums.tail.tail))

res12: List[Int] = List(1, 2, 4, 3, 4)

//插入排序算法实现

def isort(xs: List[Int]):List[Int] = {

if(xs.isEmpty) Nil

else insert(xs.head, issort(xs.tail))

}

def insert(x:Int, xs:List[Int]):List[Int] = {

if(xs.isEmpty || x <= xs.head) x::xs

else xs.head :: insert(x, xs.tail)

}

//连接操作

scala>List(1, 2, 3):::List(4, 5, 6)

res13: List[Int] = List(1, 2, 3, 4, 5, 6)

//去除最后一个元素外的元素,返回的是列表

scala> nums.init

res13: List[Int] = List(1, 2, 3)

//取出列表最后一个元素

scala>nums.last

res14: Int = 4

//列表元素倒置

scala> nums.reverse

res15: List[Int] = List(4, 3, 2, 1)

//一些好玩的方法调用

scala> nums.reverse.reverse == nums

//丢弃前面n个元素

scala>nums drop 3

res16: List[Int] = List(4)

//获取前面n个元素

scala>nums take 1

res17: List[Int] = List[1]

//将列表进行分割

scala> nums.splitAt(2)

res18: (List[Int], List[Int]) = (List(1, 2),List(3, 4))

//前一个操作与下列语句等同

scala> (nums.take(2),nums.drop(2))

res19: (List[Int], List[Int]) = (List(1, 2),List(3, 4))

//Zip操作

scala> val nums=List(1,2,3,4)

nums: List[Int] = List(1, 2, 3, 4)

scala> val chars=List(‘1‘,‘2‘,‘3‘,‘4‘)

chars: List[Char] = List(1, 2, 3, 4)

//返回的是List类型的元组(Tuple),返回的元素个数与最小的List集合的元素个数一样

scala> nums zip chars

res20: List[(Int, Char)] = List((1,1), (2,2), (3,3), (4,4))

//List toString方法

scala> nums.toString

res21: String = List(1, 2, 3, 4)

//List mkString方法

scala> nums.mkString

res22: String = 1234

//转换成数组

scala> nums.toArray

res23: Array[Int] = Array(1, 2, 3, 4)

(5)List伴生对象方法


//apply方法

scala> List.apply(1, 2, 3)

res24: List[Int] = List(1, 2, 3)

//range方法,构建某一值范围内的List

scala> List.range(2, 6)

res25: List[Int] = List(2, 3, 4, 5)

//步长为2

scala> List.range(2, 6,2)

res26: List[Int] = List(2, 4)

//步长为-1

scala> List.range(2, 6,-1)

res27: List[Int] = List()

scala> List.range(6,2 ,-1)

res28: List[Int] = List(6, 5, 4, 3)

//构建相同元素的List

scala> List.make(5, "hey")

res29: List[String] = List(hey, hey, hey, hey, hey)

//unzip方法

scala> List.unzip(res20)

res30: (List[Int], List[Char]) = (List(1, 2, 3, 4),List(1, 2, 3, 4))

//list.flatten,将列表平滑成第一个无素

scala> val xss =List(List(‘a‘, ‘b‘), List(‘c‘), List(‘d‘, ‘e‘))

xss: List[List[Char]] = List(List(a, b), List(c), List(d, e))

scala> xss.flatten

res31: List[Char] = List(a, b, c, d, e)

//列表连接

scala> List.concat(List(‘a‘, ‘b‘), List(‘c‘))

res32: List[Char] = List(a, b, c)

(6)::和:::操作符介绍

List中常用‘::‘,发音为"cons"。Cons把一个新元素组合到已有元素的最前端,然后返回结果List。


scala> val twoThree = List(2, 3)

scala> val oneTwoThree = 1 :: twoThree

scala> oneTwoThree

oneTwoThree: List[Int] = List(1, 2, 3)

上面表达式"1::twoThree"中,::是右操作数,列表twoThree的方法。可能会有疑惑。表达式怎么是右边参数的方法,这是Scala语言的一个例外的情况:如果一个方法操作符标注,如a * b,那么方法被左操作数调用,就像a.* (b)--除非方法名以冒号结尾。这种情况下,方法被右操作数调用。

List有个方法叫":::",用于实现叠加两个列表。


scala> val one = List(‘A‘, ‘B‘)

val one = List(‘A‘, ‘B‘)

scala> val two = List(‘C‘, ‘D‘)

scala> one:::two

res1: List[Char] = List(A, B, C, D)

6、Set集合

集是不重复元素的结合。集不保留顺序,默认是以哈希集实现。

如果想要按照已排序的顺序来访问集中的元素,可以使用SortedSet(已排序数据集),已排序的数据集是用红黑树实现的。

默认情况下,Scala 使用的是不可变集合,如果你想使用可变集合,需要引用 scala.collection.mutable.Set 包。

6.1、不可变集合的创建


val set1 =Set("1","1","2","3")

println(set1.mkString(","))

6.2、可变集合的创建以及添加元素

如果我们引入的集合的包是可变的,那么我们创建的集合就是可变的


import scala.collection.mutable.Set

val set2 = Set(1, 2, 3)

set2.add(4)

set2 += 5

//使用.这个方法添加元素,会返回一个新的集合

val set3 = set2.+(6)

println(set2.mkString(","))

println(set3.mkString("\001"))

6.3、可变集合删除元素


set3 -= 1

println(set3.mkString("."))

set3.remove(2)

println(set3.mkString("."))

6.4、遍历Set集合元素


for(x <- set3){

println(x )

}

注意:如果要创建有序的set,那么需要使用SortedSet。用法与Set类似

更多Set集合操作参见如下:

http://www.runoob.com/scala/scala-sets.html

6.5、Set更多常用操作介绍


序号


方法


描述


1


def +(elem: A): Set[A]


为集合添加新元素,并创建一个新的集合,除非元素已存在


2


def -(elem: A): Set[A]


移除集合中的元素,并创建一个新的集合


3


def contains(elem: A): Boolean


如果元素在集合中存在,返回 true,否则返回 false。


4


def &(that: Set[A]): Set[A]


返回两个集合的交集


5


def &~(that: Set[A]): Set[A]


返回两个集合的差集


6


def ++(elems: A): Set[A]


合并两个集合


7


def drop(n: Int): Set[A]]


返回丢弃前n个元素新集合


8


def dropRight(n: Int): Set[A]


返回丢弃最后n个元素新集合


9


def dropWhile(p: (A) => Boolean): Set[A]


从左向右丢弃元素,直到条件p不成立


10


def max: A


查找最大元素


11


def min: A


查找最小元素


12


def take(n: Int): Set[A]


返回前 n 个元素

7、集合元素与函数的映射

我们可以使用map方法,传入一个函数,然后将这个函数作用在集合当中的每一个元素上面

map:将集合中的每一个元素映射到某一个函数


val listFunc = List("name","age","zhangsan","lisi")

println(listFunc.map(x => x +"hello"))

println(listFunc.map(_.toUpperCase()))

flatmap:flat即压扁,压平,扁平化,效果就是将集合中的每个元素的子元素映射到某个函数并返回新的集合


val listFunc2 = List("address","phonNo")

println(listFunc2.flatMap( x => x +"WORLD"))

8、队列Queue

队列Queue是一个先进先出的结构

8.1、创建队列


//创建可变的队列

val queue1 = new mutable.Queue[Int]()

println(queue1)

8.2、队列当中添加元素


//队列当中添加元素

queue1 += 1

//队列当中添加List

queue1 ++=List(2,3,4)

println(queue1)

8.3、按照进入队列顺序,删除队列当中的元素(弹出队列)


val dequeue = queue1.dequeue()

println(dequeue)

println(queue1)

8.4、向队列当中加入元素(入队列操作)


//塞入元素到队列

queue1.enqueue(5,6,7)

println(queue1)

8.5、获取第一个与最后一个元素


//获取第一个元素

println(queue1.head)

//获取最后一个元素

println(queue1.last)

9、集合当中的化简、折叠与扫描操作

9.1、折叠、化简 reduce操作

将二元函数引用集合当中的函数


val reduceList = List(1,2,3,4,5)

//1-2-3-4-5 = -13

val reduceLeftList = reduceList.reduceLeft(_ - _)

val reduceLeftList2 = reduceList.reduceLeft((x,y) => x-y)

println(reduceLeftList)

println(reduceLeftList2)

//reduceRight操作

// 4-5 = -1

// 3- (-1) = 4

//2-4 = -2

//1 -(-2) = 3

val reduceRightList = reduceList.reduceRight(_ - _)

println(reduceRightList)

9.2、折叠、化简folder操作

fold函数将上一步返回的值作为函数的第一个参数继续传递参与运算,直到list中的所有元素被遍历。可以把reduceLeft看做简化版的foldLeft。相关函数:fold,foldLeft,foldRight,可以参考reduce的相关方法理解。

reduce的本质其实就是fold操作,只不过我们使用fold操作的时候,需要指定初始值fold操作


val foldList = List(1,9,2,8)

val foldResult = foldList.fold(10)((x,y) => x+y)

println(foldResult)

foldLeft操作

//50-1-9-2-8 = 30

val foldLeftResult = foldList.foldLeft(50)((x,y) => x-y)

println(foldLeftResult)

10、拉链操作

对于多个List集合,我们可以使用Zip操作,将多个集合当中的值绑定到一起去


val zipList1 = List("name","age","sex")

val zipList2 = List("zhangsan",28)

val zip = zipList1.zip(zipList2)

val toMap1 = zip.toMap

println(zip)

println(toMap1)

11、迭代器

对于集合当中的元素,我们也可以使用迭代器来进行遍历


val listIterator = List(1,2,"zhangsan")

val iterator = listIterator.iterator

while(iterator.hasNext){

println(iterator.next())

}

12、线程安全的集合

scala当中为了解决多线程并发的问题,提供对应的线程安全的集合

https://www.scala-lang.org/api/2.11.8/#package

SynchronizedBuffer

SynchronizedMap

SynchronizedPriorityQueue

SynchronizedQueue

SynchronizedSet

13、操作符

大致了解即可

  1. 如果想在变量名、类名等定义中使用语法关键字(保留字),可以配合反引号反引号:

    var `var` num:Int = 2

2) 这种形式叫中置操作符,A操作符B等同于A.操作符(B)

3) 后置操作符,A操作符等同于A.操作符,如果操作符定义的时候不带()则调用时不能加括号

4) 前置操作符,+、-、!、~等操作符A等同于A.unary_操作符。

5) 赋值操作符,A操作符=B等同于A=A操作符B

原文地址:https://www.cnblogs.com/starzy/p/10466494.html

时间: 2024-10-31 02:36:19

scala集合与数据结构的相关文章

集合结合数据结构来看看

一.先来唠一唠?     上一篇泛型适宜本意还想继续往下写写,来一下协变与逆变,奈何不知道怎么该往下写,等等我思考一下,在继续写~接下来聊聊数据结构这一话题,想到数据结构就想起了那一年我在工院上课就睡觉的时光,真实暴遣天物呀,不扯开始话题,数据结构可能在我们工作的时候用的不算太多,但是实际上不管java或者C#都将这些封装到我们常用的类里面,就比如说集合就是数据结构的真实写照~ 二.数组先来扯一扯?     数组不算是集合,但是还是想用来他的东西来说明数据结构的一些东西,不算是偏题哈~我们都知道

不相交集合的数据结构

不相交集合的数据结构 本来想着来实现基于贪婪思想的Kruskal算法-–最小生成树的算法之一. 却发现当我们合并集合时里面还涉及到一个判断"环"的问题,继而有了本篇博文:不相交集合的数据结构. 关于不相交集合的数据结构,这里作一个简单的介绍,更多的可看这里 第一:我们假设我们有n个不相交的集合{Si},i=1~n:其中每个集合中都有一个"代表元素"(这个"代表元素"你可以理解为我们班级中的"班长",对外"班长&quo

算法导论 第二十一章:不相交集合的数据结构

不相交集合(Disjoint-set )数据结构保持一组不相交的动态集合S={S(1),S(2),...,S(k)}.每个集合通过一个代表(representative)来识别,即集合中的某个成员.设x表示一个对象,不相交集合支持操作: MAKE-SET(x):建立一个新的结合,其唯一成员(也即代表)就是x.因为各集合是不相交的,故要求x没有在其他集合中出现过. UNION(x,y):将包含x和y的动态集合合并成一个新的集合(即这两个集合的并集).假定在这个操作之前两个集合是不相交的,操作之后,

scala集合类型与java的转换

scala集合与java集合类型相互转换: http://www.scala-lang.org/api/current/index.html#scala.collection.JavaConverters$ 您可以通过JavaConverters package轻松地在Java和Scala的集合类型之间转换.它用asScala 装饰常用的Java集合以和用asJava 方法装饰Scala集合.    import scala.collection.JavaConverters._    val 

Spark:scala集合转化为DS/DF

scala集合转化为DS/DF 1 case class TestPerson(name: String, age: Long, salary: Double) 2 val tom = TestPerson("Tom Hanks",37,35.5) 3 val sam = TestPerson("Sam Smith",40,40.5) 4 val PersonList = mutable.MutableList[TestPerson]() 5 PersonList

Scala集合笔记

Scala的集合框架类比Java提供了更多的一些方便的api,使得使用scala编程时代码变得非常精简,尤其是在Spark中,很多功能都是由scala的这些api构成的,所以,了解这些方法的使用,将更加有助于我们学习Scala和Spark: List,Map,Set的一些api的用法如下:  Java代码   /** * Scala 集合测试 */ def collectionTest(): Unit ={ val map =Map("red"->"红色",&

再谈Scala集合

集合!集合!一个现代语言平台上的程序员每天代码里用的最多的大概就是该语言上的集合类了,Scala的集合丰富而强大,至今无出其右者,所以这次再回过头再梳理一下. 本文原文出处:  还是先上张图吧,这是我找到的最好的一个关于Scala集合的图了,出自:http://lkumarjain.blogspot.co.id/2015/01/scala-collection-framework.html : 一致的构建风格 在Scala里我们使用一致的简洁的语法实例化一个集合,不管你使用的是一个Trait还是

Scala集合类型详解

Scala集合 Scala提供了一套很好的集合实现,提供了一些集合类型的抽象. Scala 集合分为可变的和不可变的集合. 可变集合可以在适当的地方被更新或扩展.这意味着你可以修改,添加,移除一个集合的元素.而不可变集合类永远不会改变.不过,你仍然可以模拟添加,移除或更新操作.但是这些操作将在每一种情况下都返回一个新的集合,同时使原来的集合不发生改变. 集合中基本结构: 几种常用集合类型示例: // 定义整型 List   val x = List(1, 2, 3, 4)     // 定义 S

Scala集合学习总结

遍历集合可以使用迭代器iterator的那套迭代方式.Seq是一个有先后次序的序列,比如数组或列表.IndexedSeq可以通过下标进行任意元素的访问.例如ArrrayBuffer. Set是一组没有先后次序的值,在SortedSet中,元素以某种排过序的顺序被访问. Map是一组(键,值)对偶,SortedMap按照键的顺序访问实体 Scala集合有三个基本操作: head 返回集合第一个元素 tail 返回一个集合,包含除了第一元素之外的其他元素 isEmpty 在集合为空时返回true 可