Skip to content

Commit 3ebcf96

Browse files
committed
chapter20 + 21
1 parent a445b4a commit 3ebcf96

16 files changed

+373
-0
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package s4j.scala.chapter20
2+
3+
case class Address(street: String, postcode: Option[String])
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package s4j.scala.chapter20
2+
3+
case class Customer(name: String, address: Option[Address]) extends Ordered[Customer] {
4+
private final val basket: ShoppingBasket = new ShoppingBasket
5+
6+
def add(item: Item) {
7+
basket.add(item)
8+
}
9+
10+
def total: Double = {
11+
basket.value
12+
}
13+
14+
override def compare(that: Customer): Int = name.compare(that.name)
15+
override def toString: String = name + " $ " + total
16+
}
17+
18+
//object Customer {
19+
// def unapply(customer: Customer): Option[(String, Option[Address])] = {
20+
// if (customer == null) None else Some(customer.name, customer.address)
21+
// }
22+
//}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package s4j.scala.chapter20
2+
3+
import scala.collection.mutable
4+
5+
class CustomerSet extends Customers {
6+
7+
private val customers = mutable.Set[Customer]()
8+
9+
def add(customer: Customer) = customers.add(customer)
10+
11+
def find(name: String): Option[Customer] = {
12+
for (customer <- customers) {
13+
if (customer.name == name)
14+
return Some(customer)
15+
}
16+
None
17+
}
18+
19+
def findOrNull(name: String): Customer = {
20+
for (customer <- customers) {
21+
if (customer.name == name)
22+
return customer
23+
}
24+
null
25+
}
26+
27+
def findOrThrow(name: String): Customer = {
28+
for (customer <- customers) {
29+
if (customer.name == name)
30+
return customer
31+
}
32+
throw new NotFoundException(name)
33+
}
34+
35+
def iterator: Iterator[Customer] = customers.iterator
36+
}
37+
38+
class NotFoundException(name: String) extends Exception(name)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package s4j.scala.chapter20
2+
3+
trait Customers extends Iterable[Customer] {
4+
def add(Customer: Customer)
5+
def find(name: String): Option[Customer]
6+
def findOrNull(name: String): Customer
7+
}
8+
9+
object Customers {
10+
def apply() = new CustomerSet()
11+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package s4j.scala.chapter20
2+
3+
import s4j.scala.chapter20.CustomerDatabase.database
4+
5+
object CustomerDatabase {
6+
val database = Customers()
7+
8+
val customerA = Customer("Albert", Some(Address("1a Bridge St", None)))
9+
val customerB = Customer("Beatriz", None)
10+
val customerC = Customer("Carol", Some(Address("2a Finsbury Circus", Some("AL1 2PY"))))
11+
val customerD = Customer("Sherlock", Some(Address("21b Baker Street", Some("NW1 6XE"))))
12+
13+
customerA.add(PricedItem(10))
14+
customerA.add(PricedItem(5))
15+
customerC.add(PricedItem(10))
16+
17+
database.add(customerA)
18+
database.add(customerB)
19+
database.add(customerC)
20+
database.add(customerD)
21+
}
22+
23+
object Example extends App {
24+
25+
// null case
26+
val albert = database.findOrNull("Albert")
27+
val basket = if (albert != null) albert.total else 0D
28+
29+
// map over option
30+
val exists = database.find("Albert").map(customer => "customer exists")
31+
val basketValue = database.find("Albert").map(customer => customer.total).getOrElse(0D) // forced to handle the else? get would throw
32+
33+
34+
val customers = Set("Albert", "Beatriz", "Carol", "Dave", "Erin", "Sherlock")
35+
36+
def sumCustomerBaskets_NulLCheckVersion() = {
37+
// all.map(customers.findOrNull).map(_.total).sum // throws NPE
38+
// or
39+
customers.map(database.findOrNull).map(customer => if (customer != null) customer.total else 0D).sum
40+
}
41+
42+
def sumCustomerBaskets_NulLAvoidingPatternMatch() = {
43+
customers.map(database.findOrNull(_) match {
44+
case customer@Customer(_, _) => customer.total // why no if customer != null clause? it matches on null below
45+
case a @ _ => println(a); 0D
46+
}).sum
47+
}
48+
49+
def sumCustomerBaskets_MapCouldThrowAnException() = {
50+
// all.map(customers.find(_)).map(customer => customer.get.total) // could throw an exception
51+
// customers.find("Missing").map(customer => customer.total).get // throws an exception
52+
database.find("Missing") match {
53+
case Some(customer) => customer.total
54+
case None => 0D
55+
}
56+
}
57+
58+
def sumCustomerBaskets_MapThenFlattenVersion() = {
59+
customers.map(database.find(_).map(_.total)).flatten.sum
60+
}
61+
62+
def sumCustomerBaskets_FlatMapVersion() = {
63+
customers.flatMap(name => database.find(name)).map(customer => customer.total).sum
64+
}
65+
66+
67+
val partial: Set[Option[Customer]] = customers.map(database.find)
68+
69+
println("1. " + sumCustomerBaskets_NulLCheckVersion())
70+
println("2. " + sumCustomerBaskets_NulLAvoidingPatternMatch()) // yuk!
71+
println("3. " + sumCustomerBaskets_MapCouldThrowAnException())
72+
println("4. " + sumCustomerBaskets_MapThenFlattenVersion())
73+
println("5. " + sumCustomerBaskets_FlatMapVersion())
74+
75+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package s4j.scala.chapter20
2+
3+
trait Item {
4+
def price: Double
5+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package s4j.scala.chapter20
2+
3+
case class PricedItem(price: Double) extends Item
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package s4j.scala.chapter20
2+
3+
import scala.collection.mutable
4+
5+
class ShoppingBasket {
6+
private val basket = mutable.HashSet[Item]()
7+
8+
def add(items: Item*) {
9+
for (item <- items)
10+
basket.add(item)
11+
}
12+
13+
def value: Double = {
14+
basket.map(_.price).sum
15+
}
16+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package s4j.scala.chapter21
2+
3+
case class Address(street: String, postcode: Option[String])
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package s4j.scala.chapter21
2+
3+
case class Customer(name: String, address: Option[Address]) extends Ordered[Customer] {
4+
private final val basket: ShoppingBasket = new ShoppingBasket
5+
6+
def add(item: Item) {
7+
basket.add(item)
8+
}
9+
10+
def total: Double = {
11+
basket.value
12+
}
13+
14+
override def compare(that: Customer): Int = name.compare(that.name)
15+
override def toString: String = name + " $ " + total
16+
}
17+
18+
//object Customer {
19+
// def unapply(customer: Customer): Option[(String, Option[Address])] = {
20+
// if (customer == null) None else Some(customer.name, customer.address)
21+
// }
22+
//}

0 commit comments

Comments
 (0)