[02] Lambda Expression

MIIINยท2023๋…„ 3์›” 7์ผ
0

Modern Java

๋ชฉ๋ก ๋ณด๊ธฐ
2/8
post-thumbnail

๐Ÿƒ ๋žŒ๋‹ค ํ‘œํ˜„์‹

๋žŒ๋‹ค ํ‘œํ˜„์‹์€ ์ต๋ช… ํด๋ž˜์Šค(Anonymous Class)์ฒ˜๋Ÿผ ์ด๋ฆ„์ด ์—†๋Š” ํ•จ์ˆ˜๋ฉด์„œ ๋ฉ”์„œ๋“œ๋ฅผ ์ธ์ˆ˜๋กœ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค. ๋žŒ๋‹ค ํ‘œํ˜„์‹์—๋Š” ์ด๋ฆ„์€ ์—†์ง€๋งŒ, Parameter List, Body, Return Type, ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” Exception List๋ฅผ ํฌํ•จํ•  ์ˆ˜ ์žˆ๋‹ค.

๋žŒ๋‹ค์˜ ํŠน์ง•

  • ์ต๋ช…
    - ๋ณดํ†ต์˜ ๋ฉ”์„œ๋“œ์™€ ๋‹ฌ๋ฆฌ ์ด๋ฆ„์ด ์—†๋‹ค.
  • ํ•จ์ˆ˜
    - ๋ฉ”์„œ๋“œ์ฒ˜๋Ÿผ ํŠน์ • ํด๋ž˜์Šค์— ์ข…์†๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ ํ•จ์ˆ˜๋ผ ํ•œ๋‹ค.
    - ๋ฉ”์„œ๋“œ์ฒ˜๋Ÿผ Parameter List, Body, Return Type, ๊ฐ€๋Šฅํ•œ Exception List๋ฅผ ํฌํ•จํ•œ๋‹ค.
  • ์ „๋‹ฌ
    - ๋žŒ๋‹ค ํ‘œํ˜„์‹์„ ๋ฉ”์„œ๋“œ ์ธ์ˆ˜๋กœ ์ „๋‹ฌํ•˜๊ฑฐ๋‚˜ ๋ณ€์ˆ˜๋กœ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๊ฐ„๊ฒฐ์„ฑ
    - ์ต๋ช… ํด๋ž˜์Šค์ฒ˜๋Ÿผ ๋งŽ์€ ์ฝ”๋“œ๋ฅผ ๊ตฌํ˜„ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.
-- ๊ธฐ์กด
Comparator<Apple> byWeight = new Comparator<Apple>() {
	public int compare(Apple a1, Apple a2) {
    	return a1.getWeight().compareTo(a2.getWeight());
    }
}

-- ๋žŒ๋‹ค ํ‘œํ˜„์‹
Comparator<Apple> byWeight = (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight());

์œ„ ์ฒ˜๋Ÿผ ๋žŒ๋‹ค ํ‘œํ˜„์‹์€ ์„ธ ๋ถ€๋ถ„์œผ๋กœ ๊ตฌ์„ฑ๋œ๋‹ค.
1. ํŒŒ๋ผ๋ฏธํ„ฐ ๋ฆฌ์ŠคํŠธ
2. ํ™”์‚ดํ‘œ
3. ๋žŒ๋‹ค ๋ฐ”๋””


๐Ÿš ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค

ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์ •ํ™•ํžˆ ํ•˜๋‚˜์˜ ์ถ”์ƒ ๋ฉ”์„œ๋“œ๋ฅผ ์ง€์ •ํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋‹ค. ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค์—๋Š” @FunctionalInterface ์–ด๋…ธํ…Œ์ด์…˜์ด ์ถ”๊ฐ€๋˜์–ด ์žˆ์œผ๋ฉฐ, ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค์ž„์„ ๊ฐ€๋ฆฌํ‚จ๋‹ค.

์ž๋ฐ” API์˜ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋กœ Predicate, Comparator, Runnable ๋“ฑ์ด ์žˆ๋‹ค.

// java.util.function.Predicate
public interface Predicate<T> {
	boolean test(T t);
}

// java.util.Comparator
public interface Comparator<T> {
	int compare(T o1, T o2);
}

// java.lang.Runnable
public interface Runnable {
	void run();
}

// java.awt.event.ActionListener
public interface ActionListener extends EventListener {
	void actionPerformed(ActionEvent e);
}

// java.util.concurrent.Callable
public interface Callable<V> {
	V call() throws Exception;
}

// java.security.PrivilegedAction
public interface PrivilegedAction<T> {
	T run();
}

๋žŒ๋‹ค ํ‘œํ˜„์‹์œผ๋กœ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค์˜ ์ถ”์ƒ ๋ฉ”์„œ๋“œ ๊ตฌํ˜„์„ ์ง์ ‘ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ „์ฒด ํ‘œํ˜„์‹์„ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค์˜ ์ธ์Šคํ„ด์Šค๋กœ ์ทจ๊ธ‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

// ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค Runnable
Runnable r = () -> System.out.println("Hello World!");
r.run();

// ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค Callable
public Callable<String> fetch() {
	return () -> "Tricky example ;-)";
}
System.out.println(a1.fetch().call());

Function Descriptor

ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค์˜ ์ถ”์ƒ ๋ฉ”์„œ๋“œ ์‹œ๊ทธ๋‹ˆ์ฒ˜๋ฅผ ํ•จ์ˆ˜ ๋””์Šคํฌ๋ฆฝํ„ฐ๋ผ๊ณ  ํ•œ๋‹ค. ๋‹ค์–‘ํ•œ ๋žŒ๋‹ค ํ‘œํ˜„์‹์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๊ณตํ†ต์˜ ํ•จ์ˆ˜ ๋””์Šคํฌ๋ฆฝํ„ฐ๋ฅผ ๊ธฐ์ˆ ํ•˜๋Š” ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค ์ง‘ํ•ฉ์ด ํ•„์š”ํ•˜๋‹ค.

1) java.util.function.Predicate<T>

test๋ผ๋Š” ์ถ”์ƒ ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•˜๋ฉฐ ์ œ๋„ค๋ฆญ ํ˜•์‹ T์˜ ๊ฐ์ฒด๋ฅผ ์ธ์ˆ˜๋กœ ๋ฐ›์•„ boolean์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

@FunctionalInterface
public interface Predicate<T> {
	boolean test(T t);
}

public <T> List<T> filter(List<T> list, Predicate<T> p) {
	List<T> results = new ArrayList<>();
	for (T t : list) {
		if (p.test(t)) {
			results.add(t);
		}
	}
	return results;
}

List<String> nonEmpty = filter(listOfStrings, (String s) -> !s.isEmpty());

2) java.util.function.Consumer<T>

accept๋ผ๋Š” ์ถ”์ƒ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•˜๋ฉฐ ์ œ๋„ค๋ฆญ ํ˜•์‹ T์˜ ๊ฐ์ฒด๋ฅผ ์ธ์ˆ˜๋กœ ๋ฐ›์•„ void๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

@FunctionalInterface
public interface Consumer<T> {
	void accept(T t);
}

public <T> void forEach(List<T> list, Consumer<T> c) {
	for (T t : list) {
		c.accept(t);
	}
}

forEach(Arrays.asList(1, 2, 3, 4, 5), (Integer i) -> System.out.println(i));

3) java.util.function.Function<T, R>

apply๋ผ๋Š” ์ถ”์ƒ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•˜๋ฉฐ ์ œ๋„ค๋ฆญ ํ˜•์‹ T์˜ ๊ฐ์ฒด๋ฅผ ์ธ์ˆ˜๋กœ ๋ฐ›์•„์„œ ์ œ๋„ค๋ฆญ ํ˜•์‹ R ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

@FunctionalInterface
public interface Function<T, R> {
	R apply(T t);
}

public <T, R> List<R> map(List<T> list, Function<T, R> f) {
	List<R> result = new ArrayList<>();
	for (T t : list) {
		result.add(f.apply(t));
	}
	return result;
}

List<Integer> list = map(Arrays.asList("lambdas", "in", "action"), (String s) -> s.length());

4) ํŠนํ™”๋œ ํ˜•์‹์˜ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค

์ž๋ฐ”์˜ ๋ชจ๋“  ํ˜•์‹์€ ์ฐธ์กฐํ˜• ์•„๋‹ˆ๋ฉด ๊ธฐ๋ณธํ˜•์— ํ•ด๋‹นํ•˜๋Š”๋ฐ, ์ด์ „์— ์‚ดํŽด๋ณธ ์„ธ ๊ฐœ์˜ ์ œ๋„ค๋ฆญ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค Predicate<T>, Consumer<T>, Function<T, R>์€ ์ฐธ์กฐํ˜•๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. Java์—์„œ๋Š” ๊ธฐ๋ณธํ˜•๊ณผ ์ฐธ์กฐํ˜• ๊ฐ„์˜ ์ž๋™ ๋ณ€ํ™˜ (Auto Boxing/Unboxing) ์„ ์ง€์›ํ•œ๋‹ค.

-- Auto Boxing : int (๊ธฐ๋ณธํ˜•) -> Integer (์ฐธ์กฐํ˜•)
List<Integer> list = new ArrayList<>();
for (int i=300; i<400; i++) {
	list.add(i);
}

ํ•˜์ง€๋งŒ, ์ด๋Ÿฌํ•œ Boxing/Unboxing ๊ณผ์ •์—์„œ Boxingํ•œ ๊ฐ’์€ ๊ธฐ๋ณธํ˜•์„ ๊ฐ์‹ธ๋Š” Wrapper๋กœ์จ Heap์— ์ €์žฅ๋˜์–ด ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋” ์†Œ๋น„ํ•˜๋ฉฐ ๊ธฐ๋ณธํ˜•์„ ๊ฐ€์ ธ์˜ฌ ๋•Œ๋„ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํƒ์ƒ‰ํ•œ๋‹ค. Java 8์—์„œ๋Š” ๊ธฐ๋ณธํ˜•์„ ์ž…์ถœ๋ ฅ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ์ƒํ™ฉ์—์„œ Auto Boxing/Unboxing์„ ํ”ผํ•  ์ˆ˜ ์žˆ๋„๋ก ํŠน๋ณ„ํ•œ ํ˜•์‹์˜ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šคํ•จ์ˆ˜ ๋””์Šคํฌ๋ฆฝํ„ฐboolean ํŠนํ™”int ํŠนํ™”long ํŠนํ™”double ํŠนํ™”
Predicate<T>T -> booleanIntPredicateLongPredicateDoublePredicate
Consumer<T>T -> voidIntConsumerLongConsumerDoubleConsumer
Function<T, R>T -> RIntFunction<R>LongFunction<R>DoubleFunction<R>
IntToLongFunctionLongToIntFunctionDoubleToIntFunction
IntToDoubleFunctionLongToDoubleFunctionDoubleToLongFunction
ToIntFunction<T>ToLongFunction<T>ToDoubleFunction<T>
Supplier<T>() -> TBooleanSupplierIntSupplierLongSupplierDoubleSupplier
UnaryOperator<T>T -> TIntUnaryOperatorLongUnaryOperatorDoubleUnaryOperator
BinaryOperator<T>(T, T) -> TIntBinaryOperatorLongBinaryOperatorDoubleBinaryOperator
BiPredicate<T, U>(T, U) -> boolean
BiConsumer<T, U>(T, U) -> voidObjIntConsumer<T>ObjLongConsumer<T>ObjDoubleConsumer<T>
BiFunction<T, U, R>(T, U) -> RToIntBiFunction<T, U>ToLongBiFunction<T, U>ToDoubleBiFunction<T, U>
@FunctionalInterface
public interface intPredicate {
	boolean test(int t);
}

-- Auto Boxing
Predicate<Integer> oddNumbers = (Integer i) -> i % 2 != 0;
oddNumbers.test(1000);

-- Non Boxing
IntPredicate evenNumbers = (int i) -> i % 2 == 0;
evenNumbers.test(1000);

5) ๋žŒ๋‹ค์™€ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค

์‚ฌ์šฉ ์‚ฌ๋ก€๋žŒ๋‹ค ์˜ˆ์ œํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค
boolean ํ‘œํ˜„(List<String> list) -> list.isEmpty()Predicate<List<String>>
Object ์ƒ์„ฑ() -> new Apple(10)Supplier<Apple>
Object ์†Œ๋น„(Apple a) -> System.out.println(a.getWeight())Consumer<Apple>
Object ์„ ํƒ/์ถ”์ถœ(String s) -> s.lengthFunction<String, Integer>
ToIntFunction<String>
๋‘ ๊ฐ’ ์กฐํ•ฉ(int a, int b) -> a * bIntUnaryOperator
๋‘ ๊ฐ์ฒด ๋น„๊ต(Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight())Comparator<Apple>
BiFunction<Apple, Apple, Integer>
ToIntBiFunction<Apple, Apple>

๐Ÿ“ˆ Execute Around Pattern

์ž์› ์ฒ˜๋ฆฌ์— ์‚ฌ์šฉํ•˜๋Š” ์ˆœํ™˜ ํŒจํ„ด์€ ์ž์›์„ ์—ด๊ณ  (Open), ์ฒ˜๋ฆฌํ•œ ๋‹ค์Œ์— (Process), ์ž์›์„ ๋‹ซ๋Š” (Close) ์ˆœ์„œ๋กœ ์ด๋ฃจ์–ด์ง„๋‹ค. ์ด์™€ ๋น„์Šทํ•˜๊ฒŒ ์ฝ”๋“œ๋ฅผ ์ดˆ๊ธฐํ™”/์ค€๋น„ ํ•˜๊ณ  (init/ready), ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•œ ๋‹ค์Œ์— (work), ์ •๋ฆฌ/๋งˆ๋ฌด๋ฆฌ ํ•˜๋Š” (final) ํŒจํ„ด์ด๋‹ค.

์—ฌ๊ธฐ์„œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” work์— ๋žŒ๋‹ค์™€ ๋™์ž‘ ํŒŒ๋ผ๋ฏธํ„ฐํ™”๋กœ ์œ ์—ฐํ•˜๊ณ  ๊ฐ„๊ฒฐํ•œ ์ฝ”๋“œ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

-- ํŒŒ์ผ์„ ์ฝ๋Š” ์ฝ”๋“œ
-- ๊ธฐ์กด ๋ฐฉ๋ฒ• (๋™์ž‘ : ํ•œ ์ค„ ์ฝ๊ธฐ)
public String processFile() throws IOException {
	try (BufferedReader br = new BufferedReader(new FileReader("data.txt"))) {
		return br.readLine();
	}
}

-- 1๋‹จ๊ณ„ : ํŒŒ์ผ์„ ์ฝ์–ด์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ๋™์ž‘์„ ํŒŒ๋ผ๋ฏธํ„ฐํ™” (ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค)
public interface BufferedReaderProcessor {
	String process(BufferedReader b) throws IOException;
}

-- 2๋‹จ๊ณ„ : ๋™์ž‘ ์ „๋‹ฌ ๋ฐ ์‹คํ–‰
public String processFile(BufferedReaderProcessor p) throws IOException {
	try (BufferedReader br = new BufferedReader(new FileReader("data.txt"))) {
		return p.process(br);
	}
}

-- 3๋‹จ๊ณ„ : ๋žŒ๋‹ค ํ‘œํ˜„์‹
String oneLine = processFile(br -> br.readLine());
String twoLine = processFile(br -> br.readLine() + "\r\n" + br.readLine());

๐Ÿ‘€ Method Reference

๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋ฅผ ์ด์šฉํ•˜๋ฉด ๊ธฐ์กด์˜ ๋ฉ”์„œ๋“œ ์ •์˜๋ฅผ ์žฌํ™œ์šฉํ•ด์„œ ๋žŒ๋‹ค์ฒ˜๋Ÿผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค. ๋ฉ”์„œ๋“œ๋ช… ์•ž์— ๊ตฌ๋ถ„์ž(::)๋ฅผ ๋ถ™์ด๋Š” ๋ฐฉ์‹์œผ๋กœ ๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

-- ๊ธฐ์กด
inventory.sort((Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight()));

-- Method Reference : java.util.Comparator.comparing ํ™œ์šฉ
inventory.sort(comparing(Apple::getWeight));

๋ฉ”์„œ๋“œ ์ฐธ์กฐ์˜ 3๊ฐ€์ง€ ์œ ํ˜•

1) ์ •์  ๋ฉ”์„œ๋“œ ์ฐธ์กฐ
- Ex) Integer.parseInt ๋ฉ”์„œ๋“œ๋ฅผ Integer::parseInt๋กœ ํ‘œํ˜„
2) ๋‹ค์–‘ํ•œ ํ˜•์‹์˜ ์ธ์Šคํ„ด์Šค ๋ฉ”์„œ๋“œ ์ฐธ์กฐ
- Ex) String์˜ length ๋ฉ”์„œ๋“œ๋ฅผ String::length๋กœ ํ‘œํ˜„
3) ๊ธฐ์กด ๊ฐ์ฒด์˜ ์ธ์Šคํ„ด์Šค ๋ฉ”์„œ๋“œ ์ฐธ์กฐ
- Ex) Apple ๊ฐ์ฒด์˜ getColor ๋ฉ”์„œ๋“œ๋ฅผ Apple::getColor๋กœ ํ‘œํ˜„

์ƒ์„ฑ์ž, ๋ฐฐ์—ด ์ƒ์„ฑ์ž, super ํ˜ธ์ถœ ๋“ฑ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํŠน๋ณ„ํ•œ ํ˜•์‹์˜ ๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋„ ์žˆ๋‹ค. List์˜ sort ๋ฉ”์„œ๋“œ๋Š” ์ธ์ˆ˜๋กœ Comparator๋ฅผ ๊ธฐ๋Œ€ํ•˜๋ฉฐ, Comparator๋Š” (T, T) -> int ๋ผ๋Š” ํ•จ์ˆ˜ ๋””์Šคํฌ๋ฆฝํ„ฐ๋ฅผ ๊ฐ–๋Š”๋‹ค.

-- ๊ธฐ์กด : ๋Œ€์†Œ๋ฌธ์ž ๊ตฌ๋ณ„์—†์ด ์ •๋ ฌ
List<String\> str = Arrays.asList("a", "b", "A", "B");
str.sort((s1, s2) -> s1.compareToIgnoreCase(s2));

-- Method Reference
str.sort(String::compareToIgnoreCase);

์ƒ์„ฑ์ž ์ฐธ์กฐ

ClassName::new ์ฒ˜๋Ÿผ ํด๋ž˜์Šค๋ช…๊ณผ new ํ‚ค์›Œ๋“œ๋ฅผ ์ด์šฉํ•˜์—ฌ ๊ธฐ์กด ์ƒ์„ฑ์ž์˜ ์ฐธ์กฐ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

-- ๊ธฐ์กด
Supplier<Apple> s = () -> new Apple();
Function<Integer, Apple> f = (weight) -> new Apple(weight);

-- ์ƒ์„ฑ์ž ์ฐธ์กฐ
Supplier<Apple> s = Apple::new;
Function<Integer, Apple> f = Apple::new;

Apple a1 = s.get();
Apple a2 = f.apply(100);

-- ์‹ฌํ™” : ์—ฌ๋Ÿฌ ๊ฐ์ฒด ์ƒ์„ฑ
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;
}

๐Ÿ”ฉ ๋žŒ๋‹ค ํ‘œํ˜„์‹ ์กฐํ•ฉ

Java 8 API์˜ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๋žŒ๋‹ค ํ‘œํ˜„์‹์„ ์กฐํ•ฉํ•  ์ˆ˜ ์žˆ๋Š” ์œ ํ‹ธ๋ฆฌํ‹ฐ ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•œ๋‹ค. ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋žŒ๋‹ค ํ‘œํ˜„์‹์„ ์กฐํ•ฉํ•ด์„œ ๋ณต์žกํ•œ ๋žŒ๋‹ค ํ‘œํ˜„์‹์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

Comparator ์กฐํ•ฉ

1) comparing
๋น„๊ต์— ์‚ฌ์šฉํ•  ํ‚ค๋ฅผ ์ถ”์ถœํ•˜๋Š” Function ๊ธฐ๋ฐ˜์€ Comparator๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

Comparator<Apple> c = Comparator.comparing(Apple::getWeight);

2) reversed
์—ญ์ˆœ์„ ์ ์šฉํ•˜๋Š” Comparator๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

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

3) thenComparing
์ด์ „ Comparator์— ์ด์–ด์„œ ๋‹ค์Œ Comparator๋ฅผ ์ „๋‹ฌํ•œ๋‹ค.

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

Predicate ์กฐํ•ฉ

1) negate
ํŠน์ • Predicate๋ฅผ ๋ฐ˜์ „์‹œํ‚จ๋‹ค.

-- ๋นจ๊ฐ„ ์‚ฌ๊ณผ Predicate
Predicate<Apple> redApple = e -> "RED".equals(e.getColor());

-- ๋นจ๊ฐ„ ์‚ฌ๊ณผ๊ฐ€ ์•„๋‹Œ Predicate
Predicate<Apple> notRedApple = redApple.negate();

2) and
And ์กฐ๊ฑด์œผ๋กœ Predicate๋ฅผ ์—ฐ๊ฒฐํ•œ๋‹ค.

-- ๋นจ๊ฐ„ ์ƒ‰์ด๋ฉด์„œ ๋ฌด๊ฑฐ์šด ์‚ฌ๊ณผ
Predicate<Apple> redAndHeavyApple = redApple.and(a -> a.getWeight() > 150);

3) or
Or ์กฐ๊ฑด์œผ๋กœ Prdicate๋ฅผ ์—ฐ๊ฒฐํ•œ๋‹ค.

-- ๋นจ๊ฐ„์ƒ‰์ด๋ฉด์„œ ๋ฌด๊ฑฐ์šด ์‚ฌ๊ณผ ๋˜๋Š” ๋…น์ƒ‰ ์‚ฌ๊ณผ
Predicate<Apple> redAndHeavyAppleOrGreenApple = 
	redApple
		.and(a -> a.getWeight() > 150)
		.or(a -> "GREEN".equals(a.getColor());

Function ์กฐํ•ฉ

1) andThen
์ฃผ์–ด์ง„ Function๋ฅผ ๋จผ์ € ์ ์šฉํ•œ ๊ฒฐ๊ณผ๋ฅผ ๋‹ค๋ฅธ Function์˜ ์ž…๋ ฅ์œผ๋กœ ์ „๋‹ฌํ•œ๋‹ค.

Function<String, String> addHeader = Letter::addHeader;
Function<String, String> transformationPipeline = 
	addHeader
		.andThen(Letter::checkSpelling)
		.andThen(Letter::addFooter);

2) compose
์ธ์ˆ˜๋กœ ์ฃผ์–ด์ง„ Function๋ฅผ ๋จผ์ € ์‹คํ–‰ํ•œ ๋‹ค์Œ์— ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ์™ธ๋ถ€ Function์˜ ์ธ์ˆ˜๋กœ ์ „๋‹ฌํ•œ๋‹ค.


profile
๋ฐฑ์—”๋“œ๊ฐœ๋ฐœ์ž

0๊ฐœ์˜ ๋Œ“๊ธ€