πŸ“Œλͺ¨λ˜ μžλ°” 인 μ•‘μ…˜ Chapter 3. λžŒλ‹€ ν‘œν˜„μ‹

λͺ¨κΉ…Β·2023λ…„ 12μ›” 8일
0

πŸ“– 3.6 λ©”μ„œλ“œ μ°Έμ‘°

λ©”μ„œλ“œ μ°Έμ‘° : 기쑴의 λ©”μ„œλ“œ μ •μ˜λ₯Ό μž¬ν™œμš©ν•΄μ„œ λžŒλ‹€μ²˜λŸΌ 전달 ν•  수 있게 함.
-> λžŒλ‹€ ν‘œν˜„μ‹λ³΄λ‹€ 더 가독성이 μ’‹λ‹€.

inventory.sort((Apple a1, Apple a2) ->
		a1.getWeight().compareTo(a2.getWeight()));


inventory.sort(comparing(Apple::getWeight)); 

3.6.1 λ©”μ„œλ“œ μ°Έμ‘°λ₯Ό λ§Œλ“œλŠ” 방법

  1. 정적 λ©”μ„œλ“œμ°Έμ‘°
    Integer의 parselnt λ©”μ„œλ“œ => Integer::parselnt

  2. λ‹€μ–‘ν•œν˜•μ‹μ˜ μΈμŠ€ν„΄μŠ€ λ©”μ„œλ“œμ°Έμ‘°
    String의 length λ©”μ„œλ“œ => String::length

  3. 기쑴객체의 μΈμŠ€ν„΄μŠ€ λ©”μ„œλ“œμ°Έμ‘°
    Transaction 객체λ₯Ό 할당받은 expensiveTransaction 지역 λ³€μˆ˜κ°€ 있고,
    Transaction κ°μ²΄μ—λŠ” getValue λ©”μ„œλ“œ => expensiveTransaction::getValue

λ§λ‘œν•˜λ©΄ μ–΄λ €μš°λ‹ˆ μ•„λž˜ 그림을 보자

ν€΄μ¦ˆ 3-6

λ‹€μŒμ˜ λžŒλ‹€ν‘œν˜„μ‹κ³Ό μΌμΉ˜ν•˜λŠ” λ©”μ„œλ“œμ°Έμ‘°λ₯Ό κ΅¬ν˜„ν•˜μ‹œμ˜€.

1. ToIntFunction<String> stringToInt = 
				(String s) -> Integer.parselnt(s);

2. BiPredicate<List<String>, String> contains = 
				(list, element) -> list.contains(element);

3. Predicate<String> startsWithNumber = 
				(String string) -> this.startsWithNumber(string);
    

μ •λ‹΅

1. Function<String, Integer> stringToInteger = Integer::parselnt;
	-> 정적 λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λŠ” λžŒλ‹€ ν‘œν˜„μ‹

2. BiPredicate<List<String>, String> contains = List::contains;
	-> 첫번째 인수의 contains λ©”μ„œλ“œλ₯Ό 호좜

3. Predicate<String> startsWithNumber = this::startsWithNumber;

3.6.2 μƒμ„±μž μ°Έμ‘°

Classname::new둜 λ§Œλ“€ 수 μžˆλ‹€.

Supplier의 () -> Appleκ³Ό 같은 μ‹œκ·Έλ‹ˆμ²˜λ₯Ό κ°–λŠ” μƒμ„±μžκ°€ μžˆλ‹€κ³  κ°€μ •ν•˜μž.

Supplier<Apple> c1 = Apple::new;
Apple a1 = c1.get();

Supplier<Apple> c1 = () -> new Apple();
Apple a1 = c1.get();

Apple (integer weight)λΌλŠ” μ‹œκ·Έλ‹ˆμ²˜λ₯Ό κ°–λŠ” μƒμ„±μžλŠ” Function<T,U> μΈν„°νŽ˜μ΄μŠ€μ˜ μ‹œκ·Έλ‹ˆμ²˜μ™€ κ°™λ‹€. λ”°λΌμ„œ λ‹€μŒκ³Ό 같은 μ½”λ“œλ₯Ό κ΅¬ν˜„ν•  수 μžˆλ‹€.

Function<Integer, Apple> c2 = Apple::new; 
Apple a2 = c2.apply(110);

Function<Integer, Apple> c2 = (weight) -> new Apple(weight); 
Apple a2 = c2.apply(110);


// μ˜ˆμ‹œ
List<Integer> weights = Arrays.asList(7, 3, 4, 10);
List<Apple> apples = map(weights, Apple::new); 
public List<Apple> map(List<Integer> list, Function<Integer, Apple) f) { 
	List<Apple> result = new ArrayList<>(); 
	for(Integer i : list) {
		result.add(f.apply(i));
	}
	return result;
}

Apple (String color, Integer weight) 처럼 두 인수λ₯Ό κ°–λŠ” μƒμ„±μžλŠ” BiFunction μΈν„°νŽ˜μ΄μŠ€μ™€ 같은 μ‹œκ·Έλ‹ˆμ²˜λ₯Ό κ°€μ§€λ―€λ‘œ λ‹€μŒκ³Ό 같이 ν•  수 μžˆλ‹€.

BiFunction<Color, Integer, Apple> c3 = Apple::new;
Apple a3 = c3.apply(GREEN, 110);

BiFunction<String, Integer, Apple> c3 = 
			(color, weight) -> new Apple(color, weight); 
Apple a3 = c3.apply(GREEN, 110);


// μ˜ˆμ‹œ
static Map<String, Function<Integer, Fruit>> map = new HashMap<>(); 
static {
	map.put("apple", Apple::new); 
	map.put("orange", Orange::new);
}

public static Fruit giveMeFruit(String fruit, Integer weight) {
	return map.get(fruit.toLowerCase()) 
    		.apply(weight);
}

ν€΄μ¦ˆ 3-7

Color(int, int, int) 처럼 μΈμˆ˜κ°€ 3개인 μƒμ„±μžμ˜ μƒμ„±μž μ°Έμ‘°λŠ”?

μ •λ‹΅
Color::new
-> μ‹œκ·Έλ‹ˆμ²˜λ₯Ό μ œκ³΅ν•˜λŠ” ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€κ°€ ν•„μš”ν•˜λ‹€.

public interface TriFunction<T, U, V, R> {
	R apply(T t, U u, V v);
}


// 이와 같이 μ‚¬μš© ν•  수 μžˆλ‹€.
TriFunction<Integer, Integer, Integer, Color> colorFactory = Color::new;

πŸ“– 3.7 λžŒλ‹€, λ©”μ„œλ“œ μ°Έμ‘° ν™œμš©ν•˜κΈ°

λ‹€μ–‘ν•œ μ •λ ¬ κΈ°λ²•μœΌλ‘œ μ •λ ¬ν•˜λŠ” 문제λ₯Ό ν•΄κ²°ν•΄λ³΄μž. μ§€κΈˆκΉŒμ§€ 배운 λ™μž‘ νŒŒλΌλ―Έν„°ν™”, 읡λͺ… 클래슀, λžŒλ‹€ ν‘œν˜„μ‹, λ©”μ„œλ“œ μ°Έμ‘° 등을 μ΄λ™μ›ν•œλ‹€.

3.7.1 1단계 : μ½”λ“œ 전달

sortλŠ” λ‹€μŒκ³Ό 같은 μ‹œκ·Έλ‹ˆμ²˜λ₯Ό κ°–λŠ”λ‹€.

void sort(Comparator<? super E> c)

@FunctionalInterface
public interface Comparator<T> {
	int compare(T o1, T o2);
}

sort의 λ™μž‘μ€ νŒŒλΌλ―Έν„°ν™”λ˜μ—ˆλ‹€.
1λ‹¨κ³„λŠ” λ‹€μŒκ³Ό 같이 μ™„μ„± ν•  수 μžˆλ‹€.

public class AppleComparator implements Comparator<Apple> {
	public int compare(Apple a1, Apple a2){
		return a1.getWeight().compareTo(a2.getWeight());
	}
}
inventory.sort(new AppleComparator());

3.7.2 2단계 : 읡λͺ… 클래슀 μ‚¬μš©

inventory.sort(new Comparator<Apple>() { 
	public int compare(Apple a1, Apple a2){
		return a1.getWeight().compareTo(a2.getWeight());
	}
})οΌ›

3.7.3 3단계 : λžŒλ‹€ ν‘œν˜„μ‹ μ‚¬μš©

좔상 λ©”μ„œλ“œμ˜ μ‹œκ·Έλ‹ˆμ²˜(ν•¨μˆ˜ λ””μŠ€ν¬λ¦½ν„°λΌ 뢈림)λŠ” λžŒλ‹€ ν‘œν˜„μ‹μ˜ μ‹œκ·Έλ‹ˆμ²˜λ₯Ό μ •μ˜ν•œλ‹€. Comparator의 ν•¨μˆ˜ λ””μŠ€ν¬λ¦½ν„°λŠ” (T, T) -> intλ‹€.
μš°λ¦¬λŠ” 사과λ₯Ό μ‚¬μš©ν•  κ²ƒμ΄λ―€λ‘œ 더 μ •ν™•νžˆλŠ” (Apple, Apple) -> int둜 ν‘œν˜„ν•  수 μžˆλ‹€.

inventory.sort((Apple a1, Apple a2) ->
			a1.getWeight().compareTo(a2.getWeight())
)οΌ›

// λ‹€μŒκ³Ό 같이 더 κ°„λ‹¨νžˆ ν•  수 μžˆλ‹€.
inventory.sort((a1, a2) -> a1.getWeight().compareTo(a2.getWeight()))οΌ›



// 찐찐막 κ°„λ‹¨νžˆλŠ”?
Comparator<Apple> c = Comparator.comparing((Apple a) -> a.getWeight());

inventory.sort(comparing(apple -> apple.getWeight()));

// comparing(이 λ©”μ„œλ“œκ°€ 정적 λ©”μ„œλ“œμΈ μ΄μœ λŠ” 9μž₯μ—μ„œ μ„€λͺ…함)
public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
            Function<? super T, ? extends U> keyExtractor)
    {
        Objects.requireNonNull(keyExtractor);
        return (Comparator<T> & Serializable)
            (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
    }

3.7.4 4단계 : λ©”μ„œλ“œ μ°Έμ‘° μ‚¬μš©

κ°„μ†Œ, 깔끔

inventory.sort(comparing(Apple::getWeight));

πŸ“– 3.8 λžŒλ‹€ ν‘œν˜„μ‹μ„ μ‘°ν•©ν•  수 μžˆλŠ” μœ μš©ν•œ λ©”μ„œλ“œ

μžλ°” 8 API의 λͺ‡λͺ‡ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λŠ” λ‹€μ–‘ν•œ μœ ν‹Έλ¦¬ν‹° λ©”μ„œλ“œλ₯Ό ν¬ν•¨ν•œλ‹€. 예λ₯Ό λ“€μ–΄ Comparator, Function, Predicate κ°™μ€ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λŠ” λžŒλ‹€ ν‘œν˜„μ‹μ„ μ‘°ν•©ν•  수 μžˆλ„λ‘ μœ ν‹Έλ¦¬ν‹° λ©”μ„œλ“œλ₯Ό μ œκ³΅ν•œλ‹€.
κ°„λ‹¨νžˆ 말해, κ°„λ‹¨ν•œ μ—¬λŸ¬ 개의 λžŒλ‹€ ν‘œν˜„μ‹μ„ μ‘°ν•©ν•΄μ„œ λ³΅μž‘ν•œ λžŒλ‹€ ν‘œν˜„μ‹μ„ λ§Œλ“€ 수 μžˆλ‹€λŠ” 것이닀.
??? ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λŠ” ν•˜λ‚˜μ˜ 좔상 λ©”μ„œλ“œλ§Œ μ œκ³΅ν• ν…λ° μ–΄λ–»κ²Œ μœ ν‹Έλ¦¬ν‹° λ©”μ„œλ“œλ₯Ό μ œκ³΅ν•œλ‹€λŠ” 것인가?
-> 해닡은 λ””ν΄νŠΈ λ©”μ„œλ“œ(default method)에 μžˆλ‹€. (μžμ„Έν•œ λ‚΄μš©μ€ 9μž₯μ—μ„œ λ΄…μ‹œλ‹Ή)

3.8.1 Comparator μ‘°ν•©

  • μ—­μ •λ ¬
inventory.sort(comparing(Apple::getWeight).reversed()); 
  • Comparator μ—°κ²°

λ¬΄κ²Œκ°€ 같은 두 사과과 μ‘΄μž¬ν•œλ‹€λ©΄ μ–΄λ–»κ²Œ ν•΄μ•Ό ν• κΉŒ?
-> λ‘λ²ˆμ§Έ Comparator을 λ§Œλ“€μ–΄μ„œ μ—°κ²°ν•΄μ£Όμž!

inventory.sort(comparing(Apple::getWeight)
		.reversed()
		.thenComparing(Apple::getCountry)); 

3.8.2 Predicate μ‘°ν•©

Predicate μΈν„°νŽ˜μ΄μŠ€λŠ” λ³΅μž‘ν•œ ν”„λ ˆλ””μΌ€μ΄νŠΈλ₯Ό λ§Œλ“€ 수 μžˆλ„λ‘ negate, and, or μ„Έ 가지 λ©”μ„œλ“œλ₯Ό μ œκ³΅ν•œλ‹€. 예λ₯Ό λ“€μ–΄ β€˜λΉ¨κ°„μƒ‰μ΄ μ•„λ‹Œ μ‚¬κ³Όμ²˜λŸΌ νŠΉμ • ν”„λ ˆλ””μΌ€μ΄νŠΈλ₯Ό λ°˜μ „μ‹œν‚¬ λ•Œ negate λ©”μ„œλ“œλ₯Ό μ‚¬μš© ν•  수 μžˆλ‹€.

Predicate<Apple> notRedApple = redApple.negate();

and λ©”μ„œλ“œλ₯Ό μ΄μš©ν•΄μ„œ λΉ¨κ°„μƒ‰μ΄λ©΄μ„œ λ¬΄κ±°μš΄μ‚¬κ³Όλ₯Ό μ„ νƒν•˜λ„λ‘ 두 λžŒλ‹€λ₯Ό μ‘°ν•© ν•  수 μžˆλ‹€.

Predicate<Apple> redAndHeavyApple = 
		redApple.and(apple -> apple.getWeight() > 150);

or을 μ΄μš©ν•΄μ„œ β€˜λΉ¨κ°„μƒ‰μ΄λ©΄μ„œ 무거운(150그램 이상) 사과 λ˜λŠ” κ·Έλƒ₯ 녹색 사과’
λ“± λ‹€μ–‘ν•œ 쑰건을 λ§Œλ“€μˆ˜ μžˆλ‹€.

Predicate<Apple> redAndHeavyAppleOrGreen =
	redApple.and(apple -> apple.getWeight() > 150)
		.or(apple -> GREEN.equals(a .getColor()));

3.8.3 Function μ‘°ν•©

andThen, compose 두 가지 λ””ν΄νŠΈ λ©”μ„œλ“œλ₯Ό μ œκ³΅ν•œλ‹€.

  • andThen
Function<Integer, Integer> f = x -> x + 1;
Function<Integer, Integer> g = x -> x * 2; 
Function<Integer, Integer> h = f.andThen(g); 
int result = h.apply(1); // 4λ₯Ό λ°˜ν™˜

-> 머리와 꼬리가 κ°™μ•„μ•Ό 맀칭 κ°€λŠ₯!

  • compose
Function<Integer, Integer> f = x -> x + 1;
Function<Integer, Integer> g = x -> x * 2;
Function<Integer, Integer> h = f.compose(g); // μˆ˜ν•™μœΌλ‘œλŠ” f(g(x))λ˜λŠ” (f ∘ g)(x) λΌκ³ ν‘œν˜„
int result = h.apply(1); // 3을 λ°˜ν™˜





참고자료)
λ³Έ ν¬μŠ€νŠΈλŠ” λͺ¨λ˜ μžλ°” 인 μ•‘μ…˜ 책을 μ°Έκ³ ν•˜μ—¬ μž‘μ„±ν•˜μ˜€μŠ΅λ‹ˆλ‹€.

profile
λ©ˆμΆ”μ§€ μ•ŠκΈ°

0개의 λŒ“κΈ€