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)
  }
}

 

posted @ 2020-05-22 08:52  财经知识狂魔  阅读(191)  评论(0编辑  收藏  举报