scala集合

Traversable
常用的方法都在这里,其中注意的是foreach也定义在这
package com.twq.collection.framework
import scala.collection.mutable.ArrayBuffer
/**
* Created by tangweiqun on 2017/12/10.
*/
object TraversableTest {
def main(args: Array[String]): Unit = {
//1、Traversable 中只定义了一个抽象方法: def foreach[U](f: Elem => U)
// 这个方法的功能就是遍历集合中的每一个元素,然后将函数f应用在每一个元素上
// Elem表示集合元素的类型,U表示函数f的返回类型,函数f的结果值将会丢弃
//2、Traversable所有的方法分类以及含义
val xs = Traversable(1, 2, 4, 1)
//抽象方法(Abstract Method)
xs foreach println
//添加方法(Addition)
// 将两个Traversable拼接在一起,或者将Iterator中的所有元素拼接到Traversable中
val ys = Traversable(2, 3)
xs ++ ys
//映射方法(Maps)
// 将一个方法应用到集合中的每一个元素,然后返回新的集合
xs map (i => (i + 1).toString())
xs flatMap (_.to(5))
xs collect { case i if (i == 2) => i * 3 }
//转换方法(Conversions)
//将Traversable转换成更具体的集合
val x = Traversable(2, 3)
x.toArray
x.toList
x.toIterable
x.toSeq
x.toIndexedSeq
x.toStream
x.toSet
//x.toMap // x必须是key value类型的集合
//拷贝方法(Copying)
//将集合元素拷贝到Buffer或者Array中
val buff = new ArrayBuffer[Int]()
xs.copyToBuffer(buff)
val arr = new Array[Int](4)
xs.copyToArray(arr, 1, 2) //从拷贝xs前面两个元素到arr中(从arr的下标为2开始)
//大小信息方法(Size info)
xs.isEmpty
xs.nonEmpty
xs.size
xs.hasDefiniteSize //如果Traversable知道有有限的长度则返回true
//检索元素方法(Element Retrieval)
//对于head和last不是所有的集合返回都是固定值,比如Set,因为Set是无序的
xs.head
xs.headOption
xs.last
xs.lastOption
xs find(_ == 3)
//子集合方法(Subcollections)
xs.tail //除了xs.head的所有的元素集合
xs.tails //Seq(1, 2, 4, 1).tails = Iterator( List(1, 2, 4, 1),List(2, 4, 1),List(4, 1),List(1),Nil)
xs.init //除了xs.last的所有元素的集合
xs.slice(1, 3) //List(2, 4)
xs.take(2)
xs.drop(2) //除了take(2)外的其他元素的集合
xs.takeWhile(_ == 1) //从集合的头开始提取符合条件的数据,一旦碰到不符合的数据元素则退出
xs.dropWhile(_ == 1) //从集合的头开始删除符合条件的数据,一旦碰到不符合的数据元素则退出
xs.filter(_ == 2) //过滤出符合条件的元素的集合
xs.withFilter(_ == 2) //不是严格意义上上的filter,不像filter那样会产生新的集合
xs.filterNot(_ == 2) //过滤出不符合条件的元素的集合
//切分方法(Subdivisions)
//在指定的位置对集合介个, 返回 pair of collections (xs take n, xs drop n)
xs.splitAt(3) //res20: (Seq[Int], Seq[Int]) = (List(1, 2, 4),List(1))
//根据指定的条件对集合进行切割, 返回 pair of collections (xs takeWhile p, xs.dropWhile p)
xs.span(_ == 1) //res22: (Seq[Int], Seq[Int]) = (List(1),List(2, 4, 1))
//返回集合对,第一个集合包括了符合条件的元素的集合,第二个集合包括了不符合条件的元素的集合
//(xs filter p, xs.filterNot p)
xs.partition(_ == 1) //res24: (Seq[Int], Seq[Int]) = (List(1, 1),List(2, 4))
//按照f来group集合成Map
xs.groupBy(_ + 1) //res25: scala.collection.immutable.Map[Int,Seq[Int]] = Map(2 -> List(1, 1), 5 -> List(4), 3 -> List(2))
//元素判断方法(Element Conditions)
xs.forall(_ > 0) //判断集合xs中的所有元素是否大于0
xs.exists(_ > 2) //判断集合xs中是否有大于2的元素
xs.count(_ > 2) //计算集合xs中大于2的数量
//折叠方法(Folds)
//对集合中的连续的元素应用二元操作
(0 /: xs)(_ + _)
xs.foldLeft(0)(_ + _)
(xs :\ 0)(_ + _)
xs.foldRight(0)(_ + _)
xs.reduceLeft(_ + _)
xs.reduceRight(_ + _)
//Specific Folds
xs.sum
xs.product // 元素累乘
xs.min
xs.max
//Strings
val sb = new StringBuilder
xs.addString(sb, "[", ",", "]")
xs.mkString("[", ",", "]")
xs.stringPrefix
//Views
//lazy计算特性的集合
xs.view(1, 3)
}
}
Iterable
提供了外部迭代器方法iterator
package com.twq.collection.framework
/**
* Created by tangweiqun on 2017/11/15.
*/
object IterableTest {
def main(args: Array[String]): Unit = {
//1、trait Iterable提供了iterator方法,可以返回一个用来遍历集合元素的外部迭代器
//2、iterator有两个方法,一个是hasNext,一个是next
//如果集合中还有元素的话,则hasNext返回true,否则返回false
//next返回下一个元素,如果没有下一个元素就会抛异常
//Iterable的超类Traversable中的foreach方法的实现如下:
/**
* def foreach[U](f: Elem => U): Unit = {
val it = iterator
while (it.hasNext) f(it.next())
}
*/
//3、Iterable另一个主要的优点是:有能力的高效的合作迭代两个集合
val names = Iterable("kity", "myte")
val ages = Iterable(32, 34)
val n = names.iterator
val a = ages.iterator
while (n.hasNext && a.hasNext) {
println(s"${n.next()} age is ${a.next()}")
}
//下面的代码效果和上面的是一样的
names.iterator zip ages.iterator map {case
(n, a) => s"${n} age is ${a}"} foreach println
//4、当在可变集合中使用外部迭代器的时候,迭代器背后的集合可能在迭代器不知道的情况下改变了
val x = collection.mutable.ArrayBuffer(1, 2, 3)
val i = x.iterator
//删除x中的所有元素
x.remove(0, 3)
i.hasNext //true
i.next() //java.lang.IndexOutOfBoundsException: 0
//5、Iterable应该用在明确需要外部迭代器,但不需要随机访问的应用场景
//6、所有的方法
val xs = Iterable(1, 2, 4, 2, 3)
//抽象方法(Abstract Method)
val iterator = xs.iterator
while (iterator.hasNext) {
println(iterator.next())
}
//Other Iterators
xs.grouped(2) //res31: Iterator[Iterable[Int]] = Iterator(Iterable(1, 2), Iterable(4, 2), Iterable(3))
xs.grouped(2).toList //res32: List[Iterable[Int]] = List(List(1, 2), List(4, 2), List(3))
xs.sliding(2).toList //res35: List[Iterable[Int]] = List(List(1, 2), List(2, 4), List(4, 2), List(2, 3))
//Subcollections
xs.takeRight(3)
xs.dropRight(3)
//Zippers
val ys = Iterable(3, 1, 1)
xs.zip(ys)
xs.zipAll(ys, 99, 999) // 后面指定的两个元素分别 代表 xs和ys的 空补元素
xs.zipWithIndex
//Comparison
xs sameElements ys //false
}
}
WhyTraversable
package com.twq.collection.framework
import java.io.{BufferedReader, File, FileReader}
/**
* Created by tangweiqun on 2017/12/10.
*/
object WhyTraversable {
def main(args: Array[String]): Unit = {
//1、Iterable缺点一:有一些非标准的集合很难实现外部迭代器,就比如:FileLineTraversable
//FileLineTraversable需要知道迭代是否已经完成,完成的话则需要关闭资源,这个利用外部迭代器很难做到
//所以继承Iterable的都是标准的集合
}
}
class FileLineTraversable(file: File) extends Traversable[String] {
//1、trait Traversable就定义了一个接口,就是foreach
//这个属于内部迭代,无法提供高效的随机访问能力
override def foreach[U](f: (String) => U): Unit = {
println("Opening file")
val input = new BufferedReader(new FileReader(file))
try {
var line = input.readLine()
while (line != null) {
f(line)
line = input.readLine()
}
println("Done iteration file")
} finally {
println("Closing file")
input.close()
}
}
override def toString(): String = s"{Lines of ${file.getAbsolutePath}}"
}
Arrays
package com.twq.collection.framework.seq
import scala.reflect.ClassTag
/**
* Created by tangweiqun on 2017/12/10.
*/
object ArraysTest {
def main(args: Array[String]): Unit = {
//Array是一种特殊的集合。Scala中的数组和Java中的数组是一对一的,比如:
//Array[Int]对应着java中int[],Array[String]对应着java中的String[]等
//但是scala中的Array比java中的数组功能更强大:
//1、Scala中的Array是带有类型参数的,比如Array[T] ==> T[]
//在构建泛型数组的时候需要让编译器将泛型类型告知运行时。因为:
// (1)运行时需要根据类型来构建不同的jvm数组
// (2)所有的泛型在运行的时候都是擦除的
def evenElems[T : ClassTag](xs: Vector[T]): Array[T] = {
val arr = new Array[T]((xs.length + 1) / 2)
for (i <- 0 until xs.length by 2)
arr(i / 2) = xs(i)
arr
}
//2、Scala中的Array是兼容Seq的,比如:
def test(seq: Seq[Int]) = seq.foreach(println)
test(Array(1, 2, 3)) //可以将Array传给Seq
val a1 = Array(1, 2, 3)
val seq: Seq[Int] = a1
//这个是因为在scala.LowPriorityImplicits中含有一个隐式转换,
// 这个隐式转换将Array[T]转换成WrappedArray[T]类型,而WrappedArray[T]是Seq的子类
//3、Scala中的Array支持Seq中的所有方法,比如:
val a2 = a1 map (_ * 3)
val a3 = a2 filter (_ % 2 != 0)
a3.reverse
//这个是因为在scala.PreDef中存在一个隐式转换,
// 这个隐式转换是将Array[T]类型转换称ArrayOps[T]类型,ArrayOps并不是Seq的子类,但是包含了Seq中的所有方法
//4、两个问题:
//4.1、为什么会存在两个隐式转换呢?
//第一个转成WrappedArray[T]是为了使得Array兼容Seq。如果你调用WrappedArray[T]中的方法,那么返回的就是WrappedArray[T]
val seqTmp: Seq[Int] = a1
seqTmp.reverse //res2: Seq[Int] = WrappedArray(3, 2, 1).... 这个并不是我们想要的
val ops: collection.mutable.ArrayOps[Int] = a1
ops.reverse // res3: Array[Int] = Array(3, 2, 1) 这个才是我们想要的
scala.Predef
//4.2、有两个隐式转换的话,那怎么能找对是哪个隐式转换呢?
//两个隐式转换的查找是有优先级的:
//scala.LowPriorityImplicits是scala.PreDef的父类,所以隐式查找的时候会去先查找scala.PreDef中的隐式转换
//所以对于Array方法的调用,肯定会先找到scala.PreDef中的隐式转换
//对于Array兼容Seq则会找到scala.LowPriorityImplicits中的隐式转换,因为ArrayOps并不是Seq的子类
}
}
Buffers可变集合
package com.twq.collection.framework.seq
/**
* Created by tangweiqun on 2017/12/10.
*/
object BuffersTest {
def main(args: Array[String]): Unit = {
//可变集合Buffer是Seq的一个子类
//它不仅允许更新元素的更新,而且允许元素的插入和删除
//ListBuffer 和 ArrayBuffer
//5、可变集合Buffer的方法
val buffer = scala.collection.mutable.Buffer(1, 2, 3, 1, 4) //Buffer的默认实现是ArrayBuffer
//Additions
buffer += 99
buffer += (88, 100)
buffer ++= Seq(1, 2, 3)
101 +=: buffer
Seq(1, 2, 3) ++=: buffer
buffer.insert(3, 99999)
buffer.insertAll(2, Seq(22, 33))
//Removals
buffer -= 99
buffer.remove(3)
buffer.remove(3, 4) // 索引位置 移除个数
buffer.trimStart(4) // 从头开始算 裁掉4个
buffer.trimEnd(2) // 从尾开始算 裁掉2个
buffer.clear()
//Cloning
buffer.clone()
}
}
Seq
package com.twq.collection.framework.seq
import scala.annotation.tailrec
import scala.collection.LinearSeq
/**
* Created by tangweiqun on 2017/11/15.
* Seq是一个有长度且其元素都有一个固定的下标值(从0开始)的Iterable
*/
object SeqTest {
def main(args: Array[String]): Unit = {
//1、trait Seq是通过length和apply两个接口方法定义的,代表连续有序(有序并不代表排序sorted)的集合
//apply是根据序号进行索引操作,而length则是返回集合的大小
//Seq不对索引或者length做任何的性能保证,仅用来将有序集合和Set/Map区分开
//也就是说,如果元素插入集合的顺序是重要的,并且允许重复元素,那么就使用Seq
//比如:记录采用的音频数据,其记录的顺序对于数据的处理是非常重要的
val x = Seq(2, 1, 30, -2, 20, 1, 2, 1)
x.tails map (_.take(2)) filter (_.length > 1) map (_.sum) toList
//res4: List[Int] = List(3, 31, 28, 18, 21, 3, 2)
//效果和上面是一样的,我们推荐使用sliding,而不是tails
x.sliding(2).map(_.sum).toList
//res4: List[Int] = List(3, 31, 28, 18, 21, 3, 2)
//2、所有的方法
val seq = Seq(1, 2, 4, 2, 1, 1) //Seq的默认实现是不可变集合List
//Indexing and Length
seq(2)
seq.apply(2)
seq.isDefinedAt(4) //判断是否存在这个索引
seq.length
seq.lengthCompare(4) //如果seq的长度比4小则返回-1,长度比4大则返回1,否则返回0
seq.indices // 所有的下标
//Index Search
seq.indexOf(3) //获取元素的下标
seq.lastIndexOf(1)
seq.indexOfSlice(Seq(2, 1), 2) //从seq的下标为2的位置开始,返回Seq(2, 1)在seq中的位置
seq.lastIndexOfSlice(Seq(2, 1), 2) //到2为止
seq.indexWhere(_ == 1, 2) //从seq的下标为2的位置开始,返回符合条件的下标
seq.segmentLength(_ == 1, 2) //从seq的下标为2的位置开始,返回连续符合条件的元素的个数,如果碰到不符合条件的元素则直接返回
seq.prefixLength(_ == 1) //返回连续符合条件的元素的个数,如果碰到不符合条件的元素则直接返回
//Additions
3 +: seq
seq :+ 3
seq.padTo(10, 3) // 扩充seq 不足补3
//Updates
seq.patch(2, Seq(88, 99), 3) //从seq的下标2开始将seq长度为3的元素集合替换为Seq(88, 99)
seq.updated(2, 100)
//Sorting
seq.sorted
seq.sortWith(_ < _)
seq.sortBy(_ % 2)
val person = Seq(People("kk", 23), People("mm", 21), People("mssm", 81))
implicit object PersonOrdering extends Ordering[People] {
override def compare(x: People, y: People): Int = x.age - y.age
}
person.sorted
//Reversals
seq.reverse
seq.reverseIterator //和seq.reverse.iterator一样,但是会更加的高效
seq.reverseMap(_ + 3)
//Comparisons
val ys = Seq(2, 3, 1, 1)
seq.startsWith(ys, 2) //seq 偏移2个元素 是否以ys开始
seq.endsWith(ys)
seq.contains(3)
seq.containsSlice(ys)
(seq.corresponds(ys))((x, y) => x + y == 4) //判断两个序列的元素对应起来是否符合条件
//Multiset Operations
seq.intersect(ys)
seq.diff(ys)
seq.union(ys)
seq.distinct
//3、trait LinearSeq表示能够分割为头元素 + 尾集合的集合,是Seq的子类
//定义了三个方法:isEmpty(集合是否非空)、head(非空集合的第一个元素)
// 和tail(去掉第一个元素剩下的所有元素的集合)
//这种集合类型通过头元素分割集合的尾递归算法非常的理想
val linearSeq = LinearSeq(1, 2, 3)
linearSeq.head
linearSeq.tail
linearSeq.isEmpty
val tree = Branch(1, Leaf(2), Branch(3, Leaf(4), NilTree))
traverse(tree)(println)
//当需要把一个普通递归的算法转化成尾递归或者循环算法时,
// 在堆(heap)上手工创建一个栈(stack),然后用这个栈来完成实际功能是一种常见的做法
//在使用函数式风格的尾递归算法时,LinearSeq是一个恰当的选择
//List是常用的LinearSeq的实现集合
//4、IndexedSeq也是Seq的子类,它在随机访问的时候更为高效
val indexedSeq = IndexedSeq(1, 2, 3) //默认情况下是创建一个不可变的Vector
indexedSeq.updated(1, 5)//将集合中下标为1的值改成5,生成一个新的集合
//访问IndexedSeq
indexedSeq.apply(1)
indexedSeq(2)
//Array和ArrayBuffer是常用的IndexedSeq的实现集合
//Vector同时支持高效的线形访问和随机访问,如果场景需要线形访问和随机访问的话,则用Vector
//5、LinearSeq和IndexedSeq都包含可变和不可变的
val immutableLinearSeq = scala.collection.immutable.LinearSeq(1, 2, 3)
val mutableLinearSeq = scala.collection.mutable.LinearSeq(1, 2, 3)
val immutableIndexedSeq = scala.collection.immutable.IndexedSeq(1, 2, 3)
val mutableIndexedSeq = scala.collection.mutable.IndexedSeq(1, 2, 3)
//可变和不可变都有updated方法,都是返回一个新的Seq集合
immutableIndexedSeq.updated(1, 5)
mutableIndexedSeq.updated(1, 5)
//update只有是可变集合有,改变原集合,不产生新的集合
mutableIndexedSeq.update(1, 5)
//immutableIndexedSeq.update(1, 5) 不存在的方法
}
def traverse[A, U](t: BinaryTree[A])(f: A => U): Unit = {
@tailrec
def traverseHelper(current: BinaryTree[A],
next: LinearSeq[BinaryTree[A]]): Unit = {
current match {
case Branch(value, lhs, rhs) =>
f(value)
traverseHelper(lhs, rhs +: next)
case Leaf(value) if !next.isEmpty =>
f(value)
traverseHelper(next.head, next.tail)
case Leaf(value) =>
f(value)
case NilTree if !next.isEmpty =>
traverseHelper(next.head, next.tail)
case NilTree => ()
}
}
traverseHelper(t, LinearSeq())
}
}
sealed trait BinaryTree[+A]
case object NilTree extends BinaryTree[Nothing]
case class Branch[+A](value: A,
lhs: BinaryTree[A],
rhs: BinaryTree[A]) extends BinaryTree[A]
case class Leaf[+A](value: A) extends BinaryTree[A]
case class People(name: String, age: Int)
Streams
package com.twq.collection.framework.seq
/**
* Created by tangweiqun on 2017/12/10.
*/
class StreamsTest {
def main(args: Array[String]): Unit = {
//1、Stream结构和List是一样的,但是它是延迟计算的,只有被访问到的元素才会计算
// 所以呢Stream可以无限长,Stream的性能和List是一样的
//2、List是用 :: 操作符来拼接元素,而Stream使用 #:: 来拼接元素
val str = 1 #:: 2 #:: 3 #:: Stream.empty
//3、例子:求斐波那契数列
//如果将下面的 #:: 修改成 :: 将会导致死循环
def fibFrom(a: Int, b: Int): Stream[Int] =
a #:: fibFrom(b, a + b)
val fibs = fibFrom(1, 1).take(7)
fibs.foreach(println)
fibs.toList
}
}
Strings
package com.twq.collection.framework.seq
/**
* Created by tangweiqun on 2017/12/10.
*/
object StringsTest {
def main(args: Array[String]): Unit = {
val str = "hello"
str.reverse
str.map(_.toUpper)
str drop 3
str slice (1, 4)
val s: Seq[Char] = str
//为什么String有如上的功能呢?是因为存在两个隐式转换
//第一个是低级别的隐式转换:将String类型转换成WrappedString类型,
// WrappedString是immutable.IndexedSeq的子类
//第二个是高级别的隐式转换:将String类型转换成StringOps对象,
// StringOps对象中含有immutable.IndexedSeq中的所有方法
}
}
Vectors
package com.twq.collection.framework.seq
/**
* Created by tangweiqun on 2017/12/10.
*/
class VectorsTest {
def main(args: Array[String]): Unit = {
//1、对List的头进行增删改查是一件不耗时的操作,但是对List的非头部分的增删改查是一件比较耗时的操作
//而vector则是可以高效的支持任意位置的增删改查
val vec = scala.collection.immutable.Vector.empty
val vec2 = vec :+ 1 :+ 2
val vec3 = 100 +: vec2
vec3(0)
//2、vector是不可变的
val vec4 = Vector(1, 2, 3)
vec4 updated (2, 4) //返回新的vector,而vec4不改变
//3、因为vector可以高效的支持任意位置的增删改查,所以IndexedSeq的默认实现就是vector
collection.immutable.IndexedSeq(1, 2, 3)
//4、vector的数据结构
//TODO
}
}
Map
package com.twq.collection.framework.map
import java.util.concurrent.TimeUnit
/**
* Created by tangweiqun on 2017/11/16.
*/
object MapTest {
def main(args: Array[String]): Unit = {
//1、在scala.Predef中定义了一个隐式转换,把A -> B 的表达式转换为元组(A, B)
val errorCodes = Map(1 -> "NOES", 2 -> "KTHXBAI", 3 -> "ZOMG")
//2、Map能用作从键类型到值类型的偏函数
val result = List(1, 3) map errorCodes //result: List[String] = List(NOES, ZOMG)
//3、Map还提供了当键不存在时返回默认值的能力
val addresses = Map("katy" -> "someplace 123").withDefaultValue("default place")
addresses("john") //default place
//4、在scala社区中一般习惯直接用通用的Map类型
//所有的方法:
val ms = Map("x" -> 24, "y" -> 25, "z" -> 26) //默认类型是scala.collection.immutable.Map
//Lookups
ms.get("x")
ms("x")
ms.getOrElse("c", 33)
ms.contains("c")
ms.isDefinedAt("d") //Same as contains
//Additions and Updates
ms + ("c" -> 33)
ms + ("c" -> 33, "d" -> 34)
ms ++ Map("f" -> 32, "h" -> 88)
ms.updated("x", 23) //效果和ms + (k -> v)一样
//Removals
ms - "c"
ms - ("x", "y", "d")
ms -- (Seq("c", "d"))
//Subcollections
ms.keys
ms.keySet
ms.keysIterator
ms.values
ms.valuesIterator
//Transformation
ms.filterKeys(_.contains("c"))
ms.mapValues(_ + 4)
//可变的Map的方法:
val mutableMap = scala.collection.mutable.Map("x" -> 24, "y" -> 25, "z" -> 26) // scala.collection.mutable.Map
//Additions and Updates
mutableMap("x") = 99
mutableMap += ("c" -> 98)
mutableMap += ("d" -> 98, "m" -> 77)
mutableMap ++= Map("l" -> 2)
mutableMap.put("v", 23)
mutableMap.getOrElseUpdate("l", 8)
//可以用于缓存,如下:
val cache = collection.mutable.Map[String, String]()
def cachedF(s: String) = cache.getOrElseUpdate(s, f(s)) //第二个参数是by-name参数,用的时候才会取计算
cachedF("abd")
cachedF("abd")
def cachedF_1(arg: String) = cache get arg match {
case Some(result) => result
case None =>
val result = f(arg)
cache(arg) = result
result
}
//Removals
mutableMap -= "c"
mutableMap -= ("x", "y", "d")
mutableMap --= (Seq("c", "d"))
mutableMap.remove("v")
mutableMap.retain((key, value) => key != "d")
mutableMap.clear()
//Transformation
mutableMap.transform((key, value) => value + 23)
//Cloning
mutableMap.clone()
}
def f(x: String) = {
println("taking my time.");
TimeUnit.SECONDS.sleep(2)
x.reverse
}
}
Set
package com.twq.collection.framework.set
/**
* Created by tangweiqun on 2017/11/15.
*/
object SetTest {
def main(args: Array[String]): Unit = {
//Set 提供了:
// 1、高效的检查集合是否包含某元素的实现
// 2、元素去重的功能
//set的另一个特性: 可以用作过滤函数
(0 to 100) filter Set(2, 3, 4) //Set(2, 3, 4)就是一个过滤函数
//所有的方法:
val fruit = Set("apple", "orange", "peach", "banana") //默认实现是scala.collection.immutable.Set
//Tests
fruit.contains("apple")
fruit("apple") //和fruit.contains("apple")功能是一样的
fruit.subsetOf(Set("apple", "orange", "peach", "banana", "tes"))
//Additions
fruit + "pear"
fruit + ("pear", "grape")
fruit ++ Seq("grape")
//Removals
fruit - "pear"
fruit - ("pear", "grape")
fruit -- Seq("grape")
fruit.empty
//Binary Operations
fruit & Set("orange")
fruit.intersect(Set("orange"))
fruit | Set("orange")
fruit.union(Set("orange"))
fruit &~ Set("orange")
fruit.diff(Set("orange"))
//可变Set新增的方法
val mutableSet = scala.collection.mutable.Set(1, 2, 3, 4, 1)
//Additions
mutableSet += 99
mutableSet += (88, 109)
mutableSet ++= Seq(22, 11, 23)
mutableSet.add(999)
//Removals
mutableSet -= 99
mutableSet -= (88, 109)
mutableSet --= Seq(22, 11, 23)
mutableSet.remove(999)
mutableSet.retain(_ > 10) //保留大于10的元素
mutableSet.clear()
//Update
mutableSet(999999) = true
mutableSet.update(999999, true) //两者功能是一样的
//Cloning
mutableSet.clone()
}
}
Views
package com.twq.collection.framework.view
/**
* Created by tangweiqun on 2017/12/10.
*/
object ViewsTest {
def main(args: Array[String]): Unit = {
//view 的作用
val v = Vector(1 to 10: _*)
val result1 = v.map(_ + 1) // strict
val result2 = result1.map(_ * 2)
val vv = v.view
val result3 = vv.map(_ + 1) // non-strict(lazy)
val result4 = result3.map(_ * 2)
result4.force
//view的两个使用场景
//1、消除中间结果,提升性能
def isPalindrome(x: String) = x == x.reverse
def findPalindrome(s: Seq[String]) = s find isPalindrome
val words = Seq("test", "tttt", "man", "sd", "444", "45", "", "")
findPalindrome(words take 100000) //会产生中间结果
findPalindrome(words.view take 100000) //不会产生中间结构
//2、view和可变集合的配合
val arr = (0 to 9).toArray
val subarr = arr.view.slice(3, 6)
def negate(xs: collection.mutable.Seq[Int]) =
for (i <- 0 until xs.length) xs(i) = -xs(i)
negate(subarr)
arr //部分元素被修改了
//对于数据量比较少的集合的操作,建议使用strict模式,而不要采用view的模式
//因为对于数据量少的集合使用view的开销可能还比产生中间结果的要大
}
}
与java进行转换
package com.twq.collection.framework.conversions
import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer
/**
* Created by tangweiqun on 2017/12/22.
*/
object Conversions {
def main(args: Array[String]): Unit = {
import scala.collection.JavaConversions._
/**
* 双向转换
* Iterator <--> java.util.Iterator
* Iterator <--> java.util.Enumeration
* Iterable <--> java.util.Iterable
* Iterable <--> java.util.Collection
* mutable.Buffer <--> java.util.List
* mutable.Set <--> java.util.Set
* mutable.Map <--> java.util.Map
*/
val jul: java.util.List[Int] = ArrayBuffer(1, 2, 3)
val buf: mutable.Buffer[Int] = jul
val m: java.util.Map[String, Int] = mutable.HashMap("abc" -> 1, "hello" -> 2)
val map: mutable.Map[String, Int] = m
/*
单向转换
* Seq --> java.util.List
* mutable.Seq --> java.util.List
* Set --> java.util.Set
* Map --> java.util.Map
*/
val javaul: java.util.List[Int] = List(1, 2, 3)
javaul.add(2)
}
}


浙公网安备 33010602011771号