✔함수형 인터페이스
- 함수형 인터페이스(람다식 인터페이스) : 1개의 추상 메서드를 갖는 인터페이스.
- 제약 조건 : 오직 하나의 추상 메서드만 정의되어 있어야 한다.
- static 메서드와 default 메서드의 개수에는 제약이 없다.
- 람다식 표현시 데이터 추론이 가능하여 매개변수 데이터 타입 생략 가능.
interface Test{
void funcInterface();
static void staticFunc(){}
default void defaultFunc(){}
}
일급 객체
: 다른 객체들에 일반적으로 적용 가능한 연산을 모두 지원하는 객체
- 변수에 할당(assignment)할 수 있다.
- 다른 함수를 인자(argument)로 전달 받는다.
- 다른 함수의 결과로서 리턴될 수 있다.
- 일급 객체를 쓸 수 있는 언어 : 함수형 프로그래밍 언어
- 자바는 일급 객체 사용 불가능 : 람다식으로 함수를 넘기는 것처럼 보이지만 실상은 객체를 넘기는 것.
1. 자바에서 제공하는 함수형 인터페이스
- Runnable - void run() : 매개변수 없음. 반환값 없음.
Runnable helloWorld = () -> System.out.println("Hello World!");
- Supplier< T > - T get() : 매개변수 없음. 반환 값 있음.
Supplier<String> supplyFood = () -> "스테이크 생성";
- Consumer< T > - void accept(T t) : 매개변수 1개. 반환 값 없음.
Consumer<String> consumeFood = (food) -> System.out.println(food + "를 먹었습니다.");
- Function< T, R > - R apply(T t) : 매개변수 1개. 반환 값 있음.
Function<Integer, Integer> ourSelfSum = (a) -> a + a;
- Predicate< T > - boolean test(T t) : 매개변수 1개. 반환 값 있음(boolean, 조건식을 표현하는데 사용)
Predicate<Integer> lessThanTen = (number) -> number < 10;
- BiConsumer<T, U> - void accept(T t, U u) : 매개변수 2개. 반환 값 없음
BiConsumer<String, Integer> consumeFood2 = (food, quantity) -> System.out.println(food + "를 " + quantity + "개 먹었습니다.");
- BiFunction<T, U, R> - R apply(T t, U u) : 매개변수 2개. 반환 값 있음
BiFunction<Integer, Integer, Integer> multiply = (x, y) -> x * y;
- BiPredicate<T, U> - boolean test(T t, U u) : 매개변수 2개. 반환 값 있음(boolean, 조건식을 표현하는데 사용)
BiPredicate<Integer, Integer> lessThan = (number, base) -> number < base;
- UnaryOperator< T > - T apply(T t) : 매개변수 1개. 반환 값 있음. (매개변수, 반환 값 타입 같음)
UnaryOperator<Integer> ourSelfSum = (a) -> a + a;
- BinaryOperator< T > - T apply(T t1, T t2) : 매개변수 2개. 반환 값 있음. (매개변수, 반환 값 타입 같음)
BinaryOperator<Integer> multiply = (x, y) -> x * y;
2. Collection에서의 함수형 인터페이스
- Collection에는 함수형 인터페이스를 매개변수로 가지는 메서드가 있다.
- 람다식으로 구성하여 원하는 형식으로 사용 가능.
- List의 함수형 인터페이스 활용
- void forEach(Consumer< T > action) : 모든 요소에 작업 action을 수행.
list.forEach(name -> System.out.print(name + ", "));
- boolean removeIf(Predicate< E > filter) : 조건에 맞는 요소를 삭제
list.removeIf(name -> name.contains("이") || name.contains("박"));
- void replaceAll(UnaryOperator< E > operator) : 모든 요소를 변환하여 대체
list.replaceAll(name -> name + " 교육생");
- Map의 함수형 인터페이스 활용
- void forEach(BiConsumer<K, V> action) : 모든 요소에 작업 action을 수행
map.forEach((key, value) -> System.out.print(key + ":" + value + ", "));
- void replaceAll(BiFunction<K, V, V> f) : 모든 요소에 치환작업 f를 수행
map.replaceAll((key, value) -> value + 1);
- V compute(K key, BiFunction<K, V, V> f) : 지정된 키의 값에 작업 f를 수행
int age = map.compute("김싸피", (key, value) -> value + 10);
- V computeIfAbsent(K key, Function<K, V> f) : 키가 없으면 작업 f 수행 후 추가
age = map.computeIfAbsent("홍길동", (key) -> 1);
- V computeIfPresent(K key, BiFunction<K, V, V> f) : 지정된 키가 있을 때 작업 f를 수행
age = map.computeIfPresent("홍길동", (key, value) -> value + 20);
- V merge(K key, V value, BiFunction<V, V, V> f) : 모든 요소에 병합작업 f를 수행
age = map.merge("홍길동", 10, (original, newValue) -> original + newValue);
3. 다양한 함수형 인터페이스
- Coposition(합성, 결합) - Function : apply()
Function<String, Integer> f = (s) -> Integer.parseInt(s, 16);
Function<Integer, String> g = (i) -> Integer.toBinaryString(i);
- andThen : f 수행 후 g 수행
Function<String, String> h = f.andThen(g);
- compose : g 수행 후 f 수행
Function<Integer, Integer> i = f.compose(g);
- identity : 항등 함수 (거의 사용되지 않는다.)
Function<String, String> j = Function.identity();
- Predicate Composition - Predicate : test()
Predicate<Integer> overZero = (number) -> 0 <= number;
Predicate<Integer> lessThanTen = (number) -> number < 10;
Predicate<Integer> even = (number) -> number % 2 == 0;
- and : 둘 모두 참이면 참.
overZero.and(lessThanTen).test(6);
- or : 둘 중 하나가 참이면 참.
lessThanTen.or(even).test(12);
- negate(부정하다) : 거짓이면 참.
lessThanTen.negate().test(20)
- isEqual : 둘이 같다면 참.
Predicate.isEqual(name1).test(name2);
- 기본형 데이터 함수형 인터페이스 : A, B는 기본형 부분.
- A To B Function :
DoubleToIntFunction f1 = (doubleValue) -> (int) doubleValue;
- To B Function :
ToIntFunction<Double> f2 = (doubleValue) -> doubleValue.intValue();
- A Function :
DoubleFunction<Integer> f3 = (doubleValue) -> (int) doubleValue;
- Obj A Consumer :
ObjIntConsumer<Double> f4 = (doubleValue, intValue) -> System.out.println(doubleValue * 10 + ", " + intValue * 10);
4. 메서드 참조
- 메서드 참조 : 람다식이 하나의 메서드만 호출하는 경우 메서드 참조 사용 가능.
- 람다식을 더욱 간결하게 표현하는 방법
클래스이름::메소드이름
or 참조변수이름::메소드이름
- (ex) (base, exponent) -> Math.pow(base, exponent);
- (ex) Function<String, Boolean> func = (a) -> obj.equals(a); // 람다 표현식
- Function<String, Boolean> func = obj::equals(a)