Scala集合

附上Effective Scala:Effective Scala
学习笔记摘抄于Twitter scala文档:Twitter.github.io
为了方便,本文中类的定义代码和调用代码同放一处;
实际上,代码的调用需要写在程序入口(main方法)

一、Basic Data Structures

Arrays

Arrays preserve order, can contain duplicates, and are mutable.(有序,可重复,可修改)

val numbers = Array(1, 2, 3, 4, 5, 1, 2, 3, 4, 5)
val two = numbers(1)

Lists

Lists preserve order, can contain duplicates, and are immutable.(有序,可重复,不可修改)

val numbers = List(1, 2, 3, 4, 5, 1, 2, 3, 4, 5)
numbers(3) = 10
:9: error: value update is not a member of List[Int]
             numbers(3) = 10

Sets

Sets do not preserve order and have no duplicates.(无序,不重复)

val numbers = Set(1, 2, 3, 4, 5, 1, 2, 3, 4, 5)
println(numbers) //Set(5, 1, 2, 3, 4)

Tuple

A tuple groups together simple logical collections of items without using a class.
Unlike case classes, they don’t have named accessors, instead they have accessors that are named by their position and is 1-based rather than 0-based.(下标从1开始)

val hostPort = ("localhost", 80)
val host = hostPort._1
val port = hostPort._2

Tuples fit with pattern matching nicely.

hostPort match {
  case ("localhost", port) => ...
  case (host, port) => ...
}

Tuple has some special sauce for simply making Tuples of 2 values:->

val t  = 1 -> 2
println(t) //(1,2)

Maps

Map(1 -> 2, 2 -> 3) //or Map((1,2), (2,3)) 
Map("foo" -> "bar")
Map(1 -> Map("foo" -> "bar")) //value is a  map
Map("timesTwo" -> { timesTwo(_) }) //value is a function

This looks like special syntax but remember back to our discussion of Tuple that -> can be used to create Tuples.

Option

Option is a container that may or may not hold something.
The basic interface for Option looks like:

trait Option[T] {
  def isDefined: Boolean
  def get: T
  def getOrElse(t: T): T
}

Option itself is generic and has two subclasses: Some[T] or None

val numbers = Map("one" -> 1, "two" -> 2)
val res = numbers.get("two")  //Some(2)
val res1 = numbers.get("Two") //None

getOrElse lets you easily define a default value.

val result = res1.getOrElse(0) * 2

二、Functional Combinators(组合子)

map

Evaluates a function over each element in the list, returning a list with the same number of elements.

val numbers = List(1, 2, 3, 4)
numbers.map((i: Int) => i * 2)

def timesTwo(i: Int): Int = i * 2
numbers.map(timesTwo) //pass in a function 

foreach

foreach is like map but returns nothing. foreach is intended for side-effects only.

numbers.foreach((i: Int) => i * 2)

filter

removes any elements where the function you pass in evaluates to false. Functions that return a Boolean are often called predicate(谓语) functions.

val newNumbers = numbers.filter((i: Int) => i % 2 == 0)  //List(2, 4)

def isEven(i: Int): Boolean = i % 2 == 0
numbers.filter(isEven)

zip

zip aggregates the contents of two lists into a single list of pairs.

List(1, 2, 3).zip(List("a", "b", "c")) //List((1,a), (2,b), (3,c))

partition

partition splits a collection based on where it falls with respect to a predicate function.
partition将使用给定的谓词函数分割列表。

val numbers = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
numbers.partition(_ % 2 == 0)) //(List(2, 4, 6, 8, 10),List(1, 3, 5, 7, 9))

find

find returns the first element of a collection that matches a predicate function.

numbers.find((i: Int) => i > 5)  //Some(6)

drop & dropWhile

drop drops the first i elements
dropWhile removes the first elements that match a predicate function. For example, if we dropWhile odd numbers from our list of numbers, 1 gets dropped (but not 3 which is “shielded” by 2).
dropWhile 将删除元素直到找到第一个匹配谓词函数的元素。例如,如果我们在numbers列表上使用dropWhile奇数的函数, 1将被丢弃(但3不会被丢弃,因为他被2“保护”了)。

numbers.drop(5) //List(6, 7, 8, 9, 10)
numbers.dropWhile(_ % 2 != 0)  //List(2, 3, 4, 5, 6, 7, 8, 9, 10)

foldLeft

numbers.foldLeft(0)((m: Int, n: Int) => m + n) //55

0 is the starting value (Remember that numbers is a List[Int]), and m
acts as an accumulator.

scala> numbers.foldLeft(0) { (m: Int, n: Int) => println("m: " + m + " n: " + n); m + n }
m: 0 n: 1
m: 1 n: 2
m: 3 n: 3
m: 6 n: 4
m: 10 n: 5
m: 15 n: 6
m: 21 n: 7
m: 28 n: 8
m: 36 n: 9
m: 45 n: 10
res0: Int = 55

foldRight

Is the same as foldLeft except it runs in the opposite direction.

scala> numbers.foldRight(0) { (m: Int, n: Int) => println("m: " + m + " n: " + n); m + n }
m: 10 n: 0
m: 9 n: 10
m: 8 n: 19
m: 7 n: 27
m: 6 n: 34
m: 5 n: 40
m: 4 n: 45
m: 3 n: 49
m: 2 n: 52
m: 1 n: 54
res0: Int = 55

flatten

flatten collapses one level of nested structure.

List(List(1, 2), List(3, 4)).flatten //List(1, 2, 3, 4)

flatMap

flatMap is a frequently used combinator that combines mapping and flattening. flatMap takes a function that works on the nested lists and then concatenates the results back together.

val nestedNumbers = List(List(1, 2), List(3, 4))
nestedNumbers.flatMap(x => x.map(_ * 2)) //List(2, 4, 6, 8)
nestedNumbers.map((x: List[Int]) => x.map(_ * 2)).flatten ////List(2, 4, 6, 8)

Think of it as short-hand for mapping and then flattening.

Generalized functional combinators

Interestingly, every functional combinator shown above can be written on top of fold.

def ourMap(numbers: List[Int], fn: Int => Int): List[Int] = {
  numbers.foldRight(List[Int]()) { (x: Int, xs: List[Int]) =>
    fn(x) :: xs
  }
}

ourMap(numbers, timesTwo(_)) //List(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)

Why List[Int]()? Scala wasn’t smart enough to realize that you wanted an empty list of Ints to accumulate into.

Maps?

All of the functional combinators shown work on Maps, too
Map可以被看作是一个二元组的列表,所以你写的函数要处理一个键和值的二元组。

val extensions = Map("steve" -> 100, "bob" -> 101, "joe" -> 201)

extensions.filter((namePhone: (String, Int)) => namePhone._2 < 200) //Map((steve,100), (bob,101))
extensions.filter({case (name, extension) => extension < 200}) //Map((steve,100), (bob,101))

你可能感兴趣的:(Scala集合)