Scala 容器类(三)

Set

集合是不包含重复元素的可迭代对象。

Set 类的操作

操作 说明
xs subsetOf ys 测试 xs 是否是 ys 的子集
xs ++ ys 包含 xs 中所有元素及 ys 中所有元素的集合
xs -- ys xs 中所有元素,去掉 ys 中所有元素后剩下的部分
xs.empty 与 xs 同类的空集合(非xs)
xs &~ ys 集合 xs 和 ys 的差集
mutable.Set 类的操作
操作 说明
xs ++= ys 添加集合 ys 中的所有元素到集合 xs 中,并返回 xs 本身。(表达式有副作用)
xs add x 把元素 x 添加到集合 xs 中,如集合 xs 之前没有包含 x,该操作返回 true,否则返回 false
xs retain p 只保留集合 xs 中满足条件 p 的元素
xs.clear() 删除集合 xs 中的所有元素
xs(x) = b/xs.update(x, b) 参数 b 为布尔类型,如果值为 true 就把元素x加入集合 xs,否则从集合 xs 中删除 x

可变集合和不可变集合提供了+和++操作符来添加元素,-和--用来删除元素。但是这些操作在可变集合中通常很少使用,因为这些操作都要通过集合的拷贝来实现。更有效率的方法是+=和-=,另外还有批量操作符++=和--=。
目前可变集合默认使用哈希表来存储集合元素,非可变集合则根据元素个数的不同,使用不同的方式来实现。空集用单例对象来表示。元素个数小于等于4的集合可以使用单例对象来表达,元素作为单例对象的字段来存储。 元素超过4个,非可变集合就用哈希前缀树(hash trie)来实现。

采用这种表示方法,较小的不可变集合(元素数不超过4)往往会比可变集合更加紧凑和高效。所以,在处理小尺寸的集合时,不妨试试不可变集合。

集合的两个特质是 SortedSet 和 BitSet.

SortedSet

SortedSet 是指以特定的顺序(可以在创建集合时设置顺序)排列其元素(使用iterator或foreach)的集合,默认表示是有序二叉树,即左子树上的元素小于所有右子树上的元素。这样,一次简单的顺序遍历能按增序返回集合中的所有元素。Scala的类 immutable.TreeSet 使用红黑树实现,它在维护元素顺序的同时,也会保证二叉树的平衡,即叶节点的深度差最多为1。

创建一个新的TreeSet,可以先定义排序规则,然后利用排序规则创建树集。

val myOrdering = Ordering.fromLessThan[Int](_ < _)
TreeSet.empty(myOrdering)

或者,也可以不指定排序规则参数,只需要给定一个元素类型或空集合。在这种情况下,将使用此元素类型默认的排序规则。

TreeSet.empty[String]

BitSet

BitSet是由单字或多字的紧凑位实现的非负整数的集合。其内部使用 Long 型数组来表示。第一个 Long 元素表示的范围为0到63,第二个范围为64到127,以此类推(值为0到127的非可变位集合通过直接将值存储到第一个或第两个 Long 字段的方式,优化掉了数组处理的消耗)。对于每个 Long,如果有相应的值包含于集合中则它对应的位设置为1,否则该位为0。
位集合的大小取决于存储在该集合的最大整数的值的大小。假如N是为集合所要表示的最大整数,则集合的大小就是 N/64 个长整形字,或者 N/8 个字节,再加上少量额外的状态信息字节。

当位集合包含的元素值都比较小时,它比其他的集合类型更紧凑。位集合的另一个优点是它的 contains 方法(成员测试)、+= 运算(添加元素)、-= 运算(删除元素)都非常的高效。

Map

Map是一种可迭代的键值对结构。Scala的Predef类提供了隐式转换,允许使用另一种语法:key -> value 代替(key,value)

Map类的操作
操作 说明
查询操作
ms get k 返回一个Option,其中包含和键k关联的值。若k不存在,则返回None
ms(k) (完整写法是ms apply k)返回和键k关联的值。若k不存在,则抛出异常
ms getOrElse (k, d) 返回和键k关联的值。若k不存在,则返回默认值d
ms contains k 检查ms是否包含与键k相关联的映射
ms isDefinedAt k 同contains
添加及更新
ms + (k -> v) 返回一个同时包含ms中所有键值对及从k到v的键值对k -> v的新映射
ms ++ kvs 返回一个同时包含ms中所有键值对及kvs中的所有键值对的新映射
ms updated (k, v) 同ms + (k -> v)
移除
ms - k 返回一个包含ms中除键k以外的所有映射关系的映射
ms - (k, 1, m) 返回一个滤除了ms中与所有给定的键相关联的映射关系的新映射
ms - ks
子容器
ms.keys 返回一个用于包含ms中所有键的iterable对象(注意iterable对象与iterator的区别)
ms.keySet 返回一个包含ms中所有的键的Set
ms.keysIterator 返回一个用于遍历ms中所有key的迭代器
ms.values 返回一个包含ms中所有值的iterable对象
ms.valuesIterator 返回一个用于遍历ms中所有值的迭代器
变换
ms filterKeys p 一个映射视图(Map View),其包含一些ms中的映射,且这些映射的键满足条件p。用条件谓词p过滤ms中所有的键,返回一个仅包含与过滤出的键值对的映射视图
ms mapValues f 用f将ms中每一个键值对的值转换成一个新的值,进而返回一个包含所有新键值对的映射视图

这里只练习几个陌生的操作。
REPL:

scala> val ms = Map(1->"a",2->"b",3->"c")
ms: scala.collection.immutable.Map[Int,String] = Map(1 -> a, 2 -> b, 3 -> c)

scala> ms.contains(3)
res0: Boolean = true

scala> ms.isDefinedAt(1)
res2: Boolean = true

scala> ms.keys
res6: Iterable[Int] = Set(1, 2, 3)

scala> ms.keySet
res7: scala.collection.immutable.Set[Int] = Set(1, 2, 3)

scala> ms.keysIterator
res8: Iterator[Int] = <iterator>

scala> res8.next()
res9: Int = 1

scala> res8.next()
res10: Int = 2

scala> ms.valuesIterator
res12: Iterator[String] = <iterator>

scala> ms.view.filterKeys(_>=1)  //用ms.view.filterKeys 代替 ms.filterKeys
res14: scala.collection.MapView[Int,String] = MapView(<not computed>)

mutable.Map类的操作

操作 说明
添加及更新
ms(k) = v (完整形式为ms.update(x, v))。向映射ms中新增一个以k为键、以v为值的映射关系,ms先前包含的以k为值的映射关系将被覆盖
ms += (k -> v) 向映射ms增加一个以k为键、以v为值的映射关系,并返回ms自身
ms += (k -> v, l -> w) 向映射ms中增加给定的多个映射关系,并返回ms自身
ms ++= kvs 向映射ms增加kvs中的所有映射关系,并返回ms自身
ms put (k, v) 向映射ms增加一个以k为键、以v为值的映射,并返回一个Option,其中可能包含此前与k相关联的值
ms getOrElseUpdate (k, d) 如果ms中存在键k,则返回键k的值。否则向ms中新增映射关系k -> v并返回d
移除
ms -= k 从映射ms中删除以k为键的映射关系,并返回ms自身
ms -= (k, l, m) 从映射ms中删除与给定的各个键相关联的映射关系,并返回ms自身
ms –= ks 从映射ms中删除与ks给定的各个键相关联的映射关系,并返回ms自身
ms remove k 从ms中移除以k为键的映射关系,并返回一个Option,其可能包含之前与k相关联的值
ms retain p 仅保留ms中键满足条件谓词p的映射关系
ms.clear() 删除ms中的所有映射关系
变换
ms transform f 以函数f转换ms中所有键值对(译注:原文比较含糊,transform中参数f的类型是(A, B) => B,即对ms中的所有键值对调用f,得到一个新的值,并用该值替换原键值对中的值)
克隆
ms.clone 返回一个新的可变映射(Map),其中包含与ms相同的映射关系

Synchronized Sets and Maps

无论什么样的Map实现,只需混入SychronizedMap trait,就可以得到对应的线程安全版的Map。例如,我们可以像下述代码那样在HashMap中混入SynchronizedMap。

import scala.collection.mutable.{Map,SynchronizedMap,HashMap}
object MapMaker{
    def makeMap: Map[String,String] = {
        new HashMap[String,String] with SynchronizedMap[String,String]{  //注意这里的with
            override def default(key: String) = "why do you want to know"
        }
    }
}

当向某个Map查询给定的键所对应的值,而Map中不存在与该键相关联的值时,默认情况下会触发一个NoSuchElementException异常。不过,如果自定义一个Map类并覆写default方法,便可以针对不存在的键返回一个default方法返回的值。

同步集合(synchronized set)的创建方法与同步映射(synchronized map)类似。

import scala.collection.mutable
val synchroSet = new mutable.HashSet[Int] with mutable.SynchronizedSet[Int]

另外,这里加两个例子理解with也就是Class Composition with mixins

abstract class A { val message: String }
class B extends A { val message = "I'm an instance of B"}
trait C extends A { def loudMessage = message.toUpperCase() }
class extends B with C

val d = new D
println(d.message)  //I'm an instance of class B
println(d.loudMessage) //I'M AN INSTANCE OF CLASS B
abstract class AbsIterator{
    type T
    def hasNext: Boolean
    def next(): T
}

class StringIterator(s: String) extends AbsIterator{
    type T = Char
    private var i = 0 
    def hasNext = i < s.length
    def next() = {
        val ch = s charAt i 
        i += 1
        ch
    }
}

trait RichIterator extends AbsIterator{
    def foreach(f: T => Unit): Unit = while(hasNext) f(next())
}

class RichStringIterator extends StringIterator("Scala") with RichIterator


val richStringIter = new RichStringIterator
richStringIter foreach println   

//结果 
//S
//c
//a
//l
//a
posted @   憨憨的  阅读(187)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗
点击右上角即可分享
微信分享提示