【scala专栏_持续更新】20_scala数组+元组

【大纲】
【scala专栏_持续更新】20_scala数组+元组

【正文】

1.数组

1.1.概念

数组是用来存储多个相同类型元素的容器,每个元素都有编号 = 下标 = 脚标 = 索引,索引都是从1开始的

scala中有2种数组,定长数组和变长数组

1.2.分类

1.2.1.Array

1.2.1.1.特点

定长数组Array的长度不允许变、元素值可变、元素可重复、存取有序

1.2.1.2.定义语法

0.指定长度定义空数组
    val/var a = new Array[元素类型](数组长度) # 效果:每个元素被初始化为默认值
    
1.指定元素定义数组
    val/var a = Array(8, 9, 1) # 注意:元素类型可省略,会自动推断。# 注意:第一个元素就是head元素,后边的所有元素就是tail列表。最后一个元素就是last元素,前边所有的元素就是init元素

示例

# Array 定义
object Array1 {
  def main(args: Array[String]): Unit = {
    
    val a = new Array[Int](10)
    println(a) // 效果:[I@23223dd8
    println(a.getClass) // 效果:class [I

    val b = Array("java", "scala", "python")
    println(b) // 效果:[Ljava.lang.String;@4ec6a292
    println(b.getClass) // 效果:class [Ljava.lang.String;

  }
}

1.2.2.ArrayBuffer

1.2.2.1.特点

变长数组ArrayBuffer的长度和元素值都可变,元素可重复、存取有序

1.2.2.2.定义语法

0.定义空数组
    import scala.collection.mutable.ArrayBuffer
    val/var ab = ArrayBuffer[数据类型]() # 注意: 此时默认数组长度为0,无元素值,还不能用索引操作

1.指定元素定义数组
    import scala.collection.mutable.ArrayBuffer
    val/var ab = ArrayBuffer(7, 3, 5) # 注意:元素类型可省略,会自动推断。# 注意:第一个元素就是head元素,后边的所有元素就是tail列表。最后一个元素就是last元素,前边所有的元素就是init元素

示例

# ArrayBuffer 定义
object ArrayBuffer1 {
  def main(args: Array[String]): Unit = {
    // 定义空数组
    val ab = new ArrayBuffer[Int]()
    println(ab) // 效果:ArrayBuffer()

    // 指定元素定义数组
    val ab2 = ArrayBuffer("java", "scala", "pathon")
    println(ab2) // 效果:ArrayBuffer(java, scala, pathon)
  }
}

1.2.2.3.可变数组集合通用API

# 注意:数组、列表、集、映射通用
0.+=向末尾添加多个元素 
    对象 += 新元素
    
    对象 += (新元素1, 新元素2) 
    
    对象.append(新元素) / 
    Set对象.add(新元素) / 
    Map对象.put(key, value) / 
    Map对象(key) = value
    
    对象.append(新元素1, 新元素2) # 注意:Set无、Map无
    
1.‐=删除多个元素 
    对象 ‐= 旧元素 / 
    Map对象 -= 旧key
    
    对象 ‐= (旧元素1, 旧元素2) / 
    Map对象 -= (旧key1, 旧key2)
        
2.++=拼接
    对象A ++= 对象B # 注意:对象B可以是数组、列表、集 # 注意:但A是Map时B只能是Map
      
3.‐‐=裁剪 
    对象A ‐‐= 对象B # 注意:对象B可以是数组、列表、集

4.向指定索引添加多个元素 
    对象.insert(索引, 新元素1, 新元素2) 
    
    # 注意:Set无索引、Map无索引

5.按索引删除元素 
    val 被删掉的元素 = 对象.remove(索引) / 
    val 被删掉的元素 = Set对象.remove(旧元素) / 
    val 被删掉的key的value = Map对象.remove(旧key) # 注意:返回值Some类型
    
6.从指定索引开始删除多个元素 
    对象.remove(startIndex, count) # 注意:返回值Unit 
    
    # 注意:Set无、Map无
    
7.清空所有元素
    对象.clear

示例

# ArrayBuffer 增删改
object ArrayBuffer1 {
  def main(args: Array[String]): Unit = {
    val ab = ArrayBuffer("hadoop", "spark", "flink")

    ab += "flume"
    println(ab) // 效果:ArrayBuffer(hadoop, spark, flink, flume)

    ab -= "hadoop"
    println(ab) // 效果:ArrayBuffer(spark, flink, flume)

    ab ++= Array("hive", "sqoop")
    println(ab) // 效果:ArrayBuffer(spark, flink, flume, hive, sqoop)

    ab --= Array("sqoop", "spark")
    println(ab) // 效果:ArrayBuffer(flink, flume, hive)
    
    val a = ArrayBuffer(4, 1, 6, 5, 2, 3)
    a.insert(2, 0, 0, 0)
    println(a) // 效果: ArrayBuffer(4, 1, 0, 0, 0, 6, 5, 2, 3)
    
    val removeValue = a.remove(2)
    println(removeValue) // 效果:0
    println(a) // 效果:ArrayBuffer(4, 1, 0, 0, 6, 5, 2, 3)
    
    a.remove(2, 4)
    println(a) // 效果:ArrayBuffer(4, 1, 2, 3)
  }
}

1.3.数组集合通用API

# 注意:数组、列表、集、映射通用
0.按索引访问元素
    val a = 对象(索引) / 
    val a = Map对象.get(key) # 效果:key不存在,返回None / 
    val a = Map对象.getOrElse(key, value默认值) # 效果:如果key不存在,默认值将作为value返回 / 
    val a = Map对象(key) # 效果:key不存在会报错
    
    或
    
    val a = 对象.apply(索引) /
    val value = Map对象.apply(key)
    
    # 注意:Set无
    
1.按索引修改元素,返回新对象
    对象(索引) = 新元素 
    
    # 注意:immutable.List无 
    
    # 注意:Set无、Map无
    
    或
    
    val 新对象 = 对象.updated(索引, 新元素) /
    val 新对象 = Map对象.updated(key, 新value)
    
    # 注意:Set无
    
2.子序列替换,返回新对象
    val b = 对象.patch(被替换的起始索引i, 新子序列对象a, 替换掉n个元素) #效果:从索引i开始,用子序列a替换n个元素
    
    # 注意:Set无、Map无

3.判断是否为空
    val boolean = 对象.isEmpty

4.判断是否包含
    val boolean = 对象.contains(指定元素) / val boolean = Map对象.contains(key)
    
    或
    
    val boolean = Set对象.apply(指定元素)
    
5.判断是否相同
    判断元素是否相等
        对象A == 对象B
        
    判断地址值是否相等
        对象A eq 对象B
        
    判断元素内容全部相同且迭代顺序相同
        val Boolean = 对象A.sameElements(对象B)
    
6.获取长度
    val l = 对象.size
    
    val l = 对象.length # 注意:Set无、Map无
    
7.遍历
    方式一 iterator 推荐
        val a = List(1,2,3)
        val it = a.iterator
        while(it.hasNext){
          val b = it.next()
          println(b)
        }

    方式二 foreach 推荐
        对象.foreach{x => 对元素x的处理}
        
    方式三 for
        for(元素 <‐ 对象)println(元素) 
    
    方式四 for + to
        for(索引 <‐ 0 to 对象.length ‐ 1)println(对象(索引)) 
    
    方式五 for + until
        for(索引 <‐ 0 until 对象.length)println(对象(索引))

8.分组遍历
    val a = List(1,2,3,4,5)
    val it = a.grouped(2) // 2个元素放一组进行分组,返回个Iterator
    while(it.hasNext){
      println(it.next()) // 效果:List(1, 2) List(3, 4) List(5)
    }
    
9.获取head元素 
    val a = 对象.head
    
    val a = 对象.headOption // 注意:返回值是Option类型
    
10.获取tail列表
    val a = 对象.tail
    
11.获取last元素
    val a = 对象.last
    
    val a = 对象.lastOption // 注意:返回值是Option类型
    
12.获取init列表 
    val a = 对象.init
    
13.获取第2个元素 
    val secondValue = 对象.tail.head
    
14.获取前n个元素,返回新对象 
    val l = 对象.take(元素个数)
    
15.丢弃前n个元素,剩余元素以新对象返回 
    val l = 对象.drop(n)

16.按索引截取部分,返回新对象
    val a = 对象.slice(起始索引, 截止索引) # 注意:[起始索引, 截至索引)
    
17.获取第一个满足条件的元素,返回Option
    val a = 对象.find(x => x % 2 == 0)
    
18.获取指定元素第一次出现的索引
    val index = 对象.indexOf(指定元素)
    
    # 注意:Set无、Map无
    
19.获取指定元素最后一次出现的索引
    cal index = 对象.lastIndexOf(指定元素)
    
20.根据条件获取指定元素第一次出现的索引
    val b = a.indexWhere(x => x < 5 && x % 2 ==0)
    
    val b = a.indexWhere(x => x < 5 && x % 2 ==0, 起始索引) # 效果:从起始索引开始向后找
    
    # 注意:Set无、Map无
    
21.根据条件获取指定元素最后一次出现的索引
    val b = 对象.lastIndexWhere(x => x < 7 && x % 2 ==0)
    
    val c = 对象.lastIndexWhere(x => x % 2 == 0, 终止索引) # 效果:从0索引开始找到终止索引为止
    
    # 注意:Set无、Map无
    
22.获取子序列第一次出现的索引
    val d = 对象.indexOfSlice(子序列对象)
    
    val d = a.indexOfSlice(Seq(4,6), 起始索引) # 效果:从起始索引开始向后找
    
    # 注意:Set无、Map无

23.是否以指定子序列开头
    val a = 对象.startsWith(子序列对象)

    # 注意:Set无、Map无
    
24.是否以指定子序列结尾
    val b = 对象.endsWith(子序列对象)
    
     # 注意:Set无、Map无

25.是否包含指定元素
    val boolean = 对象.contains(指定元素) /
    val value = 对象.contains(key)

26.是否包含指定子序列
    val b = 对象.containsSlice(子序列对象)
    
    # 注意:Set无、Map无
    
27.向头部添加元素,返回新对象 (不用)
    val a = 1 +: 数据类型(2,3,4) # 推荐
    
    val a = 数据类型(2,3,4).+:(1) # 注意:+:符号Set无、Map无
    
    val a = 1 :: List(2,3,4) # 注意:::符号只有List有
    val a = List(2,3,4).::(1) # 注意:::符号只有List有
    val a = 1 :: 2 :: 3 :: Nil # 注意:::符号只有List有 # 效果:向List头部连续添加元素
    
28.向尾部添加元素,返回新对象 (不用) 
    val a = 数据类型(3,6,7) :+ 2 
    
    # 注意:Set无、Map无
    
29.获取各元素的和(元素必须是数字类型)
    val a = 对象.sum 
    
    # 注意:Map?

30.获取各元素的乘积(元素必须是数字类型)
    val a = 对象.product

31.获取元素最大值
    val a = 对象.max # 效果:Map先看key,key相同再比较value

32.获取元素最小值
    val a = 对象.min # 效果:Map先看key,key相同再比较value
    
33.计算满足指定条件的元素的个数
    val a = 对象.count(x => x % 2 == 0)

34.判断元素是否满足指定条件
    val Boolean = 对象.forall(x => x % 2 ==0) // 效果:所有元素都是偶数才返回true
    
    val Boolean = 对象.exists(x => x % 2 ==0) // 效果:有一个元素是偶数就返回true

35.反转,返回新对象 
    val a = 对象.reverse # 注意:Set无、Map无
    
36.升序排序,返回新对象
    val a = 对象.sorted # 注意:Set无、Map无
    
37.元素按要求排序,返回新对象 
    val a = 对象.sortBy(x => ‐x) # 注意:Set无、Map无

38.去重,返回新对象 
    val a = 对象.distinct # 注意:Set无、Map无
    
39.按指定索引切分为二,返回新对象 
    val a = 数据类型(元素1, 元素2, 元素3, 元素4, 元素5) 
    val b = a.splitAt(索引) # 效果:(数据类型(元素1, 元素2),数据类型(元素3, 元素4, 元素5))
    
40.使用迭代器,返回新对象 
    val 新对象 = for(元素 <‐ 对象) yield 对元素操作 # 效果:新对象的数据类型和旧的一样
    
41.过滤,返回新对象
    方式一 filter
        val 新对象 = 对象.filter(x => x % 2 == 0) # 效果:满足过滤条件的元素存入新对象 # 注意:x 代表当前元素,也可用_代表当前元素
        
        或
        
        val 新对象 = Map对象.filterKeys(x => x % 2 ==0) # 效果:过滤满足条件的key存入新对象
    
    方式二 collect(偏函数)
        val a = Map("k1"->1,"k2"->2,"k3"->3)
        val b = a.collect({
            case x if x._2 % 2 == 0 => x
        }) # 效果:Map(k2 -> 2)
    
42.map操作,返回新对象 
    val 新对象 = 对象.map(x => x + 1) # 效果:取出对象中每个元素,进行处理后,存入新对象 # 注 意:x代表当前元素,也可用_代表当前元素
    
43.按元素分组 
    val a = 数据类型(元素1, 元素2, 元素3) 
    val b = a.groupBy(x => x %2 == 0)

44.类型转换 
    转String 
        方式一 mkString 推荐 
            val s = 对象.mkString # 效果:取出各元素,直接拼接成String
        
            val s = 对象.mkString(",") # 效果:取出各元素,用,拼接成String
            
            val s = 对象.mkString("<", "‐", ">") # 效果:取出各元素,用,拼接成String,首拼上 <,尾拼上>
        
        方式二 调用的java的toString() 不用 
            val s = 对象.toString() # 效果:数组的话是地址值,其他可显示出元素值
    
    不可变转可变 
        val a = 不可变对象.toBuffer / val a = 不可变Set对象.toSet / val a = 不可变Map对象.toMap
    
    转XX
        val a = 对象.toXX

45.+添加指定元素,返回新对象 
    val a = Map/Set对象 + (新元素1, 新元素2)

46.‐删除指定元素,返回新对象 
    val a = Set对象 ‐ (旧元素1, 旧元素2) / 
    val a = Map对象 ‐ (旧key1, 旧key2)
    
47.俩对象拼接,返回新对象
    val a = Traversable.concat(对象A, 对象B, 对象C) # 推荐 # 效果:新对象数据类型是List, 多个对象拼接时不会产生中间结果,但是用多个++拼接多个对象时每次++都会产生一个新的临时结果占用内存多
    
    val a = 对象A ++ 对象B # 效果:新对象的数据类型和A一样
    
    val a = 数据类型("A") ++: 数据类型("B") 
    
    val a = List("A") ::: List("B") # 注意::::符号只有List有
    
48.多维
    创建二维
        val a = 数据类型(元素1, 元素2) # 一维 
        val b = 数据类型(元素3, 元素4) # 一维 
        val c = 数据类型(a, b) # 二维
        
    遍历二维
        for(i <‐ c)println(i.mkString("‐"))
        
49.集合填充 # 注意:仅适用于Traversable
    方式一 fill快速生产指定数量的元素
        val a = Traversable.fill(3)("wsy") // 注意:第1个参数列表中只有1个参数代表创建个一维集合,第1个参数列表中的第1个参数3代表一维List有3个元素,第2个参数列表代表集合中每个元素都是"wsy"
    
        val b = Traversable.fill(3)(Random.nextInt(100)) // 注意:第1个参数列表中只有1个参数代表创建个一维集合,第1个参数列表中的第1个参数3代表一维List有3个元素,第2个参数列表代表集合中每个元素都是随机出来的一个值
    
        val c = Traversable.fill(3,4)("wsy") // 注意:第1个参数列表中有2个参数代表创建个二维集合,第1个参数列表中的第1个参数3代表外维List有3个元素,第1个参数列表中的第2个参数4代表内维List有4个元素,第2个参数列表代表集合中每个元素都是"wsy"
    
        val d = Traversable.fill(3,4,1)("wsy") // 注意:第1个参数列表中有3个参数代表创建个三维集合,第1个参数列表中的第1个参数3代表外维List有3个元素,第1个参数列表中的第2个参数4代表中维List有4个元素,第1个参数列表中的第3个参数1代表内维List有1个元素,第2个参数列表代表集合中每个元素都是"wsy"
        
    方式二 iterate根据指定条件生产指定个数的元素
        val a = Traversable.iterate(1,5)(x => x * 2) // 效果:1是初始值,共5个元素,初始值*2作为第1个元素,第1个元素*2作为第2个元素,依次类推
        
    方式三 range生成某个区间内的指定间隔的所有数据
        val a = Traversable.range(1, 20, 5) // 效果:从数字1开始,到数字19,间隔5的所有数据
        
        val a = Traversable.range(1, 20) // 注意:不指定间隔时默认间隔是1
        
50.拉链操作,返回新对象 
    val a = 数据类型(元素1, 元素2) 
    val b = 数据类型(元素3, 元素4) 
    val c = a zip b # 效果:数据类型((元素1, 元素3), (元素2, 元素4)) # 注意:a和b如果长度不一样,未对齐的元素会直接丢弃;如果有的值是null,会被当作正常元素

51.解链操作,返回新对象 
    val c = 数据类型((元素1, 元素3), (元素2, 元素4))
    val ab = c.unzip # 效果:(数据类型(元素1, 元素2), 数据类型(元素3, 元素4))

52.扁平化操作,返回新对象 
    val a = 数据类型(数据类型(元素1, 元素2), 数据类型(元素3, 元素4), 数据类型(元素5, 元素6)) 
    val b = a.flatten // 效 果:数据类型(元素1, 元素2, 元素3, 元素4, 元素5, 元素6) 
    
    # 注意:Map?

53.按照索引生成元组
    val a = Iterable("A", "B", "C", "D", "E") # 注意:Iterable换成数组、集合都通用
    val b = a.zipWithIndex // 效果:List((A,0), (B,1), (C,2), (D,3), (E,4))

54.取并集,返回新对象 
    对象A.union(对象B) # 注意:Map无
    
55.取交集,返回新对象 
    val a = 对象A.intersect(对象B) # 注意:Map无
    
56.取差集,返回新对象 
    val a = 对象A.diff(对象B) # 效果:对象A有但B没有的元素 # 注意:Map无

57.m*n矩阵转置
    val a5 = Traversable(Traversable(1,2,3), Traversable(4,5,6)) // 注意:Traversable可换成任何集合、数组
    val a6 = a5.transpose // 效果:List(List(1, 4), List(2, 5), List(3, 6)) // 注意:返回值类型和原来的一样

58.scan操作,返回新对象
    val c = Traversable(1,2,3,4,5) // 注意:Traversable可换成任意集合、数组
    val d = c.scan(0)((x,y) => x + y) // 注意:第1个参数列表是初始值,第2个参数列表是函数
    println(d) // 效果:List(初始值0, 初始值与第1个元素的计算结果1, 计算结果与第2个元素的计算结果3, 计算结果与第3个元素的计算结果6, 计算结果与第4个元素的计算结果10, 计算结果与第5个元素的计算结果15) // 注意:数据类型和原来一样

示例

# 数组常用算法
object ArrayBuffer1 {
  def main(args: Array[String]): Unit = {
    val a = ArrayBuffer(4, 1, 6, 5, 2, 3)
    println(a.sum) // 效果:21

    println(a.max) // 效果:6

    println(a.min) // 效果:1

    val b = a.sorted
    for(i <- b)print(i) // 效果:123456
    println()

    val c = b.reverse
    for(i <- c)print(i) // 效果:654321
    println()

    for(i <- a)print(i) // 效果:416523
  }
}
# 数组生成迭代器 -- yield
object HelloScala {
  def main(args: Array[String]): Unit ={
    val arr = Array(1, 2, 3, 4, 5)

    val dealArr = for(e <- arr) yield e * 2 // 数组转换 -- yield

    for(e <- dealArr)println(e)
  }
}

# 效果:2 4 6 8 10
# 数组过滤 -- filter
object HelloScala {
  def main(args: Array[String]): Unit ={
    val ab = ArrayBuffer(1, 2, 3, 4)
    val dealAb = ab.filter(_ % 2 == 0) // 数组转换 -- filter
    for(e <- dealAb) println(e)
  }
}

# 效果:2 4
# 数组映射 -- map
object HelloScala {
  def main(args: Array[String]): Unit ={
    val ab = ArrayBuffer(1, 2, 3)
    val dealAb = ab.map(_ + 1) // 数组转换 -- map
    for(e <- dealAb) println(e)
  }
}

# 效果: 2 3 4
# 数组转String
object HelloScala {
  def main(args: Array[String]): Unit ={
    val arr = Array(3, 1, 2)
    val dealArr = arr.mkString // array转String
    println(dealArr)
  }
}

# 效果:312

# 数组转String
object HelloScala {
  def main(args: Array[String]): Unit ={
    val arr = Array(3, 1, 2)
    val dealArr = arr.mkString("-") // array转String
    println(dealArr)
  }
}

# 效果:3-1-2

# 数组转String
object HelloScala {
  def main(args: Array[String]): Unit ={
    val arr = Array(3, 1, 2)
    val dealArr = arr.mkString("[","-","]") // array转String
    println(dealArr)
  }
}

# 效果:[3-1-2]
# 多维数组
object HelloScala {
  def main(args: Array[String]): Unit ={
    val arr1 = Array(1, 2)
    val arr2 = Array(3, 4)
    // 创建二维数组
    val Arr2V = Array(arr1, arr2)
    // 遍历二维数组
    for(arr <- Arr2V)println(arr.mkString("-"))
  }
}

# 效果:1-2 3-4

2.元组Tuple

2.1.概念

元组Tuple一般用来存储多个不同数据类型的值

元组的长度和内容都不可变

元组的元素可重复、存取有序

2.2.定义语法

0.通用定义语法
    val/var t = (元素1, 元素2)

1.二元组定义语法
    val/var t = 元素1 -> 元素2
    
    # 注意:
        0.只适用于二元组,即元组只有2个元素时
        
        1.二元组会自动和key-value结构进行转换

2.3.API

# 注意:元组的API很特别,几乎只适合自己,和其他类型的API不通用
0.按索引获取元素
    val a = 元组对象._1 # 注意:_1代表获取第1个元素,_2代表获取第2个元素
    
1.遍历
    val t3 = ("q", 1, 1.2, 'w')
    val it = t3.productIterator // 获取元组的迭代器对象
    for(i <- it)println(i)
        
2.Array(Tuple)转Map
    val a = Array(("tom", 8), ("Jerry", 9))
    val m = a.toMap

示例

object Tuple1 {
  def main(args: Array[String]): Unit = {
    val t3 = ("q", 1, 1.2, 'w')
    val it = t3.productIterator
    for(i <- it)print(i) // 效果:q11.2w
    println()
    println(t3._1) // 效果:q
  }
}
上一篇:Spark SQL知识点与实战


下一篇:用IDEA开发Scala程序helloworld