• Scala集合(四)


    1. 集合

    集合主要有三种:

    1. Sequence
    2. Map
    3. Set

    sequence是一种线性元素的集合,可能会是索引或者线性的(链表)。map是包含键值对的集合,就像Java的Map,set是包含无重复元素的集合。

    除了这三个主要的集合类之外,还有其他有用的集合类型,如Stack, Queue和Range。还有其他一些用起来像集合的类,如元组、枚举、Option/Some/None以及Try/Success/Failure类。

    Scala通用的序列集合:

    不可变(Immutable) 可变
    索引(Indexed) Vector ArrayBuffer
    线性链表(Linked lists) List ListBuffer

    主要不可变序列集合类:

    索引序列 线性序列 描述
    List 一个单链表。适于拆分头和剩余链表的递归算法
    Queue 先进先出数据结构
    Range 整数值范围
    Stack 后进先出
    Stream 与链表相似,但是延迟并且持久。适用于大型或无限序列,与
    Haskell的链表类似
    String 可以被当作一个不可变的,索引的字符序列
    Vector “定位”不可变,可索引的序列。Scaladoc这样描述它, “处
    理split和join非常有效率的一组嵌套数组实现”

    主要的可变序列集合:

    索引序列 线性序列 描述
    Array 依靠于Java的数组,其中元素是可变的,但不能改变大小
    ArrayBuffer 一个可变的序列集合的“定位”类。成本是常数
    ArrayStack 后进先出数据结构。在性能比较重要时Stack更好
    DoubleLinkedList 像一个单链表,但有一个prev方法。文档说“额外的连
    接让删除元素变得非常快。”
    LinkedList 一个可变的单链表
    ListBuffer 像ArrayBuffer,但依靠链表。文档说, 如果想把buffer
    转成list,用ListBuffer而不是ArrayBuffer。前插后插开
    销都是常数。其他的大部分操作都是线性的
    MutableList 一个可变的,单链表,后插开销是常数
    Queue 先进先出数据结构
    Stack 后进先出数据结构。(文档建议ArrayStack的效率稍微好
    些。)
    StringBuilder 像在循环里构建字符串

    常用到的map:

    不可变 可变 描述
    HashMap

    不可变版本用“hash trie” (晗希线索)实现,可变版本用
    “哈希表”实现
    LinkedHashMap
    “用哈希表实现可变map”,元素按插入顺序返回
    ListMap

    用链表数据结构实现的map。元素按插入的相反顺序返回,因
    为每次插入的元素都放在head
    Map

    基础的map,有可变的和不可变的实现
    SortedMap
    接序存键的一个基本特质。(当前用5。rtedMap创建一个变量
    返回TreeMap。)
    TreeMap
    不可变的,排序的map,由红黑树实现
    WeakHashMap
    一个java.util.WeakHashMap的包装,弱引用的hashmap

    选择Set:

    不可变 可变 描述
    BitSet

    非负整数表示为比特放入64位字节的可变尺寸数组。当有一组
    整数时来节省内存空间
    HashSet
    不可变版本用“hash trie” (哈希线索),可变版本用“哈希
    表” ( hashtable)
    LinkedHashSet

    一个由hashtable实现的可变Set,按照插入顺序返回元素
    ListSet

    用链表实现的set
    TreeSet
    不可变版本用树实现。可变版本基于不可变的AVL树作为数据结构的SortedSet
    Set
    一般的基础特质
    SortedSet
    一个基础特质

    表现的像集合的类型:

    Scala提供了很多其他的集合类型,还有一些表现的像集合的类型,尽管它们不是集合:

    描述
    Enumeration 一个包含常数值的有限集合(比如,一周的天数或一年的周数)
    Iterator 迭代器不是一个集合,它可以访问集合中的元素.它也是集合,然而,定义许多方法便会发现一个普通的集合类,包括foreach, map, flatMap等。也可以在需要时把迭代器转换为一个集合
    Option 包含一个或者零个元素的集合,Some和None继承自Option。
    Tuple 支持异构的集合元素。没有一个“元组”类,元组由Tuple1 到Tuple22组成, 支持从1至22个元素

    2. List

    创建List:

    val list = List(1,2,3)
    val list1 = List[Number](1,2,3,4)
    val list2 = List.range(1,10)
    val list3 = List.range(1,20,2)
    val list4 = List.fill[String](3)("list")
    List[Char] list5 = "list".toList
    

    创建可变列表:

    var buffer = new ListBuffer[String]()
    buffer.+=("you","have","a","child")
    buffer += "。"
    println(buffer.toList)
    
    输出:
    List(you, have, a, child, 。)
    
    Process finished with exit code 0
    

    List基本方法的使用:

    1.合并两个list:

    val l3 = list ::: list1
    val l7 = list ++ list1
    val l8 = List.concat(list,list1)
    println(l3,l7,l8)
    
    结果:
    (List(2, 3, 4, 5),
    List(2, 3, 4, 5),
    List(2, 3, 4, 5))
    

    2.+:和:+ 的用法区别-连接两个列表:

    val list = List(2,3)
    val list1 = List(4,5)
    val l2 = list +: list1
    val l3 = list :+ list1
    println(l2,l3)
    输出:
    (List(List(2, 3), 4, 5),
    List(2, 3, List(4, 5)))
    

    由结果可以看出+:和:+是根据”:”的方法来解析数据的,”:”朝向那一边,这一边的数据就会作为基数据,另一方的数据会被添加到这个List中。

    3.使用Stream—-惰性计算元素周期

    List通过::构造, Stream可以用#::方法构建,表达式的结尾用Stream.empty代替Nil:

    val stream = 1#::2#::3#::Stream.empty
    println(stream)
    val iterator = stream.iterator
    while (iterator.hasNext){
      println(iterator.next())
    }
    输出:
    Stream(1, ?)
    1
    2
    3
    
    Process finished with exit code 0
    

    可以看到打印stream的时候只打出了1,后面的是?。这是因为流的结尾还没有执行,?表示惰性集合的结尾尚未被执行的表示方式。

    2.数组

    2.1 创建数组:

    val array = Array(1,2,3)
    val array1 = Array("I","am","a","boy")
    val array2 = Array[String]("I","am","a","boy")
    val array3 = new Array[Number](3)
    array3(0) = 1
    array3(1) = 2
    array3(2) = 3
    
    println(array.toList,array1.toList,array2.toList,array3.toList)
    
    输出:
    (List(1, 2, 3),
    List(I, am, a, boy),
    List(I, am, a, boy),
    List(1, 2, 3))
    

    其他创建数组的方式:

    val a1 = Array.range(1,10)
    val a2 = Array.range(1,20,2)
    val a3 = Array.apply(2,3,4,5,6)
    val a4 = Array.fill[String](3)("oo")
    val a5 = Array.tabulate(5)(n=>n+5)
    
    println(a1.toList,a2.toList,a3.toList,a4.toList,a5.toList)
    
    输出:
    (List(1, 2, 3, 4, 5, 6, 7, 8, 9),
    List(1, 3, 5, 7, 9, 11, 13, 15, 17, 19),
    List(2, 3, 4, 5, 6),
    List(oo, oo, oo),
    List(5, 6, 7, 8, 9))
    

    创建可变数组:

    Array既是可变的又是不可变的,可变的是他的内容,不可变的是他的大小。要想创建一个大小可变的数组,可以使用ArrayBuffer。

    val a1 = ArrayBuffer[Number](1)
    a1 += 2
    a1 += 3
    a1 += 4
    println(a1)
    
    val a2 = List[Number](5,6)
    a1 ++= a2
    println(a1)
    输出:
    ArrayBuffer(1, 2, 3, 4)
    ArrayBuffer(1, 2, 3, 4, 5, 6)
    
    Process finished with exit code 0
    

    删除操作:

    val a1 = ArrayBuffer[Number](1,2,3,4,5)
    a1 -= 1
    println(a1)
    a1 -= (1,2)
    println(a1)
    a1 --= List(1,2,3)
    println(a1)
    val a2 = ArrayBuffer[Number](2,2,4,3,4,5)
    #删除第一个位置的数据
    a2.remove(1)
    println(a2)
    #从第三个位置开始,删除两个数据
    a2.remove(3,2)
    println(a2)
    
    输出:
    
    ArrayBuffer(2, 3, 4, 5)
    ArrayBuffer(3, 4, 5)
    ArrayBuffer(4, 5)
    ArrayBuffer(2, 4, 3, 4, 5)
    ArrayBuffer(2, 4, 3)
    
    Process finished with exit code 0
    

    3. Map

    创建Map:

    var a1 =  Map("name"->"xiaoming","age"->12)
    val a2 = Map(("name","xiaoming"),("age",12))
    a1 += ("address"->"xxxx")
    println(a1,a2)
    
    输出:
    (Map(name -> xiaoming, age -> 12, address -> xxxx),
    Map(name -> xiaoming, age -> 12))
    
    Process finished with exit code 0
    

    修改Map:

    默认Map是immutable类型的,所以如果要修改Map,需要手动引入Mutable的Map。

    var a1 =  mutable.Map("name"->"xiaoming","age"->12)
    a1("name") = "xiaohong"
    println(a1)
    a1 ++= List("address"->"xxx","sex"->1)
    println(a1)
    a1 -= "name"
    println(a1)
    a1 --= List("age","sex")
    println(a1)
    a1.put("idCard","111")
    a1.remove("address")
    println(a1)
    
    输出:
    Map(age -> 12, name -> xiaohong)
    Map(address -> xxx, age -> 12, name -> xiaohong, sex -> 1)
    Map(address -> xxx, age -> 12, sex -> 1)
    Map(address -> xxx)
    Map(idCard -> 111)
    

    遍历映射:

    var a1 =  mutable.Map("name"->"xiaoming","age"->12,"address"->"xxx","sex"->1)
    for((k,v) <- a1){
      println(k,v)
    }
    a1.foreach(x=>{
      println(x._1,x._2)
    })
    

    常用方法:

    var a1 =  mutable.Map("name"->"xiaoming","age"->12,"address"->"xxx","sex"->1)
    //判断某个key是否存在
    if(a1.contains("name")){
      println(a1("name"))
    }
    //过滤元素,a1直接就被改变为过滤后的值
    a1 = a1.retain((k,v)=>k.length == 3)
    println(a1)
    //改变元素的值
    a1.transform((k,v)=>v + "1")
    println(a1)
    a1 =  mutable.Map("name"->"xiaoming","age"->12,"address"->"xxx","sex"->1)
    //保留指定的key,一定要将返回结果赋值给新的变量,返回类型为MapLike
    val a2  =a1.filterKeys(_.length > 3)
    println(a2)
    //也可以使用Set集合传递你需要的key
    val a3 = a1.filterKeys(Set("name","age"))
    println(a3)
    //使用filter方法可以任意指定过滤key还是value
    a1 = a1.filter(k=>k._1.length > 3)
    println(a1)
    //take方法可以提取map中的前n个元素,注意如果用Map因为是无序的,每次都不保证取出元素的顺序
    a1 =  mutable.LinkedHashMap("name"->"xiaoming","age"->12,"address"->"xxx","sex"->1)
    a1 = a1.take(2)
    println(a1)
    
    输出:
    xiaoming
    Map(age -> 12, sex -> 1)
    Map(age -> 121, sex -> 11)
    Map(address -> xxx, name -> xiaoming)
    Map(age -> 12, name -> xiaoming)
    Map(address -> xxx, name -> xiaoming)
    Map(name -> xiaoming, age -> 12)
    

    4.Set

    集合的基本操作:

    val a1 = mutable.Set(1,2,3,4)
    a1 += 5
    //集合中的元素是无序的并且是唯一的
    a1 += 1
    println(a1)
    a1 += (6,7)
    println(a1)
    a1 ++= List(8,9)
    println(a1)
    a1.add(10)
    println(a1)
    a1 -= 1
    println(a1)
    a1 -= (2,3)
    println(a1)
    a1 --=Array(4,5)
    println(a1)
    //过滤元素
    a1.retain(_ > 9)
    println(a1)
    
    输出:
    
    Set(1, 5, 2, 3, 4)
    Set(1, 5, 2, 6, 3, 7, 4)
    Set(9, 1, 5, 2, 6, 3, 7, 4, 8)
    Set(9, 1, 5, 2, 6, 3, 10, 7, 4, 8)
    Set(9, 5, 2, 6, 3, 10, 7, 4, 8)
    Set(9, 5, 6, 10, 7, 4, 8)
    Set(9, 6, 10, 7, 8)
    Set(10)
    

    创建有序集合:

    var a1 = SortedSet(1,2,3,4)
    println(a1)
    a1 = a1.filter(v=>v>3)
    println(a1)
    var a2 = mutable.LinkedHashSet(1,2,3,4)
    a2 = a2.filter(v=>v>3)
    println(a2)
    
    输出:
    TreeSet(1, 2, 3, 4)
    TreeSet(4)
    Set(4)
    

    从输出类型上可以看到SortedSet被改变之后输出为TreeSet对象,这是因为SortedSet只有不可变的版本,如果想用可变的集合,可以使用TreeSet。

    5.队列和堆栈
    var a1 = mutable.Queue(1,2,3)
    a1.enqueue(1)
    var a2 = a1.dequeueAll(x=>x>0)
    println(a2)
    println(a1)
    输出:
    ArrayBuffer(1, 2, 3, 1)
    Queue()
    
    
    var a1 = mutable.Stack(1,2,3,4)
    a1.pop()
    println(a1)
    a1.push(1)
    println(a1)
    a1.pop()
    println(a1)
    
    输出:
    Stack(2, 3, 4)
    Stack(1, 2, 3, 4)
    Stack(2, 3, 4)
    
    Process finished with exit code 0
    

    6.强大的Range功能

    var a1 = (1 to 10).toList
    println(a1)
    var a2 =(1 until(10)).toList
    println(a2)
    var a3 = (1 to 10 by(2)).toList
    println(a3)
    var a4 = ('a' to 'm').toList
    println(a4)
    
    输出:
    List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    List(1, 2, 3, 4, 5, 6, 7, 8, 9)
    List(1, 3, 5, 7, 9)
    List(a, b, c, d, e, f, g, h, i, j, k, l, m)
    
    Process finished with exit code 0
    

    上面这些功能在for循环中经常用到。

  • 相关阅读:
    hdoj-1005-Number Sequences
    FOJ-1058-粗心的物理学家
    程序设计第三次作业附加 代码规范
    简单数论
    FOJ-1001-Duplicate Pair
    链表初尝试-链表的构建与输出-指针
    函数递归简单题-hdoj-2044 2018-一只小蜜蜂 母牛的故事
    电路与电子学-第一章直流电路分析方法小概括
    DFS回溯-函数递归-xiaoz triangles
    进制转换 hdoj-2031
  • 原文地址:https://www.cnblogs.com/rickiyang/p/11074185.html
Copyright © 2020-2023  润新知