Scala(七)-①-数据结构-集合-Array和List和ListBuffer

Java中不可变集合

  • 不可变集合概念(java为例)
public class ImmutableDemo01ForJava {
   public static void main(String[] args) {
       // 1.不可变集合,内容可变,旦数组本身不能动态增长
       int []nums = new int[3];
       nums[2] = 2;
       //  nums[3] = 1  错误

       // 2.可变集合,集合本省能够动态增长
ArrayList arrayList = new ArrayList<String>();
       arrayList.add("t1");
       System.out.println(arrayList.hashCode());
       arrayList.add("t2");
       System.out.println(arrayList.hashCode());
   }
}

Scala中的集合

特点

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

两个主要的包:
不可变集合:scala.collection.immutable
可变集合: scala.collection.mutable

  • Scala默认采用不可变集合,对于几乎所有的集合类,Scala都同时提供了可变(mutable)和不可变(immutable)的版本
  • Scala的集合有三大类:序列Seq集Set映射Map,所有的集合都扩展自Iterable特质,在Scala中集合有可变(mutable)和不可变(immutable)两种类型.

举个例子

  • 不可变集合: scala不可变集合,就是这个集合本身不能动态变化.(类似java的数组,是不可以动态增长的)
  • 可变集合:可变集合,就是这个集合本身可以动态变化的.(比如:ArrayList,是可以动态增长的)

不可变集合继承层次一栏图

image.png

可变集合继承层次一栏图

image.png

细节

  • Seq是Java中没有的,List归属于Seq.所以这里的List和Java不一样.
  • for循环里的1 to 3,就是基于IndexSeq下的Vector
  • String也是属于indexSeq
  • Queue和Stack归属于LinearSeq.即是线性的,有头有尾
  • IndexSeqLinearSeq.IndexSeq是基于索引的序列,LinearSeq是线性序列

① 数组

Why

Scala同时支持不可变集合可变集合.不可变集合是线程安全的.

  • 队列的应用场景
    推荐系统要用户最近浏览的10个商品.

How

  • 学习集合的创建、修改、删除、增加

定长数组-Array

创-方式一-new Array
/**
  * @author sweetcs
  */
object ArrayDemo01 {
  def main(args: Array[String]): Unit = {

    // 默认为零
    var arr = new Array[Int](4)
    println("数组长度=" + arr.length)
    println("循环遍历数组:")
    for (item <- arr) {
      println(item)
    }

    arr(3)=1
    
    println("循环遍历数组:")
    for (item <- arr) {
      println(item)
    }

  }
}
创-方式二-Array
/**
  * @author sweetcs
  */
object ArrayDemo02ForApply {
  def main(args: Array[String]): Unit = {
    // 数组元素的类型时Any.一旦定义就不可在更改
    var array = Array(1, 2, "beijing")

    // 数组元素的类型时Int.一旦定义就不可在更改
    var arrayOfInts = Array(1,2)


    for (item <- array) {
      println(item)
    }

    // 传统for循环基于索引遍历
    var len = array.length
    for (i <- 0 until len) {
      printf("%s\t", array(i))
    }
  }
}

变长数组-ArrayBuffer

创-变长数组的增删改查
/**
  * @author sweetcs
  */
object MutableArrayDemo01 {
  def main(args: Array[String]): Unit = {
    
    val arrayBuffer = ArrayBuffer[Any](2,3,"beijing")
    println(arrayBuffer(2))

    println(arrayBuffer.hashCode())
    // 增
    arrayBuffer.append(5, 6)
    println(arrayBuffer.hashCode())

    // 删
    arrayBuffer.remove(0)
    // 查
    for (item <- arrayBuffer) {
      print(item + "\t")
    }
  }
}

定长数组和变长数组的转换

  • toArray
  • toBuffer
/**
  * @author sweetcs
  */
object MutableArrayDemo02ForTranslateImutable {
  def main(args: Array[String]): Unit = {

    val arrayBuffer = ArrayBuffer(1,2,"beijing")
    val array = arrayBuffer.toArray
    println(array.hashCode(), arrayBuffer.hashCode())
    println("遍历不可变数组")
    for (item <- array) {
      println(item)
    }

    val mutableArray = array.toBuffer
    mutableArray.append(3)
    println("遍历mutableArray")
    for (item <- mutableArray) {
      println(item)
    }

    println("遍历arrayBuffer")
    for (item <- arrayBuffer) {
      println(item)
    }
  }
}

多维数组

语法
// 创建一个3行四列的Double数组
val arr = Array.ofDim[Double](3,4)
多维数组Demo
/**
  * @author sweetcs
  */
object ArrayDemo05ForMultiplyDimArray {
  def main(args: Array[String]): Unit = {

    val arr = Array.ofDim[Int](3, 4)

    // 查
    println("查case==========")
    for (row <- arr) {
      println(row)
      for (col <- row) {
        println(col + "\t")
      }
    }

    println("改case==========")
    // 改
    arr(0)(1) = 3
    for (row <- arr) {
      println(row)
      for (col <- row) {
        println(col + "\t")
      }
    }

  }
}

Java数组(List)和Scala数组(ArrayBuffer)的互转

  • Scala->Java
object ArrayDemo06ForScalaArrayToJavaArray {

  def main(args: Array[String]): Unit = {

    //创建了ArrayBuffer
    val arr = ArrayBuffer("1", "2", "3")

    //下面的import 引入了我们需要的隐式函数【这里就是隐式函数的应用】
    //implicit def bufferAsJavaList[A](b : scala.collection.mutable.Buffer[A]) : java.util.List[A]
    import scala.collection.JavaConversions.bufferAsJavaList

    // 触发隐式转换
    val javaArr = new ProcessBuilder(arr)

    //返回的是 List<String>
    val arrList = javaArr.command()

    println(arrList) //输出 [1, 2, 3]
  }
}

  • Java->Scala
object ArrayDemo07ForJavaArrayToScalaArray {
  def main(args: Array[String]): Unit = {

    val arrList = new java.util.ArrayList[String]()

    import scala.collection.JavaConversions.asScalaBuffer
    import scala.collection.mutable
    // java.util.List ==> Buffer
    val scalaArr: mutable.Buffer[String] = arrList
    scalaArr.append("jack")
    scalaArr.append("tom")
    println(scalaArr)
    scalaArr.remove(0)
    println(scalaArr) // (2,3,jack,tom)

  }
}

What

  • 不可变集合: 集合本身不能变化,类似于Java里的数组,不是动态增长

  • 可变集合: 集合本身能变化

  • toBuffer的底层实现
    又重新new了一个ArrayBuffer,将数据拷贝到这个ArrayBuffer实例中

  override def toBuffer[A1 >: A]: mutable.Buffer[A1] = {
    val result = new mutable.ArrayBuffer[A1](size)
    copyToBuffer(result)
    result
  }

Details

  • Scala创建的集合几乎所有是不可变集合.
  • Scala集合集合的三大类型Seq\Set\Map
  • ArrayBuffer是变长数组,类似于ArrayList
  • 定长数组和变长数组的相互转换, 返回的是新数组,不改变旧数组

② 元组

Why

  • 元组用来解决那些想把不同的数据类型放在一起的需求.
  • 元组可以理解为一个容器, 可以存放各种相同或不同类型的数据.

How

元组语法

使用小括号标识元组.

val t = (1,23,"we are")
元组DEMO
  • 元组的创建元组类型
object TupleDemo01 {
  def main(args: Array[String]): Unit = {

    val tuple1 = (1,2,3,4,"hello")
    println(tuple1, tuple1.getClass) // ((1,2,3,4,hello),class scala.Tuple5)

  }
}
  • 元组访问,序号方式(1开始)、索引方式(0开始)
  • 元组遍历需要使用迭代器
object TupleDemo02ForAccess {
  def main(args: Array[String]): Unit = {

    val tuple = (1, 2, 3, "beijing")

    println(tuple._1)
    println(tuple.productElement(0))

    println("元组的遍历")
    // 元组遍历,要用迭代器
    for (item <- tuple.productIterator) {
      println(item)
    }

  }
}

What

元组的访问-索引方式(0开始)原理
  @throws(classOf[IndexOutOfBoundsException])
  override def productElement(n: Int) = n match { 
    case 0 => _1
    case 1 => _2
    case 2 => _3
    case 3 => _4
    case _ => throw new IndexOutOfBoundsException(n.toString())
 }

Details

  • 编译期根据Tuple的数据个数,创建对应元组类型.例如, Tuple5表示这个元组有5个元素.
  • 元组的元素个数最多是22个.

③ List

Why

List是Seq的子类,用于按序存放元素.

How

不可变List

  • list的创建和访问
 val list = List(1, 2, 3, "beijing")
  • list元素的追加方式,使用+:或者:+, 冒号一边为list,返回的是一个新List对象
    代码
/**
  * @author sweetcs
  */
object ListDemo02ForAppendAndReturnNewList {
  def main(args: Array[String]): Unit = {
    val list = List(1, 2, 3, "beijing")

    // 在列表的最后追加
    val newList = list :+ 6

    // 在列表的头追加
    val newList02 = 6 +: list
    println(s"list hashcode = ${list.hashCode()}, newList = ${newList.hashCode()}, newList02 = ${newList02.hashCode()}")
    println("newList= " + newList)
    println("newList02= " + newList02)
  }
}

输出

list hashcode = -1049219423, newList = 173175143, newList02 = -1337286218
newList= List(1, 2, 3, beijing, 6)
newList02= List(6, 1, 2, 3, beijing)
  • ::和:::添加集合
object ListDemo02ForAppendAndReturnNewList {
  def main(args: Array[String]): Unit = {
    val list = List(1, 2, 3, "beijing")

    // 在列表的最后追加
    val newList = list :+ 6

    // 使用::添加元素, 会将一个集合当成一个整体放入集合中.
    // 使用:::添加元素, 会将一个集合中的元素都依次添加进去
    val newList03 = 4 :: 5 :: 6 :: 7 :: list :: Nil
    println(newList03)


    val newList04 = 4 :: 5 :: 6 :: 7 :: list ::: Nil
    println(newList04)
  }
}

可变list-ListBuffer

ListBuffer是可变的list集合, 可以添加, 删除元素,ListBuffer属于序列

object ListDemo03ForListBuffer {
  def main(args: Array[String]): Unit = {
    val lst0 = ListBuffer[Int](1, 2, 3)
    //如何访问
    println("lst0(2)=" + lst0(2)) // 输出 lst0(2)= 3
    for (item <- lst0) { // 遍历,是有序
      println("item=" + item)
    }

    //动态的增加元素,lst1就会变化, 增加一个一个的元素
    val lst1 = new ListBuffer[Int] //空的ListBuffer
    lst1 += 4 // lst1 (4)
    lst1.append(5) // list1(4,5)

    //
    lst0 ++= lst1 // lst0 (1, 2, 3,4,5)

    println("lst0=" + lst0)


    val lst2 = lst0 ++ lst1 // lst2(1, 2, 3,4,5,4,5)
    println("lst0=" + lst0)
    println("lst2=" + lst2)

    val lst3 = lst0 :+ 5 // lst0 不变 lst3(1, 2, 3,4,5,5)
    println("lst3=" + lst3)


    println("=====删除=======")
    println("lst1=" + lst1)
    lst1.remove(1) // 表示将下标为1的元素删除
    for (item <- lst1) {
      println("item=" + item) //4
    }

  }
}

Details

  • Scala中的List是能存放元素,Java中的List是一个接口
  • List属于Seq,默认情况下创建的List是不可变List实例
  • List在scala包对象声明的,因此不需要引入其它包也可以使用val List = scala.collection.immutable.List
  • :: 运算时,集合对象一定要放置在最右边.
  • ::: 运算符是将集合中的每一个元素加入到集合中去,并且左右两边都必须是集合.
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容