π£ chap9. 리ν©ν°λ§, ν μ€ν , λλ²κΉ
λλ€ ννμμΌλ‘ μ λ΅, ν νλ¦Ώ λ©μλ, μ΅μ λ², μ무 체μΈ, ν©ν 리 λ±μ κ°μ²΄μ§ν₯ λμμΈ ν¨ν΄μ κ°μνν μ μλ λ°©λ² νμ
9.1 κ°λ μ±κ³Ό μ μ°μ±μ κ°μ νλ 리ν©ν°λ§
λλ€, λ©μλ μ°Έμ‘°, μ€νΈλ¦Ό λ±μ κΈ°λ₯μ μ΄μ©ν΄ λ κ°λ μ± μ’μ μ½λλ‘ 리ν©ν°λ§Β νλ λ°©λ²
9.1.1 μ½λ κ°λ μ± κ°μ
μΌλ°μ μΌλ‘Β μ½λ κ°λ μ±μ΄ μ’λ€ = μ΄λ€ μ½λλ₯Ό λ€λ₯Έ μ¬λλ μ½κ² μ΄ν΄ν μ μμΒ μ μλ―Έ
μ¦, λ΄κ° ꡬνν μ½λλ₯Ό λ€λ₯Έ μ¬λμ΄Β μ½κ² μ΄ν΄νκ³ μ μ§λ³΄μ ν μ μκ² λ§λλ κ²
- λλ€, λ©μλ μ°Έμ‘°, μ€νΈλ¦Όμ νμ©ν 3κ°μ§ 리ν©ν°λ§ λ°©λ²
9.1.2 μ΅λͺ ν΄λμ€λ₯Ό λλ€ ννμμΌλ‘ 리ν©ν°λ§νκΈ°
μ΅λͺ ν΄λμ€λ μ½λλ₯Ό μ₯ν©νκ² λ§λ€κ³ μ½κ² μλ¬λ₯Ό μΌμΌν€κΈ° λλ¬Έμ λ κ°κ²°νκ³ κ°λ μ± μ’μ μ½λλ₯Ό ꡬννκΈ° μν΄Β λλ€ ννμΒ μ μ΄μ©νλ κ²μ΄ μ’μ
νμ§λ§, λͺ¨λ μ΅λͺ ν΄λμ€κ° λ€ λλ€ ννμμΌλ‘ λ³νκ°λ₯ν κ²μ μλ
- μ΅λͺ ν΄λμ€μμ μ¬μ©νΒ thisμ superΒ λ λλ€ ννμμμ λ€λ₯Έ μλ―Έλ₯Ό κ°λλ€. μ΅λͺ ν΄λμ€μμ thisλ μ΅λͺ ν΄λμ€ μμ μ κ°λ¦¬ν€μ§λ§ λλ€μμλ λλ€λ₯Ό κ°μΈλ ν΄λμ€λ₯Ό κ°λ¦¬ν¨λ€.
- μ΅λͺ ν΄λμ€λ κ°μΈκ³ μλ ν΄λμ€μ λ³μλ₯Ό κ°λ¦΄ μ μλ€. But λλ€ ννμμΌλ‘λ λ³μλ₯Ό κ°λ¦΄ μ μμ
- μ΅λͺ ν΄λμ€λ₯Ό λλ€ ννμμΌλ‘ λ°κΎΈλ©΄ μ½ν μ€νΈ μ€λ²λ‘λ©μ λ°λ₯Έ λͺ¨νΈν¨ μ΄λ κ°λ₯ μ΅λͺ ν΄λμ€λ μΈμ€ν΄μ€νν λ λͺ μμ μΌλ‘ νμμ΄ μ ν΄μ§λ λ°λ©΄ λλ€μ νμμ μ½ν μ€νΈμ λ°λΌ λ¬λΌμ§κΈ° λλ¬Έμ΄λ€. νμ§λ§, IntelliJ λ±μ IDEμμλ μ΄λ₯ΌΒ μλμΌλ‘ ν΄κ²°ν΄μ£Όλ 리ν©ν°λ§ κΈ°λ₯ μ 곡
9.1.3. λλ€ ννμμ λ©μλ μ°Έμ‘°λ‘ λ¦¬ν©ν°λ§νκΈ°
λλ€ ννμμ μ½κ² μ λ¬ν μ μλ 짧μ μ½λμ΄μ§λ§,Β λ©μλ μ°Έμ‘°Β λ₯Ό μ΄μ©νλ©΄ λ κ°λ μ±μ λμΌ μ μλ€.
λ©μλ μ°Έμ‘°μ λ©μλλͺ μΌλ‘ μ½λμ μλλ₯Ό λͺ ννκ² μ릴 μ μκΈ° λλ¬Έ
1
2
3
4
5
6
7
8
9
10
11
12
//λλ€ ννμ
Map<CaloricLevel, List<Dish>> dishesByCaloricLevel =
menu.stream()
.collect(groupingBy(dish -> {
if (dish.getCalories() <= 400) return CaloricLevel.DIET;
else if (dish.getCalories() <= 700) return CaloricLevel.NORMAL;
else return CaloricLevel.FAT;
}));
//λ©μλ μ°Έμ‘°
Map<CaloricLevel, List<Dish>> dishesByCaloricLevel = menu.stream()
.collect(groupingBy(Dish::getCaloricLevel));
λν,Β comparing
κ³ΌΒ maxBy
Β κ°μ μ μ ν¬νΌ λ©μλλ₯Ό νμ©νλ κ²λ μ’λ€.
sum
,Β maximum
λ± μμ£Ό μ¬μ©νλ 리λμ± μ°μ°μ λ©μλ μ°Έμ‘°μ ν¨κ» μ¬μ©ν μ μλ λ΄μ₯ ν¬νΌ λ©μλλ₯Ό μ 곡νλ€.
λ΄μ₯ 컬λ ν°λ₯Ό μ΄μ©νλ©΄ λ λͺ νν μ½λλ₯Ό μμ±ν μ μλ€.
9.1.4. λͺ λ Ήν λ°μ΄ν° μ²λ¦¬λ₯Ό μ€νΈλ¦ΌμΌλ‘ 리ν©ν°λ§νκΈ°
μ€νΈλ¦Ό APIλ λ°μ΄ν° μ²λ¦¬ νμ΄νλΌμΈμ μλλ₯Ό λ λͺ ννκ² λ³΄μ¬μ€λ€.
1
2
3
4
5
6
7
8
9
10
11
//μ€νΈλ¦Ό μ¬μ© X
List<String> dishNames = new ArrayList<>();
for(Dish dish: menu) {
if(dish.getCalories() > 300) {
dishNames.add(dish.getName());
}
}
//μ€νΈλ¦Ό μ¬μ© O
menu.parallelStream().filter(d -> d.getCalories() > 300)
.map(Dish::getName)
.collect(toList());
9.2. λλ€λ‘ κ°μ²΄μ§ν₯ λμμΈ ν¨ν΄ 리ν©ν°λ§νκΈ°
λμμΈ ν¨ν΄Β μ λ€μν ν¨ν΄μ μ νλ³λ‘ μ 리ν κ²μΌλ‘ 곡ν΅μ μΈ μννΈμ¨μ΄ λ¬Έμ λ₯Ό μ€κ³ν λ μ¬μ¬μ©ν μ μλ, κ²μ¦λ μ²μ¬μ§μ μ 곡νλ€. λμμΈ ν¨ν΄μ λλ€ ννμμ μ΄μ©νλ©΄ λ¬Έμ λ₯Ό λ μ½κ³ κ°λ¨νκ² ν΄κ²°ν μ μλ€.
9.2.1. μ λ΅
μ λ΅ ν¨ν΄Β μΒ ν μ νμ μκ³ λ¦¬μ¦μ 보μ ν μνμμ λ°νμμ μ μ ν μκ³ λ¦¬μ¦μ μ ννλ κΈ°λ²
λ€μν κΈ°μ€μ κ°λ μ λ ₯κ°μ κ²μ¦νκ±°λ, λ€μν νμ± λ°©λ²μ μ¬μ©νκ±°λ, μ λ ₯ νμμ μ€μ νλ λ±μ μλ리μ€μ μ μ©ν μ μλ€.
μ λ΅ν¨ν΄μ κ΅¬μ± λΆλΆ
- μκ³ λ¦¬μ¦μ λνλ΄λ μΈν°νμ΄μ€ (Strategy μΈν°νμ΄μ€)
- λ€μν μκ³ λ¦¬μ¦μ λνλ΄λ ν κ° μ΄μμ μΈν°νμ΄μ€ ꡬν (ConcreteStrategyA, ConcreteStrategyB κ°μ ꡬ체μ μΈ κ΅¬ν ν΄λμ€)
- μ λ΅ κ°μ²΄λ₯Ό μ¬μ©νλ ν κ° μ΄μμ ν΄λΌμ΄μΈνΈ
1
2
3
4
5
6
7
8
9
10
11
//λλ€ μ¬μ© μ
Validator numericValidator = new Validator(new IsNumberic());
boolean b1 = numericValidator.validate("aaaa");
Validator lowerCaseValidator = new Validator(new IsAllLowwerCase());
boolean b2 = lowerCaseValidator.validate("bbbb");
//λλ€ μ¬μ© ν
Validator numericValidator = new Validator((String s) -> s.matches("[a-z]+"));
boolean b1 = numericValidator.validate("aaaa");
Validator lowewrCaseValidator = new Validator((String s) -> s.matches("\\d+"));
boolean b2 = lowerCaseValidator.validate("bbbb");
- λλ€λ₯Ό μ΄μ©νλ©΄ μ λ΅ λμμΈ ν¨ν΄μμ λ°μνλ μμν μ½λλ₯Ό μ κ±°ν μ μλ€.
- λλ€ ννμμ μ½λμ‘°κ°(λλ μ λ΅) μ μΊ‘μννλ€.
9.2.2. ν νλ¦Ώ λ©μλ
μκ³ λ¦¬μ¦μ κ°μλ₯Ό μ μν λ€μ,Β μκ³ λ¦¬μ¦μ μΌλΆλ₯Ό κ³ μΉ μ μλ μ μ°ν¨μ μ 곡 ν΄μΌ ν λλΒ ν νλ¦Ώ λ©μλΒ λμμΈ ν¨ν΄μ μ΄μ©νλ κ²μ΄ μ’λ€.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//λλ€ μ¬μ© μ
abstract class OnlineBanking {
public void processCustomer(int id) {
Customer c = Database.getCustomerWithId(id);
makeCustomerHappy(c);
}
abstract void makeCustomerHappy(Customer c);
}
//λλ€ μ¬μ© ν
public void processCustomer(int id, Consumer<Customer> makeCustomerHappy) {
Customer c = Database.getCustomerWithId(id);
makeCustomerHappy.accept(c);
}
new OnlineBankingLambda().processCustomer(1337, (Customer c) ->
System.out.println("Hello " + c.getName());
λλ€λ₯Ό μ¬μ©νλ©΄ onlineBanking ν΄λμ€λ₯Ό μμλ°μ§ μκ³ μ§μ λλ€ ννμμ μ λ¬ν΄ λ€μν λμμ μΆκ°ν μ μλ€.
9.2.3. μ΅μ λ²
μ΄λ€ μ΄λ²€νΈκ° λ°μνμ λΒ μ£Όμ²΄Β κ° λλ ν κ°μ²΄κ°Β μ΅μ λ²Β λΌ λΆλ¦¬λ λ€λ₯Έ κ°μ²΄ 리μ€νΈμκ² μλμΌλ‘ μλ¦Όμ 보λ΄μΌ νλ μν©μμΒ μ΅μ λ² λμμΈ ν¨ν΄Β μ μ¬μ©νλ€.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//λλ€ μ¬μ© μ
class Feed implements Subject {
private final List<Observer> observers = new ArrayList<>();
public void registerObserver(Observer o) {
this.observers.add(o);
}
public void notifyObservers(String tweet) {
observers.forEach(o -> o.notify(tweet));
}
}
//λλ€ μ¬μ© ν
f.registerObserver((String tweet) -> {
if(tweet != null && tweet.contains("money")) {
System.out.println("Breaking news in NY! " + tweet);
}
});
f.registerObserver((String tweet) -> {
if(tweet != null && tweet.contains("queen")) {
System.out.println("Yet more news from London... " + tweet);
}
});
νμ§λ§, μ΅μ λ²κ° μνλ₯Ό κ°μ§λ©°, μ¬λ¬ λ©μλλ₯Ό μ μνλ λ± λ³΅μ‘νλ€λ©΄ λλ€ ννμλ³΄λ€ κΈ°μ‘΄μ ν΄λμ€ κ΅¬νλ°©μμ κ³ μνλ κ²μ΄ λ°λμ§ν μλ μλ€.
9.2.4. μ무 체μΈ
μμ μ²λ¦¬ κ°μ²΄μ 체μΈ(λμ μ²΄μΈ λ±)μ λ§λ€ λλΒ μ무 μ²΄μΈ ν¨ν΄Β μ μ¬μ©νλ€. ν κ°μ²΄κ° μ΄λ€ μμ μ μ²λ¦¬ν λ€μμ λ€λ₯Έ κ°μ²΄λ‘ κ²°κ³Όλ₯Ό μ λ¬νκ³ , λ€λ₯Έ κ°μ²΄λ ν΄μΌ ν μμ μ μ²λ¦¬ν λ€μμ λ λ€λ₯Έ κ°μ²΄λ‘ μ λ¬νλ μμ΄λ€.
μ΄ ν¨ν΄μΒ ν©μ 체μΈ(ν¨μ μ‘°ν©)Β κ³Ό λΉμ·νλ€. μμ
μ²λ¦¬ κ°μ²΄λ₯ΌΒ Function<String, String>
, λ μ νν νννμλ©΄Β UnaryOperator<String>
Β νμμ μΈμ€ν΄μ€λ‘ ννν μ μλ€.
9.2.5. ν©ν 리
μΈμ€ν΄μ€ν λ‘μ§μ ν΄λΌμ΄μΈνΈμ λ ΈμΆνμ§ μκ³ κ°μ²΄λ₯Ό λ§λ€ λΒ ν©ν 리 λμμΈ ν¨ν΄Β μ μ¬μ©νλ€.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//λλ€ μ¬μ© μ
public class ProductFactory {
public static Product createProduct(String name) {
switch(name) {
case "loan" : return new Loan();
case "stock" : return new Stock();
case "bond" : return new Bond();
default : throw new RuntimeException("No such product " + name);
}
}
}
//λλ€ μ¬μ© ν
Supplier<Product> loanSupplier = Loan::new;
Loan loan = loanSupplier.get();
final static Map<String, Supplier<Product>> map = new HashMap<>();
static {
map.put("loan", Loan::new);
map.put("stock", Stock::new);
map.put("bond", Bond::new);
}
But, ν©ν 리 λ©μλ μμ μμ±μλ‘ μ¬λ¬ μΈμλ₯Ό μ λ¬νλ μν©μμλ μ μ©νκΈ° μ΄λ ΅λ€.
e.g. μΈ μΈμλ₯Ό λ°λ μμ±μλΌλ©΄ TriFunctionμ΄λΌλ νΉλ³ν ν¨μν μΈν°νμ΄μ€λ₯Ό μ¬μ©ν΄μΌ νκ³ , κ²°κ΅ λ€μκ³Ό κ°μ΄ Mapμ μκ·Έλμ²κ° 볡μ‘ν΄μ§λ€.
1
2
3
4
public interface TriFunction <T, U, V, R> {
R apply(T t, U u, V v);
}
Map<String, TriFunction<Integer, Integer, String, Product>> map = new HashMap<>();
9.3. λλ€ ν μ€ν
νλ‘κ·Έλ¨μ΄ μλλλ‘ λμνλμ§ νμΈνκΈ° μν΄Β λ¨μ ν μ€νΈΒ λ₯Ό ν΄λ³Ό μ μλ€.
1
2
3
4
5
6
7
@Test
public void testMoveRightBy() throws Exception {
Point p1 = new Point(5, 5);
Point p2 = p1.moveRightBy(10);
assertEquals(15, p2.getX());
assertEquals(5, p2.getY());
}
9.3.1. 보μ΄λ λλ€ ννμμ λμ ν μ€ν
μμ ν
μ€νΈμ½λλΒ moveRightBy
κ° publicμ΄λ―λ‘ λ¬Έμ μμ΄ μλνλ€. νμ§λ§ λλ€λ μ΅λͺ
μ΄λ―λ‘ ν
μ€νΈ μ½λ μ΄λ¦μ νΈμΆν μ μλ€. λ°λΌμ νμνλ€λ©΄ λλ€λ₯Ό νλμ μ μ₯ν΄μ μ¬μ¬μ©ν μ μμΌλ©° λλ€μ λ‘μ§μ ν
μ€νΈν μ μλ€.
1
2
3
4
5
6
public class Point {
public final static Comparator<Point> compareByXAndThenY =
comparing(Point::getX).thenComparing(Point::getY);
...
}
1
2
3
4
5
6
7
@Test
public void testComparingTwoPoints() throws Exception {
Point p1 = new Point(10, 15);
Point p2 = new Point(10, 20);
int result = Point.compareByXAndThenY.compare(p1, p2);
assertTrue(result < 0);
}
9.3.2. λλ€λ₯Ό μ¬μ©νλ λ©μλμ λμμ μ§μ€νλΌ
λλ€μ λͺ©νλΒ μ ν΄μ§ λμμ λ€λ₯Έ λ©μλμμ μ¬μ©ν μ μλλ‘ νλμ μ‘°κ°μΌλ‘ μΊ‘μννλ κ²Β μ΄λ€. λλ€ ννμμ μ¬μ©νλ λ©μλμ λμμ ν μ€νΈν¨μΌλ‘μ¨ λλ€λ₯Ό 곡κ°νμ§ μμΌλ©΄μλ λλ€ ννμμ κ²μ¦ν μ μλ€.
1
2
3
4
5
public static List<Point> moveAllPointsRightBy(List<Point> points, int x) {
return points.stream()
.map(p -> new Point(p.getX() + x, p.getY()))
.collect(toList());
}
μ μ½λμΒ p -> new Point(p.getX() + x, p.getY());
Β ν
μ€νΈ
1
2
3
4
5
6
7
8
9
@Test
public void testMoveAllPointsRightBy() throws Exception {
List<Point> points =
Arrays.asList(new Point(5, 5), new Point(10, 5));
List<Point> expectedPoints =
Arrays.asList(new Point(15, 5), new Point(20, 5));
List<Point> newPoints = Point.moveAllPointsRightBy(points, 10);
assertEquals(expectedPointes, newPoints);
}
9.4. λλ²κΉ
λ¬Έμ κ° λ°μν μ½λλ₯Ό λλ²κΉ ν λ κ°λ°μλ λ€μ λ κ°μ§λ₯Ό λ¨Όμ νμΈν΄μΌ νλ€.
- μ€ν νΈλ μ΄μ€
- λ‘κΉ
νμ§λ§ λλ€ ννμκ³Ό μ€νΈλ¦Όμ κΈ°μ‘΄μ λλ²κΉ κΈ°λ²μ 무λ ₯ννλ€.
9.4.1. μ€ν νΈλ μ΄μ€ νμΈ
μμΈ λ°μμΌλ‘ νλ‘κ·Έλ¨ μ€νμ΄ κ°μκΈ° μ€λ¨λμλ€λ©΄ λ¨Όμ μ΄λμμ λ©μ·κ³ μ΄λ»κ² λ©μΆκ² λμλμ§ μ΄ν΄λ΄μΌ νλ€.
λλ€ννμμ μ΄λ¦μ΄ μκΈ° λλ¬Έμ μ‘°κΈ λ³΅μ‘ν μ€ν νΈλ μ΄μ€κ° μμ±λλ€.
1
2
3
Exception in thread "main" java.lang.NullPointerException
at Debugging.lambda$main$0(Debugging.java:6)
at Debugging$$Lambda$5/284720968.apply(Unknown Source)
λλ€ ννμ λ΄λΆμμ μλ¬κ° λ°μνλ©΄ λλ€ ννμμ μ΄λ¦μ΄ μμΌλ―λ‘ μ»΄νμΌλ¬κ° λλ€λ₯Ό μ°Έμ‘°νλ μ΄λ¦μ λ§λ€μ΄λΈλ€.
λ°λΌμ λλ€ ννμκ³Ό κ΄λ ¨ν μ€ν νΈλ μ΄μ€λ μ΄ν΄νκΈ° μ΄λ €μΈ μ μλ€.