140 likes | 153 Views
Learn the benefits of using immutable classes with constructor parameters in Java to reduce J2EE EJB boilerplate and ease development. Explore case classes and abstract class implementation with relevant examples. Practice iterating through lists and handling accumulators effectively.
E N D
Case Classes HW4 Review
Case Classes • Why? Immutable classes with ctor parameters. Easier than defining setters and getters and a class for them. Reduces Boilerplate from J2EE EJBshttps://gist.github.com/dougc333/2975185224510197e005 • How to move the common weight into abstract class?
Case Class • abstract class CodeTree2 { • val name:String • def weight:Int • } • case class Fork3(left: CodeTree, right: CodeTree, chars: List[Char], weight: Int) extends CodeTree • case class Leaf3(char: Char, weight: Int) extends CodeTree • object foo2 extends Application{ • val l3 = Leaf3('a',1) • println(l3.weight) • val f3 = Fork3(l3, Leaf3('b',2),List('c'),4) • println(f3.weight) • } • 1 • 4 • For weight move into ABC • def weight(tree: CodeTree): Int = { • tree.weight • }
Case classes • Autoimplement getters/setters & no instanceof needed. Return ivars from ctor args def chars(tree: CodeTree): List[Char] = tree match{ case Fork(_, _, chars, _) => chars case Leaf(char, _) => List(char) }
MakeCodeTree • Fork is for combining 2 CodeTrees, to add lists together use ++ or :::. def makeCodeTree(left: CodeTree, right: CodeTree) = Fork(left, right, chars(left) ++ chars(right), weight(left) + weight(right))
times • def times(chars: List[Char]): List[(Char, Int)] = { • def timesAcc(chars:List[Char],acc:Map[Char,(Char,Int)]):Map[Char,(Char,Int)] = chars match { • case Nil => acc • case x::xs => if (acc contains x) {val tmpacc=acc.updated(x,(x,acc(x)._2+1));timesAcc(xs,tmpacc)} else {val tmpacc=acc+(x->(x,1));timesAcc(xs,tmpacc)}; • } • timesAcc(chars,Map()).values.toList • } • This is a good time to practice. Reduce number of new things to learn. Remove pairs, remove return • Implement def times(chars:List[Chars]) and put in print statements to show what is happening
Iterating through list • //iterate through the list • def testMe2(chars:List[Char]):Unit={ • def testMe2Acc(chars:List[Char]) = chars match{ • case Nil => println("testMe2 match empty list") • case x::xs => println("testMe2 not empty List x:"+x+",xs:"+xs); testMe2(xs) • } • testMe2Acc(chars) • } • Write test code to verify your print statements match what is happening and you can iterate through the list.
Add accumulator • def testMe3(chars:List[Char]):Unit={ • def testMe3Acc(chars:List[Char],acc:Map[Char,Int]):Unit = chars match{ • case Nil => println("testMe3 match empty list") • case x::xs => println("testMe3 not empty List x:"+x+",xs:"+xs);println("acc:"+acc); if (acc contains x) {val tmpacc=acc.updated(x,acc(x)+1);println("contains acc after add+"+tmpacc);testMe3Acc(xs,tmpacc)} else {println("not contains adding");val tmpacc=acc+(x->1);print("acc after add:"+tmpacc);testMe3Acc(xs,tmpacc)}; • } • testMe3Acc(chars,Map()) • }
Add Pairs w/no return type • //make pairs, w/o return type • def testMe5(chars:List[Char]):Unit={ • def testMe5Acc(chars:List[Char],acc:Map[Char,(Char,Int)]):Unit = chars match{ • case Nil => println("testMe5 empty list"); • case x::xs => println("testMe5 char:"+x);println("acc before insert:"+acc); if (acc contains x) {val tmpacc=acc.updated(x,(x,acc(x)._2+1));println("tmpacc+"+tmpacc);testMe5Acc(xs,tmpacc)} else {println("not contains adding");val tmpacc=acc+(x->(x,1));print("acc after add:"+tmpacc);testMe5Acc(xs,tmpacc)}; • } • testMe5Acc(chars,Map()) • }
Add map return and convert to list • def testMe6(chars:List[Char]):List[(Char,Int)]={ • def testMe6Acc(chars:List[Char],acc:Map[Char,(Char,Int)]):Map[Char,(Char,Int)] = chars match{ • case Nil => println("testMe6 empty list");acc • case x::xs => println("testMe6 char:"+x);println("acc before insert:"+acc); if (acc contains x) {val tmpacc=acc.updated(x,(x,acc(x)._2+1));println("tmpacc+"+tmpacc);testMe6Acc(xs,tmpacc)} else {println("not contains adding");val tmpacc=acc+(x->(x,1));print("acc after add:"+tmpacc);testMe6Acc(xs,tmpacc)}; • } • testMe6Acc(chars,Map()).values.toList • }
Final answer for times • def times(chars: List[Char]): List[(Char, Int)] = { • def timesAcc(chars:List[Char],acc:Map[Char,(Char,Int)]):Map[Char,(Char,Int)] = chars match { • case Nil => acc • case x::xs => if (acc contains x) {val tmpacc=acc.updated(x,(x,acc(x)._2+1));timesAcc(xs,tmpacc)} else {val tmpacc=acc+(x->(x,1));timesAcc(xs,tmpacc)}; • } • timesAcc(chars,Map()).values.toList • }
Sort list then convert Pairs to leaf • def makeOrderedLeafList(freqs: List[(Char, Int)]): List[Leaf] = • { • freqs.sortBy(Tuple2 => Tuple2._2).map(Tuple2 => Leaf(Tuple2._1, Tuple2._2)) • }
Singleton • def singleton(trees:List[CodeTree]):Boolean ={ • if (trees.length == 1) true • false • }
Combine, 2 examples • Tree match & no tree match def combine(trees: List[CodeTree]): List[CodeTree] = trees match{ case first::second::restofList => { val ct = makeCodeTree(first,second) val large = trees.filter(x=>weight(x)>weight(ct)) return ct::large } case _ => println("less than 2"); trees //if less than 2 return trees } def combine2(trees: List[CodeTree]): List[CodeTree] = { if (trees.length>=2) { val ct = makeCodeTree(trees.head,trees(2)) val large = trees.filter(x=>weight(x)>weight(ct)) return ct::large } trees }