Scala入门详解(三)

个人博客原文链接

集合

List
/**
  * List
  * 列表类似于数组,它们所有元素的类型都相同,但是它们也有所不同:
  * 列表是不可变的,值一旦被定义了就不能改变,
  * 其次列表具有递归的结构(也就是链接表结构)而数组不是
  */
object TestList {
  def main(args: Array[String]): Unit = {
    // 不可变List
    // 声明不可变List
    // 字符串列表,两种方式
    val strs = List("a","b","c","d")
    val strs2 = "a"::("b"::("c"::("d"::Nil)))
    // 整型列表,两种方式
    val nums = List(1,2,3,4)
    val nums2 = 1::(2::(3::(4::Nil)))
    // 空列表,两种方式
    val empty = List()
    val empty2 = Nil
    // 二维列表,两种方式
    val dim = List(
      List(1,1,1),
      List(2,2,2),
      List(3,3,3)
    )
    val dim2 = (1::(1::(1::Nil)))::(2::(2::(2::Nil)))::(3::(3::(3::Nil)))::Nil
    // 遍历
    for (i <- dim2){
      println(i)
    }

    // 列表基本操作
    // head 返回列表第一个元素
    // tail 返回一个列表,包含除了第一元素之外的其他元素
    // isEmpty 在列表为空时返回true
    println(strs.head)
    println(strs.tail)
    println(empty.isEmpty)

    // 连接列表
    // 1. 使用 ::: 运算符
    val str = strs:::strs2
    // 2. 使用List.:::() 方法
    val num = nums.:::(nums2)
    // 3. 使用concat方法
    val tem = List.concat(strs,strs2)

    // List.fill()
    // 我们可以使用 List.fill() 方法来创建一个指定重复数量的元素列表
    val remem = List.fill(3)("ok")

    // List.tabulate()
    // 通过给定的函数来创建列表,第一个参数为元素的数量
    // 第二个参数为指定的函数,我们通过指定的函数计算结果并返回值插入到列表中,起始值为 0
    val squares = List.tabulate(6)(n => n * n)

    // List.reverse
    // 将列表的顺序反转
    strs.reverse

    val list = List(1)
    // 添加元素
    val list2 = 2 :: list
    println(list2)

    // List函数操作
    val data = List("hello","Mike")
    // map,把元素中的每个元素转成List
    println(data.map(_.toList));
    // flatMap,将list元素分成多个list元素,再重新合成新的List元素
    println(data.flatMap(_.toList))
    val lnum = List(1,2,3,4)
    // sum,求和
    println(lnum.sum)
    // filter,过滤
    println(lnum.filter(_ %2 == 0))
    // partition,分区即根据条件分成两个list
    println(lnum.partition(_ %2 == 0))
    // groupBy,根据条件分组,返回Map集合
    println(lnum.groupBy(i => i))
    // slice,返回(first,end]区间的值
    println(lnum.slice(1,4))
    // splitAt,从第n个元素开始切开,分成两部分
    println(lnum.splitAt(2))
    // reduce,合并
    println(lnum.reduce(_+_))
    // fold,合并,有初始值
    println(lnum.fold(10)(_+_))
    // find,返回第一个符合的值(Option类型)
    println(lnum.find(_ % 3 == 0).get)
    // takeWhile,返回符合条件的List
    println(lnum.takeWhile(_ < 3))
    // dropWhile,删除符合条件的元素,返回剩下元素的List
    println(lnum.dropWhile(_ < 3))
    // span,和partition类似,符合条件的返回一个List,不符合条件的返回另一个List
    println(lnum.span(_ < 4))
    // sortWith,排序
    println(lnum.sortWith(_ < _))
    println(lnum.sortWith(_ > _))
    // sorted排序
    println(lnum.sorted)
    // range
    println(List.range(2,10,3))
    // zip,unzip
    val zipped = "abcd".toList.zip("123")
    println(zipped)
    println(zipped.unzip)
    println(zipped.unzip._1)

    // 变形集合,开启多个线程
    val morelist:List[Int] = (1 to 100).map(i => 1).toList
    println(morelist.par.fold(10)(_+_))

    // view,惰性化计算
    val seq = Seq(1,2,3)
    val listS = seq.toList.map(i => println("A")).map(j => println("B"))
    val listS2 = seq.view.toList.map(i => println("A")).map(j => println("B"))
//    println("***"+listS)

    // ListBuffer
    // 可变列表
    val lBuffer = scala.collection.mutable.ListBuffer(1,2,3,4)
    // 追加元素
    lBuffer += 5
    println(lBuffer)

  }
}

Set
/**
  * Set
  * Scala Set(集合)是没有重复的对象集合,所有的元素都是唯一的。Scala 集合分为可变的和不可变的集合。
  * 默认情况下,Scala 使用的是不可变集合,如果你想使用可变集合,需要引用 scala.collection.mutable.Set包
  */
object TestSet {
  def main(args: Array[String]): Unit = {
    // 不可变Set
    // 声明不可变Set
    val s = Set(1,2,3)
    // 添加元素,返回新的Set
    val s1 = s.+(4)
    println(s1)
    // 连接集合,两种方式
    var s2 = s ++ s1
    var s3 = s.++(s1)
    println(s3)
    // 最大值,最小值
    println(s3.max)
    println(s3.min)
    // 交集,两种方式
    val num1 = Set(1,2,3,4)
    val num2 = Set(3,6,9)
    val num3 = num1.&(num2)
    val num4 = num1.intersect(num2)
    println(num4)


    // 可变Set
    // 声明可变Set
    val set = scala.collection.mutable.Set(0,1,2)
    // 添加元素
    set.add(3)
    set += 4
    // 删除元素
    set.remove(0)
    set -= 1
    println(set)
    // 清除所有元素
    set.clear()
    println(set)
    println(set.getClass.getName) // mutable
    // 将可变集合转化为不可变集合
    val set2 = set.toSet
    println(set2.getClass.getName) // immutable

  }
}

Map
/**
  * Map
  * Map有两种类型,可变与不可变,区别在于可变对象可以修改它,而不可变对象不可以。
  * 默认情况下Scala使用不可变 Map。如果你需要使用可变集合,你需要显式的引入
  * import scala.collection.mutable.Map类。在Scala中你可以同时使用可变与不可变Map,
  * 不可变的直接使用Map,可变的使用mutable.Map。
  */
object TestMap {
  def main(args: Array[String]): Unit = {
    // 不可变Map
    // 声明不可变Map
    val map1 = Map(1 -> 1,2 -> 2)
    val map11 = Map((1,1),(2,2),(3,3))
    // 添加键值对
    val map2 = map1 + (4->4)
    println(map2)

    // 基本操作
    // 返回Map所有的键(key)
    println(map2.keys)
    // 返回Map所有的值(value)
    println(map2.values)
    // 在Map为空时返回true
    println(map2.isEmpty)

    // Map合并,两种方式
    val map3 = map1 ++ map2
    val map4 = map1.++(map2)

    // 遍历输出Map的key和value,方式一
    map3.keys.foreach{
      i => println("key:"+i)
        println("value:"+map3(i))
    }
    // 遍历输出Map的key和value,方式二
    for((key,value) <- map3){
      println("key:"+key+" ==> value:" + value);
    }

    // 查看map中是否有对应的key
    if (map2.contains(2))
      println("存在")
    else
      println("不存在")


    // 可变Map
    // 声明可变Map
    val mapDyn = scala.collection.mutable.Map(1 -> "张三",2 -> "李四")
    // 添加元素
    mapDyn += (3 -> "王五")
    mapDyn(4) = "赵六"
    // 删除元素
    mapDyn -= (1)
    // 遍历k-v
    for ((k,v) <- mapDyn) println("k:"+k+" v:"+v)

    // Mapp排序
    // SortedMap
    val sortedScore = scala.collection.immutable.SortedMap("Scala"->7,"Hadoop"->10,"Spark"->12)
    for ((k,v) <- sortedScore) println("k:"+k+" v:"+v)
  }
}

Queue
/**
  * Queue
  * 队列
  */
object TestQueue {
  def main(args: Array[String]): Unit = {
    // 不可变队列
    // 声明不可变队列
    val queue = scala.collection.immutable.Queue(1,2,3)
    // 添加元素,返回一个新的队列
    val queue2 = queue.enqueue(List(1,2,3))
    println(queue2)
    // dequeue,将quenue2拆分成两部分:第一个元素,和剩下的一个元素组成Queue两部分
    // 相当于先进先出,拿走一个元素
    val (first,others) = queue2.dequeue
    println(first+"|"+others)


    // 可变队列
    // 声明可变队列
    val queue3 = scala.collection.mutable.Queue(1,2,3)
    // 追加元素
    queue3 += 4
    // 追加集合
    queue3 ++= List(5,6)
    println(queue3)
    // dequeue,可变的Queue只返回第一个元素,并且把第一个元素从Queue中删除
    println(queue3.dequeue)

  }
}
Stack
/**
  * Stack
  * 栈
  */
object TestStack {
  def main(args: Array[String]): Unit = {
    // 不可变栈
    // 声明不可变栈
    val stack = scala.collection.immutable.Stack(1,2,3)
    println(stack)
    // 入栈,往栈顶添加元素,返回新的对象
    val stack2 = stack.push(4)
    println(stack2)

    // 可变栈
    // 声明不可变栈
    val stack3 = scala.collection.mutable.Stack(1,2,3)
    // 入栈往栈顶添加元素
    stack3.push(4)
    println(stack3)
    // 返回栈顶元素
    println(stack3.top)
    // 出栈,返回并删除栈顶元素
    stack3.pop()
    println(stack3)
  }
}

Tree
/**
  * TreeSet
  * TreeMap
  * 返回的结果都是已经排好序的
  */
object TestTree {
  def main(args: Array[String]): Unit = {
    // 不可变TreeSet
    val treeSet = scala.collection.immutable.TreeSet(1,4,2,9,5,2,7)
    // 添加元素,返回新的对象
    val treeSet3 = treeSet + 50
    println(treeSet3)
    // 可变TreeSet
    val treeSet2 = scala.collection.mutable.TreeSet(1,4,2,9,5,2,7)
    // 添加元素
    treeSet2 += 100
    println(treeSet2)


    // 不可变TreeMap
    val treeMap = scala.collection.immutable.TreeMap("book" -> "ok","others" -> "no")
    // 添加元素,返回新的对象
    val treeMap3 = treeMap + ("food" -> "ok")
    println(treeMap3)
    // 可变TreeMap,不存在的
  }
}

泛型

/**
  * 泛型类、泛型函数
  * 泛型用于指定方法或类可以接受任意类型参数
  * 参数在实际使用时才被确定
  * 泛型可以有效地增强程序的适用性
  * 使用泛型可以使得类或方法具有更强的通用性
  */
object TestGeneric {
  def main(args: Array[String]): Unit = {
    // 泛型类
    class GenericClass[F, S, T](val f: F, val s: S, val t: T)
    // 实例化方式1:类型推导
    val gc = new GenericClass("xj", 22, 'C')
    // 实例化方式2:类型声明
    val gc2 = new GenericClass[String, String, Int]("xj", "lj", 22)

    // 泛型函数
    def getData[T](list: List[T]) = list(list.length - 1)

    println(getData(List('b', "bj", 26, 2.0)))
    // 获得getData的引用,必须指定泛型类型
    val t = getData[Int] _
    println(t(List(1, 2, 3, 4, 5)))

    // 类型变量界定
    // 通过编译,为范型T增加了约束,限定上界为Comparable[T]
    // 范型类型T也就具有了Comparable[T]中的compareTo(T)方法,类似于java中的继承
    def typeVariable[T <: Comparable[T]](a: T, b: T) = {
      if (a.compareTo(b) > 0)
        1
      else
        -1
    }
    // 正确运行,String有上界Comparable[T]
    println(typeVariable("a", "b"))
    // Int类型运行错误,Int没有上界Comparable[T],但是为何编译不报错?
    // 如果想成功运行的话,就需要进行一次隐式转换,
    // 将Int类型转换成支持Comparable[T]的类型,此时应该改用视图界定<%
    // 视图界定帮我们进行了隐式转换,将Int转换成了支持Comparable[T]的RichInt类型
    //    println(typeVariable(1,2))

    // 视图界定
    // <% 泛型视图界定符,表示把传入不是Comparable[T]类型的 隐式传换 为Comparable[T]类型
    // a之所以能使用方法compareTo,是因为a被隐式传换为Comparable[T]类型
    def viewBound[T <% Comparable[T]](a: T, b: T) = {
      if (a.compareTo(b) > 0)
        a
      else
        b
    }
    // Int类型被隐式转换成了支持Comparable[T]的RichInt类型
    println(viewBound(1, 2))


    // 上下文界定
    class PairOrdering[T: Ordering](val first: T, val second: T) {
      // compareTo方法进行比较,如果大于0返回first
      def bigger(implicit ordered: Ordering[T]) = {
        if (ordered.compare(first, second) > 0) first else second
      }
    }
    // 函数调用
    var pair = new PairOrdering("Spark", "Hadoop")
    // 执行结果:Spark
    println(pair.bigger)


    // 多重界定
    //  一个类型参数有多个类型约束,比如:
    //  T >: A <: B 表示T所允许的范围是A的父类 或者是B的子类
    //  T: A: B 表示作用域必须同时满足存在A[T]和B[T]隐式值
    //  T <% A <% B表示作用域必须同时满足T到A和T到B的隐式转换
    class Animal{
      def speak():Unit={
        println("666")
      }
    }
    class Person extends Animal{}
    class Student extends Person{}
    def showAll[T >: Person <: Person](str:T) ={
      str.speak()
    }

    // Manifest关键字
    // 数组在声明时必须要求指定具体的类型,在函数泛型是无法知道具体类型,
    // 通过Manifest关键字使得运行时可以根据这个Manifest参数做更多的事情
    def arrayMake[T: Manifest](first: T, second: T) = {
      val r = new Array[T](2);
      r(0) = first;
      r(1) = second;
      // 返回r
      r;
    }
//    val array = arrayMake("a","b")
//    for (i <- array) println(i)
    arrayMake("a","b").foreach(println)


    // ClassTag关键字
    // ClassTag[T]保存了泛型擦除后的原始类型T,提供给被运行时的
    def mkArray[T:ClassTag](elems:T*) = Array[T](elems:_*)
    mkArray(42,13).foreach(println)
    mkArray("Japan","Brazil","Germany").foreach(println)


    // 类型约束
    // 类型约束提供给你的是另外一个限定类型的方式,总共有三种关系可供使用
    // T =:= U 表示测试T 是否等于U类型
    // T <:< U 表示测试T 是否为U的子类型
    // T <%< U 表示是否存在T到U 的转换


    // 协变,逆变
    // 协变[+T]
    // 只有满足指定类型或者指定类型子类才可以被兼容,即使是指定类型的父类也不会被兼容,
    // 通俗地讲,只要是你或者你的子类我都可以编译通过

    // 逆变[-T]
    // 只有满足指定类型或者指定类型父类才可以被兼容,即使是指定类型的子类也不会被兼容
    // 通俗地讲,只要是你或者你的父类我都可以编译通过
  }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值