β ν¨μν μΈν°νμ΄μ€ νμ€ API μ΄μ 리
ν¨μν μΈν°νμ΄μ€ νμ€ API
ν¨μν μΈν°νμ΄μ€(functional interface)λ μΆμλ©μλκ° 1κ°λ§ μ μλ μΈν°νμ΄μ€λ₯Ό ν΅μΉνμ¬ μΌμ»«λλ€. μ΄ μΈν°νμ΄μ€ ννμ λͺ©μ μ μλ°μμ λλ€ ννμ(Lambda Expression)μ μ΄μ©ν΄ ν¨μν νλ‘κ·Έλλ°μ ꡬννκΈ° μν΄μ μ΄λ€.
// @FunctionalInterface μ΄λ
Έν
μ΄μ
μ μΈν°νμ΄μ€μ λΆμ¬μ£Όλ©΄,
// λ κ° μ΄μμ λ©μλ μ μΈ μ μ»΄νμΌ μ€λ₯λ₯Ό λ°μμμΌ κ°λ°μμ μ€μλ₯Ό μ€μΌ μ μλ€.
@FunctionalInterface
public interface Animal {
public void method();
}
κ·Έλ°λ° κ³°κ³°ν μκ°ν΄λ³΄λ©΄ ν¨μμ νν(Signature)λ λ€μνλ€. ν¨μμ λ¦¬ν΄ κ°μ΄ μμμλ μμμλ μκ³ λ§€κ°λ³μ κ°―μκ° 1κ° νΉμ 2κ°μΌ μλ μλ€. μ΄λ¬ν ννμ ν¨μλ₯Ό μΌμΌν μ μν΄μ μ¬μ©νκΈ°μ λ무 μμ΄ λ§μΌλ, μλ° κ°λ°μ§λ€μ΄ 미리 ν¨μν μΈν°νμ΄μ€λ₯Ό λ§λ€μ΄ μ 곡νλ κ²μ΄ λ°λ‘ μ΄λ² μκ°μ λ°°μΈ ν¨μν μΈν°νμ΄μ€ νμ€ API μ΄λ€.
μλ°μμ μλ£κ΅¬μ‘°λ₯Ό 컬λ μ νλ μμν¬λ‘ 미리 λ§λ€μ΄ μ 곡νλ―μ΄, μμ£Ό μ¬μ©ν κ² κ°μ λλ€ ν¨μ ννλ₯Ό ν¨μν μΈν°νμ΄μ€ νμ€ APIλ‘ λ―Έλ¦¬ λ§λ€μ΄ μ 곡ν΄μ€λ€λΌκ³ μ΄ν΄νλ©΄ λλ€.
νμ€ API μ’ λ₯
ν¨μμ μΈν°νμ΄μ€ νμ€ APIλ java.util.function ν¨ν€μ§λ‘ μ 곡λλ€. μ΄ ν¨ν€μ§ μμ μλ ν¨μμ μΈν°νμ΄μ€ μ’
λ₯λ‘λ Consumer, Supplier, Function, Operator, Predicate κ° μλ€. μ΄ μΈν°νμ΄μ€λͺ
μ κ° ν¨μμ ννμ λͺ©μ μ λ°λΌ μ‘°κΈ μ¬λ―Έμκ² λΆμ¬μ§ μ΄λ¦μΈλ° μ΄μ λν΄μλ λ€μμ μμΈν λ€λ£¬λ€.
import java.util.function.*;
ν¨μν μΈν°νμ΄μ€ | λ©μλ νν | API νμ© | 맀κ°λ³μ | λ°νκ° |
Runnable | void run() | λ§€κ° λ³μλ₯Ό μ¬μ© μνκ³ λ¦¬ν΄μ νμ§ μλ ν¨μ ννλ‘ μ΄μ© λνμ μΌλ‘ μ°λ λμ λ§€κ° λ³μλ‘ μ΄μ© |
X | X |
Consumer<T> | void accept(T t) | λ§€κ° λ³μλ₯Ό μ¬μ©λ§ νκ³ λ¦¬ν΄μ νμ§ μλ ν¨μ ννλ‘ μ΄μ© | O | X |
Supplier<T> | T get() | λ§€κ° λ³μλ₯Ό μ¬μ© μνκ³ λ¦¬ν΄λ§ νλ ν¨μ ννλ‘ μ΄μ© | X | O |
Function<T, R> | R apply(T t) | 맀κ°κ°μ 맀ν(=νμ λ³ν)ν΄μ 리ν΄νκΈ° | O | O |
Predicate<T> | boolean test(T t) | 맀κ°κ°μ΄ 쑰건μ λ§λμ§ λ¨μ ν΄μ boolean λ¦¬ν΄ | O | O |
Operator | R applyAs(T t) | 맀κ°κ°μ μ°μ°ν΄μ κ²°κ³Ό 리ν΄νκΈ° | O | O |
(T: λ°μ΄ν° νμ , R: λ¦¬ν΄ νμ )
μ΄ μ²λΌ λ€μν ν¨μμ ννκ° λ μ μλ κ²λ€μ μΆλ € λͺ¨μ μ 리νμ¬ APIλ‘ μ 곡ν¨μΌλ‘μ¨, μ°λ¦¬ κ°μ κ°λ°μλ€μ κ΅³μ΄ μΆμ λ©μλ νλ κ°μ§ μΈν°νμ΄μ€λ₯Ό μΌμΌν μ μν νμμμ΄ API λ§ κ°μ Έλ€ μ°λ©΄ λλ κ²μ΄λ€.
νμ€ APIλ νμ μ 곡 μ©λμ΄λ€
μλ°μ λλ€μμ λ³μλ 맀κ°λ³μμ ν λΉνκΈ° μν΄μλ κ·Έμ ν΄λΉνλ μΈν°νμ΄μ€ νμ μ΄ νμνλ€.
μλ₯Ό λ€μ΄ μλ°μ€ν¬λ¦½νΈ κ°μκ²½μ° μ½νμ μΈμ΄μ΄κΈ° λλ¬Έμ λ€μκ³Ό κ°μ΄ λ³μμ ν¨μλ₯Ό λμ λ§νλ©΄ μμμ νμ μΆλ‘ μ΄ λλ€.
let a = () => {};
νμ§λ§ μλ°λ κ°νμ μΈμ΄μ΄κΈ° λλ¬Έμ μ΄λ ν μ μλ©΄ μ μμ λ§λ νμ μ, ν¨μλ©΄ ν¨μμ λ§λ νμ μ μ§μ ν΄ μ£Όμ΄μΌ νλ€. κ·Έλμ λλ€ ν¨μλ₯Ό λ΄μ μ μλ λνν νμ μ μΈν°νμ΄μ€ νμ μΌλ‘ μ ν κ²μ΄λΌκ³ μ΄ν΄νλ©΄ λλ€. (μ ννλ μΈν°νμ΄μ€ μ΅λͺ ꡬν κ°μ²΄λ₯Ό κ°λ΅ν ν κ²μ΄λ€)
@FunctionalInterface
public interface Animal {
public void run();
}
// run() μ΄λΌλ λ©μλλ₯Ό μΈν°νμ΄μ€ νμ
μΌλ‘ μ μΈνμ¬ μ μ
Animal a = () -> {};
κ·Έλ°λ° ν¨μν μΈν°νμ΄μ€λΌκ³ νμ§λ§ μ¬μ€μ μΈν°νμ΄μ€λͺ μ΄ λ±ν μ ν΄μ Έ μμ§ μκΈ° λλ¬Έμ λ¬Έμ κ° λ°μνλ€. κ·Έλ₯ μΆμ λ©μλ νκ°λ§ κ°μ§κ³ μμΌλ©΄ λͺ¨λ μΈν°νμ΄μ€λ ν¨μμ μΈν°νμ΄μ€λ‘ μ·¨κΈλ μ μκΈ° λλ¬Έμ΄λ€.
μ΄κ²μ΄ μ λ¬Έμ λλ©΄ λ©μλλ₯Ό μ€κ³ν λ μ 맀ν΄μ§λ€. λ§μΌ νλΌλ―Έν°λ‘ λλ€ ν¨μλ₯Ό λ°λ μ΄λ ν λ©μλλ₯Ό μ€κ³νλ€κ³ νλ©΄, μ΄ λ§€κ°λ³μμ μΈν°νμ΄μ€ νμ λͺ μ μ§μ νλλ° μ λ‘μ¬νμ΄ μκΈ΄λ€. λΌμ΄λΈλ¬λ¦¬ μ¬μ©μκ° μΈν°νμ΄μ€ νμ λͺ μ μ΄μ° μ§μμ§ μ΄λ»κ² μκ³ κ°νμ μΈμ΄μΈ μλ°μμ μ€κ³λ₯Ό νλλμΈ λ¬Έμ μ΄λ€.
λ°λΌμ μλ° κ°λ°μ§λ€μ΄ 미리 ν¨μν μΈν°νμ΄μ€ μ΄λ¦λ€μ μ ν΄ μ 곡νλ κ²μ΄ μμ νμμ λ³Έ Runnable, Consumer, Supplier, Function, Operator, Predicate μΈν°νμ΄μ€μΈ κ²μ΄λ€.
Runnable μΈν°νμ΄μ€
ν¨μν μΈν°νμ΄μ€μ λλ€ ν¨μλ₯Ό μ΄ν΄νλλ° μμ΄ κ°μ₯ μ’μ κ²μ΄ λ°λ‘ Runnable μΈν°νμ΄μ€μ΄λ€. μ€μ μλ° ν¨ν€μ§μ μ μ λμ΄μλ Runnalbe μΈν°νμ΄μ€ μ μΈ μ½λλ₯Ό 보면 λ€μκ³Ό κ°μ΄ λμ΄ μλ€.
λ λ¬λ¦°λ€ νΉμ μ€ννλ€λΌλ μλ―ΈμΈκ² κ°μλ° λΉμ΅ μ΄λ¬ν μΈν°νμ΄μ€λ μ λ§λ€μλμ§ μ΄λμ μ¬μ©λλμ§ μ 맀λͺ¨νΈνλ€.
μμ λ§νλ―μ΄ μ΄λ¬ν μΈν°νμ΄μ€λ€μ λ§λ μ΄μ λ λλ€ ν¨μμ νμ λͺ μ 미리 μ§μ νκΈ° μν΄μ λΌκ³ νλ€. μ¦, 맀κ°λ³μλ₯Ό λ°μ§λ μκ³ λ¦¬ν΄κ°μ΄ μκ³ κ·Έλ₯ μ€νλ§ νλ λλ€ ν¨μ ννλ₯Ό λ°λ λ©μλλ₯Ό μ€κ³ν λ λλ€ λ§€κ°λ³μμ μΈν°νμ΄μ€ νμ μ Runnableλ‘ μ€μ νλ©΄ λλ κ²μ΄λ€. κ·Έλ¦¬κ³ κ·Έ λ©μλκ° λ°λ‘ μ°λ¦¬κ° μ μλ Thread ν΄λμ€μ λ©μλ(μμ±μ)μ΄λ€.
Thread thread = new Thread( () -> {
for(int i = 0; i < 10; i++) {
System.out.println(i);
}
} );
μ€μ Thread ν΄λμ€ μ μλ¬Έμ κ°μ μμ±μ ννλ₯Ό 보면 λ€μκ³Ό κ°μ΄ νλΌλ―Έν°λ‘ Runnalbe νμ
μ target λ³μλ₯Ό λ°μ μ¬μ©ν λ€λ κ²μ λ³Ό μ μλ€.
μ΄κ²μ΄ ν¨μν μΈν°νμ΄μ€ νμ€ APIμ μ‘΄μ¬ μ΄μ λ€. RunnalbeμΈμλ μ¬λ¬κ°μ§ μλ° λ©μλμμ 미리 νλΌλ―Έν° νμ μΌλ‘ μ μλ μ¬λ¬ μ’ λ₯μ ν¨μν μΈν°νμ΄μ€ νμ€ APIμ μ μλ νμ μ λ°λλ‘ μ€κ³νμκΈ° λλ¬Έμ μμ λ‘κ² λλ€μμ ν λΉ ν μ μλ κ²μ΄λ€.
ν¨μν μΈν°νμ΄μ€ API μ¬μ©λ²
μ΄μ λΆν° ν¨μμ μΈν°νμ΄μ€ APIμ ꡬ체μ μΈ μ¬μ©λ²μ λν΄ μμΈν μμλ³Ό μκ°μ κ°μ§ν λ°, μμ²λ μμ νμ€ APIλ₯Ό λ³΄κ³ μ λ κ²λ¨Ήμ§ λ§μ. μ λλ‘ μΌμΌν λ€ μΈμ°λ € νμ§λ§κ³ String μ΄λ List ν΄λμ€μ λ©μλ μ²λΌ νμν λλ§λ€ μ°Ύμμ μ¬μ©νλ©΄ λλ€.
μ΄ νμ€ APIλ€μ μ¬μ€μ μκ³ λ³΄λ©΄ λ³κ±° μλ λλ€μ΄λ€. λ¨μ΄λ§ κ·Έλ΄μΈνκ² ν¨μν μΈν°νμ΄μ€ API λΌκ³ νμ§, κ·Έλ₯ λλ€μμ μ΄μ©ν΄ νλ‘κ·Έλλ°ν λ μμ£Ό μ¬μ©λ κ² κ°μ ν¨μ λͺ¨μ, ννλ₯Ό 미리 λ§λ€μ΄λκ³ μΈν°νμ΄μ€ μ΄λ¦λ§ μμ£Ό κ·Έλ΄μΈνκ² μ λ¬Έκ° μ²λΌ μ§μ΄λμ κ² λΏμ΄λ€.
μλ₯Όλ€μ΄ λ°λ‘ λ€μμ λ°°μΈ Consumer μΈν°νμ΄μ€ APIλ κ·Έλ₯ λκ° λλ¨ν μλ£ν λ§λ₯ 보μ΄κ² μ§λ§, κ·Έλ₯ 맀κ°λ³μλ§ λ°κ³ λ°νκ°μ΄ μλ ννμ ν¨μλ₯Ό νννκΈ° μν΄ 'μλΉ' λΌλ λ¨μ΄λ₯Ό κ³¨λΌ λ£μ κ² λΏμ΄λ€. κ·Έλ¦¬κ³ μλ°μλ νμ μ΄ μ¬λ¬κ°μ΄λ κ° νμ λ€μ λ§μΆ° Consumer λ₯Ό μ¬λ¬κ°λ‘ ꡬμ±ν κ²μ΄λ€.
μ΄ μ μ μ μν΄μ μΈν°νμ΄μ€ νμ€ APIλ₯Ό μ΄ν΄λ³΄λ©΄ 곡λΆμ λν κ±°λΆκ°μ΄λ μλ°κ° μμ΄ μ€λ¬΄μ€νκ² νμ΅ ν μ μμ κ²μ΄λ€.
Consumer μΈν°νμ΄μ€
- μν : 맀κ°κ°λ§ λ°κ³ μ²λ¦¬ (리ν΄κ° X)
- μ€ν λ©μλ :
accept() - μλΉ(consume)νλ€λ λ§μ μ¬μ©λ§ ν λΏ λ¦¬ν΄κ°μ΄ μλ€λ λ»μΌλ‘ 보면 λλ€.
μΈν°νμ΄μ€ νν | λ΄μ© |
Consumer<T> | T ννμ μΈμκ°μ λ°λλ€ |
BiConsumer<T, U> | T, U ννμ μΈμκ° 2κ°λ₯Ό λ°λλ€ |
XXXConsumer | XXX ννμ μΈμκ°μ λ°λλ€ |
ObjXXXConsumer<T> | T, XXX ννμ μΈμκ° 2κ°λ₯Ό λ°λλ€ |
BiConsumerμ Bi λ»μ, λΌν΄μ΄μμ νμλ μμ΄ μ λμ¬ bi- λ‘ "λ"μ μλ―Ένλ€. λ°λΌμ 맀κ°λ³μλ₯Ό λκ° λ°λλ€λ‘ μ΄ν΄νλ©° μκΈ°νλ©΄ λλ€.
Consumer μ’ λ₯
μΈν°νμ΄μ€ λͺ | μΆμ λ©μλ | μ€λͺ |
Consumer<T> | void accept(T t) | κ°μ²΄ Tλ₯Ό λ°μ μλΉ |
BiConsumer<T, U> | void accept(T t, U u) | κ°μ²΄ Tμ Uλ₯Ό λ°μ μλΉ |
DoubleConsumer | void accept(double value) | double κ°μ λ°μ μλΉ |
IntConsumer | void accept(int value) | int κ°μ λ°μ μλΉ |
LongConsumer | void accept(long value) | long κ°μ λ°μ μλΉ |
ObjDoubleConsumer<T> | void accept(T t, double value) | κ°μ²΄ Tμ double κ°μ λ°μ μλΉ |
ObjIntConsumer<T> | void accept(T t, int value) | κ°μ²΄ Tμ int κ°μ λ°μ μλΉ |
ObjLongConsumer<T> | void accept(T t, long value) | κ°μ²΄ Tμ long κ°μ λ°μ μλΉ |
public static void main(String[] args) {
// κ°μ²΄ Tλ₯Ό λ°μ μΆλ ₯νλ ν¨μ μ μ
Consumer<String> c1 = t -> System.out.println("μ
λ ₯κ° : "+ t);
c1.accept("νκΈΈλ");
// κ°μ²΄ Tμ Uλ₯Ό λ°μ μΆλ ₯νλ ν¨μ μ μ
BiConsumer<String, Integer> c2 = (a, b) -> System.out.println("μ
λ ₯κ°1 : "+ a+ ", μ
λ ₯κ°2 : "+ b);
c2.accept("νκΈΈλ", 100);
// int κ°μ λ°μ μΆλ ₯νλ ν¨μ μ μ
IntConsumer c3 = a -> System.out.println("μ
λ ₯κ° : "+ a);
c3.accept(100);
// double κ°μ λ°μ μΆλ ₯νλ ν¨μ μ μ
DoubleConsumer c4 = a -> System.out.println("μ
λ ₯κ° : "+ a);
c4.accept(100.01);
// long κ°μ λ°μ μΆλ ₯νλ ν¨μ μ μ
LongConsumer c5 = a -> System.out.println("μ
λ ₯κ° : "+ a);
c5.accept(2100000000);
}
λ§μΌ 3κ° μ΄μμ 맀κ°λ³μλ₯Ό λ°λ λλ€ ν¨μλ₯Ό λ§λ€κ³ μΆλ€λ©΄, μ§μ μΈν°νμ΄μ€λ₯Ό μ μν΄μ μ¬μ©νμ¬μΌ νλ€.
interface TripleConsumer<T, U, K> {
void accept(T t, U u, K k);
}
public class Main {
public static void main(String[] args) {
TripleConsumer<String, Double, Integer> c1 = (t, u, k) -> {
System.out.printf("%s + %f + %d", t, u, k);
};
c1.accept("μλ
", 101.23, 999);
}
}
Supplier μΈν°νμ΄μ€
- μν : μ무 맀κ°κ° μμ΄ λ¦¬ν΄κ°λ§μ λ°ν
- μ€ν λ©μλ :
getXXX() - μμ°(supply)νλ€λ λ§μ λ°μ΄ν°λ₯Ό λ°ν(곡κΈ) νλ€λ λ»μΌλ‘ 보면 λλ€.
μΈν°νμ΄μ€ νν | λ΄μ© |
Supplier<T> | Tν λ°ν |
XXXSupplier | XXXν λ°ν |
Supplier μ’ λ₯
μΈν°νμ΄μ€ λͺ | μΆμ λ©μλ | μ€λͺ |
Supplier<T> | T get() | T κ°μ²΄λ₯Ό λ¦¬ν΄ |
BooleanSupplier | Boolean getAsBoolean() | Boolean κ°μ λ¦¬ν΄ |
DoubleSupplier | double getAsDouble() | double κ°μ λ¦¬ν΄ |
IntSupplier | int getAsInt() | int κ°μ λ¦¬ν΄ |
LongSupplier | long getAsLong() | long κ°μ λ¦¬ν΄ |
public static void main(String[] args) {
// T κ°μ²΄λ₯Ό 리ν΄νλ ν¨μ μ μ
Supplier<Object> supplier = () -> new Object();
System.out.println(supplier.get());
// Boolean κ°μ 리ν΄νλ ν¨μ μ μ
BooleanSupplier booleanSup = () -> true;
System.out.println(booleanSup.getAsBoolean());
// int κ°μ 리ν΄νλ ν¨μ μ μ
IntSupplier intSup = () -> {
int num = (int) (Math.random() * 6) + 1;
return num;
};
System.out.println("μ£Όμ¬μ λλ€ μ«μ : " + intSup.getAsInt());
// double κ°μ 리ν΄νλ ν¨μ μ μ
DoubleSupplier doubleSup = () -> 1.0;
System.out.println(doubleSup.getAsDouble());
// long κ°μ 리ν΄νλ ν¨μ μ μ
LongSupplier longSup = () -> 1L;
System.out.println(longSup.getAsLong());
}
Function μΈν°νμ΄μ€
- μν : 맀ν(νμ λ³ν)νκΈ°
- μ€ν λ©μλ :
applyXXX() - 맀ν νλ€λ λ§μ, μλ₯Όλ€μ΄ μ¬λ¬ λ°μ΄ν° νλͺ©λ€μ΄ λ€μ κ°μ²΄μμ νΉμ νμ κ°μ μΆμΆνκ±°λ νΉμ λ€λ₯Έ νμ μΌλ‘ λ³ννλ μμ μ μ¬μ©νλ€κ³ 보면 λλ€.
μΈν°νμ΄μ€ νν | λ΄μ© |
Function<T, R> | T λ°μμ R λ¦¬ν΄ |
BiFunction<T, U, R> | T, U λ°μμ R λ¦¬ν΄ |
XXXFunction<T> | XXX λ°μμ T λ¦¬ν΄ |
XXXtoYYYFunction | XXX λ°μμ YYY λ¦¬ν΄ |
toXXXFunction<T> | T λ°μμ XXX λ¦¬ν΄ |
toXXXBiFunction<T, U> | T, U λ°μμ XXX λ¦¬ν΄ |
Tμ Uλ 맀κ°λ³μ νμ μ΄κ³ Rμ 리ν΄(return) νμ κΈ°νΈνκ³ λ³΄λ©΄ λλ€.
Function μ’ λ₯
μΈν°νμ΄μ€ λͺ | μΆμ λ©μλ | μ€λͺ |
Function<T, R> | R apply(T t) | κ°μ²΄ Tλ₯Ό κ°μ²΄ Rλ‘ λ§€ν |
BiFunction<T, U, R> | R apply(T t, U u) | κ°μ²΄ Tμ Uλ₯Ό κ°μ²΄ Rλ‘ λ§€ν |
DoubleFunction<R> | R apply(double value) | doubleμ κ°μ²΄ Rλ‘ λ§€ν |
IntFunction<R> | R apply(int value) | intλ₯Ό κ°μ²΄ Rλ‘ λ§€ν |
IntToDoubleFunction | double applyAsDouble(int value) | intλ₯Ό doubleλ‘ λ§€ν |
IntToLongFunction | long applyAsLong(int value) | intλ₯Ό longμΌλ‘ 맀ν |
LongToDoubleFunction | double applyAsDouble(long value) | longμ doubleλ‘ λ§€ν |
LongToIntFunction | int applyAsInt(long value) | longμ intλ‘ λ§€ν |
ToDoubleBiFunction<T, U> | double applyAsDouble(T t, U u) | κ°μ²΄ Tμ Uλ₯Ό doubleλ‘ λ§€ν |
ToDoubleFunction<T> | double applyAsDouble(T value) | κ°μ²΄ Tλ₯Ό doubleλ‘ λ§€ν |
ToIntBiFunction<T, U> | int applyAsInt(T t, U u) | κ°μ²΄ Tμ Uλ₯Ό intλ‘ λ§€ν |
ToIntFunction<T> | int applyAsInt(T t) | κ°μ²΄ Tλ₯Ό intλ‘ λ§€ν |
ToLongBiFunction<T, U> | long applyAsLong(T t, U u) | κ°μ²΄ Tμ Uλ₯Ό longμΌλ‘ 맀ν |
ToLongFunction<T> | long applyAsLong(T t) | κ°μ²΄ Tλ₯Ό longμΌλ‘ 맀ν |
public static void main(String[] args) {
// intνμ StringμΌλ‘ νμ
λ³ννλ ν¨μ μ μ
Function<Integer, String> intToStr = t -> String.valueOf(t);
String str = intToStr.apply(100);
// Stringμ intνμΌλ‘ νμ
λ³ννλ ν¨μ μ μ
ToIntFunction<String> strToInt = t -> Integer.parseInt(t);
int num = strToInt.applyAsInt("100");
// intνμ doubleνμΌλ‘ νμ
λ³ννλ ν¨μ μ μ
IntToDoubleFunction intToDouble = t -> (double) t;
double d = intToDouble.applyAsDouble(100);
}
class Student {
private String name;
int korean_score;
int english_score;
int math_score;
Student(String name, int korean_score, int english_score, int math_score) {
this.name = name;
this.korean_score = korean_score;
this.english_score = english_score;
this.math_score = math_score;
}
String getName() {
return name;
}
}
public static void main(String[] args) {
List<Student> list = List.of(
new Student("νκΈΈλ", 99, 12, 45),
new Student("μκΊ½μ ", 76, 20, 8),
new Student("κ³ λ΄λ", 36, 50, 33),
new Student("κΉμ’μ§", 77, 89, 91)
);
// κ° νμμ μ΄λ¦ κ°μ Έμ€λ ν¨μ μ μ (맀κ°νμ
: Student κ°μ²΄, 리ν΄νμ
: Stringν)
Function<Student, String> getNameFunc = (s) -> s.getName();
// κ° νμμ κ΅κ³Όλͺ© νκ· κ³μ°νκ³ κ°μ Έμ€λ ν¨μ μ μ (맀κ°νμ
: Student κ°μ²΄, 리ν΄νμ
: intν)
ToDoubleFunction<Student> getScoreFunc = (s) -> {
int sum = s.korean_score + s.english_score + s.korean_score;
double avg = sum / 3.0;
return avg;
};
for (Student student : list) {
String name = getNameFunc.apply(student);
double avg = getScoreFunc.applyAsDouble(student);
System.out.printf("%s νκ· μ μ : %f\n", name, avg);
}
}
Operator μΈν°νμ΄μ€
- μν : 맀κ°κ° κ³μ°ν΄μ λμΌν νμ μΌλ‘ 리ν΄νκΈ°
- μ€ν λ©μλ :
applyXXX() - Functionκ³Ό λΉμ·νμ§λ§, 맀κ°κ°μ 리ν΄κ°μΌλ‘ 맀ν(νμ λ³ν)νλ μν 보λ€λ 맀κ°κ°μ μ΄μ©ν΄μ μ°μ°μ μνν ν λμΌν νμ μΌλ‘ 리ν΄κ°μ μ 곡νλ μν μ μ΄μ μ΄ κ°μλ€.
μΈν°νμ΄μ€ νν | λ΄μ© |
UnaryOprater<T> | Tνμ μ°μ°νκ³ λ¦¬ν΄ |
BinaryOperator<T> | Tνμ μ°μ°νκ³ λ¦¬ν΄ |
XXXUnaryOperator | XXX νμ 1κ° μ°μ° |
XXXBinaryOperator | XXX νμ 2κ° μ°μ° |
Unaryλ λ¨ν(μ°μ°μ΄ 1κ°) μ΄κ³ , Binaryλ μ΄ν(μ°μ°μ΄ 2κ°) μ΄λΌλ λ»μ΄λ€.
Operator μ’ λ₯
μΈν°νμ΄μ€ λͺ | μΆμ λ©μλ | μ€λͺ |
UnaryOperator<T> | T apply(T t) Function<T, R>μ νμ μΈν°νμ΄μ€ |
Tλ₯Ό μ°μ°ν ν R λ¦¬ν΄ |
BinaryOperator<T> | T apply(T t, T u) BiFunction<T, U, R>μ νμ μΈν°νμ΄μ€ |
Tμ Uλ₯Ό μ°μ° ν R λ¦¬ν΄ |
DoubleUnaryOperator | double applyAsDouble(double) | ν κ°μ doubleμ μ°μ° |
DoubleBinaryOperator | double applyAsDouble(double, double) | λ κ°μ doubleμ μ°μ° |
IntUnaryOperator | int applyAsInt(int) | ν κ°μ intλ₯Ό μ°μ° |
IntBinaryOperator | int applyAsInt(int, int) | λ κ°μ intλ₯Ό μ°μ° |
LongUnarayOperator | long applyAsLong(long) | ν κ°μ longμ μ°μ° |
LongBinaryOperator | long applyAsLong(long, long) | λ κ°μ longμ μ°μ° |
class Operation {
static int calculate(int[] arr, IntBinaryOperator o) {
int result = arr[0];
for (int i = 1; i < arr.length; i++) {
result = o.applyAsInt(result, arr[i]);
}
return result;
}
}
public static void main(String[] args) {
int[] numbers = {3, 1, 7, 6, 5};
// λ°°μ΄ μμμ λͺ¨λ ν© κ΅¬νκΈ°
int sum = Operation.calculate(numbers, (x, y) -> {
return x + y;
});
System.out.println(sum);
// λ°°μ΄ μμμ λͺ¨λ κ³± ꡬνκΈ°
int mul = Operation.calculate(numbers, (x, y) -> {
return x * y;
});
System.out.println(mul);
// λ°°μ΄ μμμ€ κ°μ₯ ν° μ ꡬνκΈ°
int max = Operation.calculate(numbers, (x, y) -> {
int tmp;
if(x > y)
tmp = x;
else
tmp = y;
return tmp;
});
System.out.println(max);
// λ°°μ΄ μμμ€ κ°μ₯ μμ μ ꡬνκΈ°
int min = Operation.calculate(numbers, (x, y) -> {
int tmp;
if(x < y)
tmp = x;
else
tmp = y;
return tmp;
});
System.out.println(min);
}
Predicate μΈν°νμ΄μ€
- μν : 맀κ°κ°μ λ°κ³ true / false 리ν΄
- μ€ν λ©μλ :
test() - 맀κ°κ°μ λ°μ μ°Έ/κ±°μ§μ λ¨μ (predicate) νλ€κ³ μκ°νλ©΄ λλ€.
μΈν°νμ΄μ€ νν | λ΄μ© |
Predicate<T> | T λ₯Ό λ°μ boolean λ¦¬ν΄ |
BiPredicate<T, U> | T, Uλ₯Ό λ°μ boolean λ¦¬ν΄ |
XXXPredicate | XXXλ₯Ό λ°μ boolean λ¦¬ν΄ |
Predicate μ’ λ₯
μΈν°νμ΄μ€ λͺ | μΆμ λ©μλ | μ€λͺ |
Predicate<T> | Boolean test(T t) | κ°μ²΄ Tλ₯Ό μ‘°μ¬ |
BiPredicate<T, U> | Boolean test(T t, U u) | κ°μ²΄ Tμ Uλ₯Ό λΉκ΅ μ‘°μ¬ |
DoublePredicate | Boolean test(double value) | double κ°μ μ‘°μ¬ |
IntPredicate | Boolean test(int value) | int κ°μ μ‘°μ¬ |
LongPredicate | Boolean test(long value) | long κ°μ μ‘°μ¬ |
class Student {
String name;
int score;
public Student(String name, int score) {
this.name = name;
this.score = score;
}
}
public static void main(String[] args) {
List<Student> list = List.of(
new Student("νκΈΈλ", 99),
new Student("μκΊ½μ ", 76),
new Student("κ³ λ΄λ", 36),
new Student("κΉμ’μ§", 77)
);
// intν 맀κ°κ°μ λ°μ νΉμ μ μ μ΄μμ΄λ©΄ true μλλ©΄ false λ₯Ό λ°ννλ ν¨μ μ μ
IntPredicate scoring = (t) -> {
return t >= 60;
};
for (Student student : list) {
String name = student.name;
int score = student.score;
// ν¨μ μ€ννμ¬ μ°Έ / κ±°μ§ κ° μ»κΈ°
boolean pass = scoring.test(score);
if(pass) {
System.out.println(name + "λ " + score + "μ μ κ΅μ΄ ν©κ²©μ
λλ€.");
} else {
System.out.println(name + "λ " + score + "μ μ κ΅μ΄ λΆν©κ²©μ
λλ€.");
}
}
}
ν¨μν μΈν°νμ΄μ€ λν΄νΈ λ©μλ
Function ν©μ±
μ€κ³ λ±νμλ μν μκ°μ f(x) ν¨μμ g(x) ν¨μκ° μμ λ, μ΄ λ ν¨μλ₯Ό ν©μ±νμ¬ f(g(x)) λΌλ ν©μ± ν¨μλ₯Ό λ€λ€λ³Έ κΈ°μ΅μ΄ μ΄λ ΄νμ΄λλ§ μμ κ²μ΄λ€. f(g(x)) λ g(x)μ κ²°κ³Όλ₯Ό λ€μ f(x) ν¨μμ μΈμλ‘ λ£μ΄μ€ κ²μ΄λ€.
μ΄μ²λΌ λ λλ€ ν¨μλ₯Ό μ°κ²°νμ¬ ν©μ±μν¬ μ μλλ°, μ΄ ν©μ± μν€λ λ©μλλ₯Ό μλ°μμ ν¨μν μΈν°νμ΄μ€μ λν΄νΈ λ©μλλ‘μ μ 곡νλ€.
μΈν°νμ΄μ€ λ©μλ | μ€λͺ |
default <V> Function <T, V> andThen (Function <? super R, ? extends V> after); | f(g(x)) ν©μ±ν¨μ |
default <V> Function <V, R> compose(Function <? super V, ? extends T> before); | g(f(x)) ν©μ±ν¨μ (andThenμ λ°λ) |
static <T> Function<T, T> identity(); | νλ±ν¨μ (μκΈ° μμ λ°ν) |
ν©μ± ν¨μλ Function μΈν°νμ΄μ€ λΏλ§ μλλΌ Consumer μ΄λ Operator μΈν°νμ΄μ€λ μ‘΄μ¬νλ€.
λλ€ ν©μ± μ¬μ© μμ 1
κ°λ¨ν μν ν¨μλ₯Ό μ½λλ‘ ννν΄ λ³΄μλ€. μ«μλ₯Ό λ°μΌλ©΄ 4λ₯Ό λΉΌλ ν¨μ f(x) μ μ«μλ₯Ό λ°μΌλ©΄ λλ°° κ³±ν΄μ£Όλ ν¨μ g(x) λ₯Ό λλ€ννμμΌλ‘ μ μΈνμλ€. κ·Έλ¦¬κ³ μ΄ λμ andThen κ³Ό composeλ‘ ν©μ±νμ¬ μ¬μ©νλ©΄ λ€μκ³Ό κ°λ€.
public static void main(String[] args) {
Function<Integer, Integer> f = num -> (num - 4); // f(x)
Function<Integer, Integer> g = num -> (num * 2); // g(x)
// f(g(x))
int a = f.andThen(g).apply(10);
System.out.println(a); // (10 - 4) * 2 = 12
// g(f(x)) - andThenμ λ°λλ‘ ν΄μνλ©΄ λλ€
int b = f.compose(g).apply(10);
System.out.println(b); // 10 * 2 - 4 = 16
}
andThen κ³Ό compose μ μ°¨μ΄λ κ°λ¨νλ€.
f.andThen(g) λ₯Ό μννλ©΄ f ν¨μλ₯Ό μ€νν κ²°κ³Ό κ°μ λ€μ g ν¨μμ μΈμλ‘ μ λ¬νμ¬ κ²°κ³Όλ₯Ό μ»κ² λλ€. λ¨, f ν¨μμ λ¦¬ν΄ νμ
μ΄ g ν¨μμ 맀κ°λ³μ νμ
κ³Ό νΈνλμ΄μΌ νλ€.
f.compose(g) λ₯Ό μννλ©΄ g ν¨μλ₯Ό μ€νν κ²°κ³Ό κ°μ λ€μ f ν¨μμ μΈμλ‘ μ λ¬νμ¬ κ²°κ³Όλ₯Ό μ»κ² λλ€. μ¦, andThenμ λ°λ λ²μ μ΄λΌκ³ 보면 λλ€.
μ¦,x.andThen(y)λy.compose(x)μ λμΌνλ€κ³ 보면 λλ€.
λλ€ ν©μ± μ¬μ© μμ 2
λ€μ Member ν΄λμ€μ Address ν΄λμ€κ° μκ³ , Member ν΄λμ€μμ Address κ°μ²΄λ₯Ό ν©μ±(composition) νμ¬ κ°μ§κ³ μλ€. μ΄ κ°μ²΄λΌλ¦¬ ν©μ±λ κ΄κ³λ₯Ό ν©μ± ν¨μλ₯Ό ν΅ν΄ λ©€λ²μ λμ μ£Όμκ°μ λΆλ¬μ€λ κ°λ¨ν μμ μ΄λ€.
class Member {
private String name;
private Address address; // Address κ°μ²΄λ₯Ό ν©μ±(composition)
public Member(String name, Address address) {
this.name = name;
this.address = address;
}
public String getName() { return name; }
public Address getAddress() { return address; }
}
class Address {
private String country;
private String city;
public Address(String country, String city) {
this.country = country;
this.city = city;
}
public String getCountry() { return country; }
public String getCity() { return city; }
}
public static void main(String[] args) {
Member member = new Member("νκΈΈλ", new Address("μ‘°μ ", "νμ"));
// Member 맀κ°νμ
κ³Ό Address 리ν΄νμ
Function<Member, Address> f = x -> x.getAddress(); // Address κ°μ²΄λ₯Ό μ»κΈ°
// Address 맀κ°νμ
κ³Ό String 리ν΄νμ
Function<Address, String> g = x -> x.getCity(); // city λ¬Έμμ΄ μ»κΈ°
// f(g(x))
Function<Member, String> fg = f.andThen(g);
String city = fg.apply(member); // Address κ°μ²΄λ₯Ό μ»κ³ (f μ€ν), Address κ°μ²΄μμ city νλκ°μ μ»κΈ°(g μ€ν)
System.out.println("κ±°μ£Ό λμ : " + city);
fg = g.compose(f);
city = fg.apply(member);
System.out.println("κ±°μ£Ό λμ : " + city);
}
Predicate κ²°ν©
Predicate ν¨μν μΈν°νμ΄μ€λ μ°Έ / κ±°μ§ κ°μ 리ν΄νλ ν¨μλ₯Ό λ€λ£¬λ€. μ¦, true / false 쑰건μμ λνμ¬ μ΄λ€μ κ²°ν©νμ¬ and μ°μ°, or μ°μ°μ ννλ€κ³ 보면 λλ€.
μΈν°νμ΄μ€ λ©μλ | μ€λͺ |
default Predicate<T> and (Predicate<? super T> other) | and μ°μ° |
default Predicate<T> or (Predicate<? super T> other) | or μ°μ° |
default Predicate<T> negate() | μ λΆμ |
static <T> Predicate<T> isEqual(Object targetRef) | κ°μ²΄ λΉκ΅ |
λλ€ κ²°ν© μ¬μ© μμ
쑰건문μ ꡬμ±ν λ if(x > 10 && x < 20) μ΄λ°μμΌλ‘ 쑰건 μ°μ°μλ₯Ό μ΄μ©ν΄ λ²μλ₯Ό ꡬμ±ν΄λ³Έμ μ΄ μμ κ²μ΄λ€. μ΄κ²μ λλ€ ν¨μλ‘ ννν κ²μ΄λΌκ³ 보면 λλ€.
public static void main(String[] args) {
Predicate<Integer> greater = x -> x > 10;
Predicate<Integer> less = x -> x < 20;
// x > 10 && x < 20
Predicate<Integer> between = greater.and(less);
System.out.println(between.test(15)); // true
// x > 10 || x < 20
Predicate<Integer> all = greater.or(less);
System.out.println(all.test(5)); // true
// x <= 10
Predicate<Integer> negate = greater.negate();
System.out.println(negate.test(50)); // false
}
isEqual() μ μ μΈν°νμ΄μ€ λ©μλλ μ
λ ₯κ°μΌλ‘ λ°μ κ°μ²΄μ κ°μμ§ νλ¨ν΄μ£Όλ λ©μλ μ΄λ€. κ·Έλ₯ equals() λ₯Ό λλ€ ν¨μλ‘ ννν κ²μ΄λΌκ³ 보면 λλ€.
public static void main(String[] args) {
// ν¨μμ μΈμλ‘ λ€μ΄μ¨ λ¬Έμμ΄μ΄ "νκΈΈλ" μΈμ§ νλ³ν΄μ£Όλ ν¨μ
Predicate<String> checkMyName = Predicate.isEqual("νκΈΈλ");
System.out.println(checkMyName.test("μκΊ½μ ")); // false
System.out.println(checkMyName.test("νκΈΈλ")); // true
}
μλ° μ»¬λ μ μ ν¨μν μΈν°νμ΄μ€
λ§μ§λ§μΌλ‘ μλ°μ 컬λ μ νλ μμν¬μ ν¨μν μΈν°νμ΄μ€μ ν¨κ» μ¬μ©ν μ μλ λ©μλλ λ³λλ‘ μ§μνλ€.
μΈν°νμ΄μ€ | λ©μλ | μ€λͺ |
Collection | boolean removeIf(Predicate<E> filter); | 쑰건μ λ§λ μ리먼νΈλ₯Ό μμ |
List | void replaceAll(UnaryOperator<E> operator); | λͺ¨λ μ리먼νΈμ operatorλ₯Ό μ μ©νμ¬ λ체(replace) |
Iterable | void forEach(Consumer<T> action); | λͺ¨λ μ리먼νΈμ action μν |
μΈν°νμ΄μ€ | λ©μλ | μ€λͺ |
Map | V compute(K key, BiFunction<K, V, V> f); | μ§μ λ ν€μ ν΄λΉνλ κ°μ fλ₯Ό μν |
Map | V computeIfAbsent(K key, Function<K, V> f); | μ§μ λ ν€κ° μμΌλ©΄ f μνν μΆκ° |
Map | V cumputeIfPresent(K key, BiFunction<K, V, V> f) | μ§μ λ ν€κ° μμ λ, f μν |
Map | V merge(K key, V value, BiFunction<V, V, V> f); | λͺ¨λ μ리먼νΈμ Merge μμ μν, ν€μ ν΄λΉνλ κ°μ΄ μμΌλ©΄ f μνν΄μ λ³ν©ν ν λΉ |
Map | void forEach(BiConsumer<K, V> action); | λͺ¨λ μ리먼νΈμ action μν |
Map | void replaceAll(BiFunction<K, V, V> f); | λͺ¨λ μ리먼νΈμ f μνν λ체 |
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
// κ° μμμ 10μ κ³±ν¨
list.replaceAll( (x) -> x * 10 );
// 리μ€νΈλ Iteratbleμ μμνλκΉ μ¬μ©μ΄ κ°λ₯
list.forEach( (x) -> System.out.println(x) );
}
ν¨μν μΈν°νμ΄μ€ API μ¬μ© μ 리ν
보λ€μνΌ ν¨μν μΈν°νμ΄μ€ μ’ λ₯λ κ²°μ½ μ μκ² μλλΌ νλνλ κΈ°μ΅νκΈ° μ 맀νκΈ°λ νκ³ , μΈμ μ΄λλ μΈν°νμ΄μ€ νμ μ κ³¨λΌ μ¬μ©ν μ§ λ°λ‘ λ μ¬λ¦¬κΈ°λ νλ€λ€. κ·Έλμ νλμ λ€μ΄μ¬ μ μκ² μ μ 리λ λμμ κ°μ Έμ 보μλ€.
μΌμͺ½ μΈλ‘ λΆλΆμ 맀κ°λ³μ νμ μ λνλ΄λ κ²μ΄κ³ , κ° νμ μμͺ½ λΆλΆμ ν¨μ λ°ν νμ μ λνλ΄λ κ²μ΄λ€. λ§μΌ double ν 맀κ°λ³μλ₯Ό λ°μ void λ‘ ννλ ν¨μν μΈν°νμ΄μ€κ° 무μμΈμ§ μ°ΎμΌλ €λ©΄, μΌμͺ½μμ (double) → μ μ°Ύκ³ ν μλ¨μ → void λ₯Ό 맀μΉν΄λ³΄λ©΄ λ°λ‘ DoubleConsumer μΈν°νμ΄μ€λ₯Ό μ¬μ©νλ€λ κ²μ μ μ μκ² λλ€.
# μ°Έκ³ μλ£
https://hbase.tistory.com/78
https://palpit.tistory.com/673
http://blog.orfjackal.net/2014/07/java-8-functional-interface-naming-guide.html