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,是可以动态增长的)
不可变集合继承层次一栏图
可变集合继承层次一栏图
细节
- Seq是Java中没有的,List归属于Seq.所以这里的List和Java不一样.
- for循环里的
1 to 3
,就是基于IndexSeq下的Vector -
String
也是属于indexSeq
-
Queue和Stack
归属于LinearSeq
.即是线性
的,有头有尾
-
IndexSeq
和LinearSeq
.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
- :: 运算时,集合对象一定要放置在
最右边
. - ::: 运算符是将集合中的每一个元素加入到集合中去,并且左右两边都必须是集合.