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();
       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
    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
  • :: 运算时,集合对象一定要放置在最右边.
  • ::: 运算符是将集合中的每一个元素加入到集合中去,并且左右两边都必须是集合.

你可能感兴趣的:(Scala(七)-①-数据结构-集合-Array和List和ListBuffer)