scala collection

Download Scala collection

Post on 15-Jan-2015




2 download

Embed Size (px)




  • 1. Introducing Collectionsin ScalaRishi KhandelwalSoftware ConsultantKnoldus Software LLPEmail :

2. FeaturesEasy to useConciseSafeFastUniversal 3. Continued...e.g. val (minors, adults) = people partition (_.age < 18) It partitions a collection of people into minors and adults depending on their age.Much more concise than the one to three loops required for traditionalcollection processing.Writing this code is much easier, once we learn the basiccollection vocabulary.Safer than writing explicit loops.The partition operation is quite fast. 4. Mutable and Immutable collectionsMutable :can change, add, or remove elements of a collectionimport scala.collection.mutableImmutable :never changeupdation return a new collection and leave the old collectionunchanged.By default collections are immutable 5. Continued...To use mutable collections, just importscala.collection.mutable.To use both mutable and immutable versions of collections isto import just the package collection.mutable.e.g. scala> import scala.collection.mutable import scala.collection.mutable scala> val immutSet=Set(1,2,3) immutSet: scala.collection.immutable.Set[Int] = Set(1, 2, 3) scala> val mutSet=mutable.Set(1,2,3) mutSet: scala.collection.mutable.Set[Int] = Set(2, 1, 3) 6. Collections consistencyQuite a bit of commonality shared by all these collections.Every kind of collection can be created by the same uniformsyntax writing collection class name followed by its elements:e.g. Traversable(1, 2, 3) Iterable("x", "y", "z") Map("x" -> 24, "y" -> 25, "z" -> 26) Set(Color.Red, Color.Green, Color.Blue)Same principle also applies for specific collection implementationse.g. List(1, 2, 3) HashMap("x" -> 24, "y" -> 25, "z" -> 26) 7. Collection hierarchyscala Traversable trait scala Iterable trait scala scala.collection scala.collectionSeqSetMaptraittraittrait 8. Trait TraversableAt the top of the collection hierarchy.Only abstract operation is foreach:def foreach[U](f: Elem =>U)foreach method is meant to traverse all elements of the collection.apply the given operation f, to each element.Elem => U= the type of the operation.Elem = the type of the collections elements.U = an arbitrary result type.It also defines many concrete methods 9. Trait IterableNext trait from the top.All methods are defined in terms of an abstract method, iterator, whichyields the collections elements one by one.Implementation of foreach :def foreach[U](f: Elem => U): Unit = { val it = iterator while (it.hasNext) f(}Two more methods exist in Iterable that return iterators:grouped and sliding.These iterators do not return single elements but whole subsequences ofelements of the original collection. 10. scala> val xs = List(1, 2, 3, 4, 5)xs: List[Int] = List(1, 2, 3, 4, 5)grouped :scala> val git = xs grouped 3git: Iterator[List[Int]] = non-empty iteratorscala> List[Int] = List(1, 2, 3)scala> List[Int] = List(4, 5)sliding:scala> val sit = xs sliding 3sit: Iterator[List[Int]] = non-empty iteratorscala> List[Int] = List(1, 2, 3)scala> List[Int] = List(2, 3, 4)scala> List[Int] = List(3, 4, 5) 11. Why have both Traversable and Iterable?sealed abstract class Treecase class Branch(left: Tree, right: Tree) extends Treecase class Node(elem: Int) extends Tree Using Traversablesealed abstract class Tree extends Traversable[Int] {def foreach[U](f: Int => U) = this match {case Node(elem) => f(elem)case Branch(l, r) => l foreach f; r foreach f}}Traversing a balanced tree takes time proportional to the number ofelements in the tree. A balanced tree with N leaves will have N - 1 interior nodes ofclass branch. So the total number of steps to traverse the tree is N + N - 1. 12. Continued...Using Iterable :sealed abstract class Tree extends Iterable[Int] {def iterator: Iterator[Int] = this match { case Node(elem) => Iterator.single(elem) case Branch(l, r) => l.iterator ++ r.iterator } } Theres an efficiency problem that has to do with the implementation of theiterator concatenation method, ++The computation needs to follow one indirection to get at the right iterator(either l.iterator,or r.iterator).Overall, that makes log(N) indirections to get at a leaf of a balanced treewith N leaves. 13. Trait SeqSeq trait represents sequences.A sequence is a kind of iterable that has a length and whose elements havefixed index positions, starting from 0.Each Seq trait has two subtraits, LinearSeq and IndexedSeqA linear sequence has efficient head and tail operationse.g. List, StreamAn indexed sequence has efficient apply, length, and (if mutable)update operations. e.g. Array, ArrayBuffer 14. SequencesClasses that inherit from trait SeqLists :Always Immutable Support fast addition and removal of items to the beginning ofthe listscala> val colors = List("red", "blue", "green")colors: List[java.lang.String] = List(red, blue, green)scala> colors.headres0: java.lang.String = redscala> colors.tailres1: List[java.lang.String] = List(blue, green) 15. Continued...Array :Efficiently access an element at an arbitrary position.Scala arrays are represented in the same way as Java arraysCreate an array whose size is known but dont yet know theelement values:e.g. scala> val fiveInts = new Array[Int](5) fiveInts: Array[Int] = Array(0, 0, 0, 0, 0)Initialize an array when we do know the element values:e.g. scala> val fiveToOne = Array(5, 4, 3, 2, 1)fiveToOne: Array[Int] = Array(5, 4, 3, 2, 1)Accessing and updating an array element:e.g. scala> fiveInts(0) = fiveToOne(4) scala> fiveInts res1: Array[Int] = Array(1, 0, 0, 0, 0) 16. Continued...List buffers :It is a mutable object which can help you build lists moreefficiently when you need to append.Provides constant time append and prepend operations.Append elements with the += operator,and prepend them withthe +: operator.Obtain a List by invoking toList on the ListBuffer.To use it, just import scala.collection.mutable.ListBuffer 17. Continued...scala> import scala.collection.mutable.ListBufferimport scala.collection.mutable.ListBufferscala> val buf = new ListBuffer[Int]buf: scala.collection.mutable.ListBuffer[Int] = ListBuffer()scala> buf += 1scala> buf += 2scala> bufres11: scala.collection.mutable.ListBuffer[Int]= ListBuffer(1, 2)scala> 3 +: bufres12: scala.collection.mutable.Buffer[Int]= ListBuffer(3, 1, 2)scala> buf.toListres13: List[Int] = List(3, 1, 2) 18. Continued...Array buffers : It is like an array, except that you can additionally add and removeelements from the beginning and end of the sequence. To use it just import scala.collection.mutable.ArrayBuffer e.g. scala> import scala.collection.mutable.ArrayBufferimport scala.collection.mutable.ArrayBuffer To create an ArrayBuffer, only specify a type parameter, no need not specify a length. e.g. scala> val buf = new ArrayBuffer[Int]()buf: scala.collection.mutable.ArrayBuffer[Int] =ArrayBuffer() 19. Continued... Append to an ArrayBuffer using the += method:e.g. scala> buf += 12 scala> buf += 15 scala> buf res16: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(12, 15). All the normal array methods are availablee.g. scala> buf.length res17: Int = 2 scala> buf(0) res18: Int = 12 20. Continued... Queue : first-in-first-out sequence. Both mutable and immutable variants of Queue. Create an empty immutable queue: e.g. scala> import scala.collection.immutable.Queueimport scala.collection.immutable.Queuescala> val empty = Queue[Int]()empty: scala.collection.immutable.Queue[Int] = Queue() Note : scala> val empty=new Queue[Int] :8: error: constructor Queue in class Queue cannot be accessed in object $iw Access to protected constructor Queue not permitted because enclosing class object $iw in object $iw is not a subclass ofclass Queue in package immutable where target is defined val empty=new Queue[Int] ^ 21. Continued...Append an element to an immutable queue with enqueue:e.g. scala> val has1 = empty.enqueue(1) has1: scala.collection.immutable.Queue[Int] = Queue(1)To append multiple elements to a queue, call enqueue with a collection asits argument:e.g. scala> val has123 = has1.enqueue(List(2, 3))has123: scala.collection.immutable.Queue[Int] =Queue(1,2,3)To remove an element from the head of the queue,use dequeue:scala> val (element, has23) = has123.dequeueelement: Int = 1has23: scala.collection.immutable.Queue[Int] = Queue(2,3) 22. Continued...Use mutable Queuescala> import scala.collection.mutable.Queueimport scala.collection.mutable.Queuescala> val queue = new Queue[String]queue: scala.collection.mutable.Queue[String] = Queue()scala> queue += "a"scala> queue ++= List("b", "c")scala> queueres21: scala.collection.mutable.Queue[String] = Queue(a, b, c)scala> queue.dequeueres22: String = ascala> queueres23: scala.collection.mutable.Queue[String] = Queue(b, c) 23. Continued...Stack :last-in-first-out sequence.Both mutable and immutable variants..push an element onto a stack with push,pop an element with pop,peek at the top of the stack without removing it with topscala> import scala.collection.mutable.Stackimport scala.collection.mutable.Stackscala> val stack = new Stack[Int]stack: scala.collection.mutable.Stack[Int] = Stack() 24. Continued...scala> stack.push(1)scala> stackres1: scala.collection.mutable.Stack[Int] = Stack(1)scala> stack.push(2)scala> stackres3: scala.collection.mutable.Stack[Int] = Stack(1, 2)scala> stack.topres8: Int = 2scala> stackres9: scala.collection.mutable.Stack[Int] = Stack(1, 2)scala> stack.popres10: Int = 2scala> stackres11: scala.collection.mutable.Stack[Int] = Stack(1) 25. Continued...Strings (via StringOps) :It implements many sequence methods..Predef has an implicit conversion from String to StringOps,we can treat anystr