일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
- JavaScript
- 반복문
- Programming
- softeer
- 자바의 정석(기초편)
- BFS
- 백준
- Java
- SQL
- Steve Jobs
- 해시
- programmers
- 영어원서
- nextInt
- 티스토리챌린지
- 오블완
- 관계형 데이터베이스
- java.lang 패키지
- Spring
- Java script
- Python
- 소프티어
- StringTokenizer
- MySQL
- Computer Science
- 알고리즘
- thinking differently
- Spring Framework
- 코딩테스트
- 프로그래머스
- Today
- Total
도라에몽 개발자
람다식(Lambda Expression) 본문
- 람다식(Lambda Expression)의 정의
- 함수(메서드)를 간단한 식(expression)으로 표현하는 방법을 의미함.
- 익명 함수(이름 없는 함수; Anonymout function): 반환타입과 이름을 삭제한 형태 - 람다식(Lambda Expression)으로 작성하는 방법
1) 메서드의 이름과 반환타입 제거하고, '->' 표시를 블록({}) 앞에 추가
2) 반환값(return값) 있는 경우, 식이나 값만 적고 return문은 생략 가능하며 ';'표시 붙이지 않음.
3) 매개변수 타입이 추론 가능한 경우, 매개변수 타입 또한 생략 가능함. - 람다식(Lambda Expression) 작성 시 주의사항
- 매개변수가 하나인 경우에는 괄호() 생략 가능하나, 매개변수 타입이 생략될 수 없는 경우에는 괄호() 또한 생략 불가능
- 괄호{} 안의 문장이 하나인 경우 괄호{} 생략 가능하며, 문장 끝에 ; 표시 붙이지 않아도 됨.
- 괄호{} 안의 문장이 return문인 경우에는 괄호{} 생략 불가능하나, 대부분의 return문은 생략 가능하기 때문에 참고만 할 것
int max(int a, int b) {
return a > b ? a : b; // a가 b보다 크면 a이고, 크지 않으면 b로 반환
}
// 위와 같은 코드를 람다식으로 변경하면 아래와 같음.
(int a, int b) -> { // 반환타입과 이름(int max) 삭제
return a > b ? a : b;
}
// 반환값 있는 경우, return문 생략 가능(끝에 ; 표시도 붙이지 않음)
(int a, int b) -> a > b ? a : b
// 매개변수 타입 추론 가능한 경우에는 생략 가능(대부분 가능!)
(a, b) -> a > b ? a : b
cf. 함수 vs 메서드
→ 근본적으로는 동일하며, 함수는 일반적 용어이고 메서드는 객체지향개념 용어라고 할 수 있음.
→ 함수는 클래스에 독립적이나, 메서드는 클래스에 종속적이라는 차이가 있음.
- 람다식(Lambda Expression)의 특징
- 익명 함수가 아닌, '익명 객체'임.
- 객체의 선언 및 생성을 동시에 함.
함수형 인터페이스
- 정의
- 단 하나의 추상 메서드만 선언된 인터페이스(interface)
// 함수형 인터페이스 - MyFunction
interface MyFunction{
public abstract int max(int a, int b);
}
MyFunction f = new MyFunction() { // 익명클래스의 선언 및 객체 생성 동시에 함.
public int max(int a, int b) {
return a > b ? a : b;
}
};
int value = f.max(3,5);
▼ 함수형 인터페이스 활용 예시
(* 함수형 인터페이스의 메서드와 람다식의 매개변수 개수 및 반환타입이 일치해야 함.) ★★★
<함수형 인터페이스의 메서드의 매개변수 개수 및 반환타입>
- ... public abstract int max(int a, int b) : 매개변수는 a, b로 총 2개이며, 반환타입은 int임.
<람다식의 매개변수 개수 및 반환타입>
- ... (a, b) ... : 매개변수는 a, b로 총 2개이며, 반환타입은 int임.
// 함수형 인터페이스 - MyFunction
interface MyFunction{
public abstract int max(int a, int b);
}
// 다음과 같이, 함수형 인터페이스 타입으로 람다식을 참조할 수 있음.
MyFunction f = (a, b) -> a > b ? a : b;
int value = f.max(3,5);
람다식을 참조변수로 다룰 수 있게 됨으로써, 메서드를 통해 람다식을 주고 받을 수 있음.
즉, 변수처럼 메서드를 주고 받을 수 있게 됨.
@FunctioanlInterface
interface MyFuntion { // 단 하나의 추상메서드만 선언된 함수형 인터페이스
void myMethod(); // public abstract 생략된 추상 메서드
}
void aMethod(MyFunction f) { // 함수형 인터페이스(MyFunction) 타입의 매개변수 f 참조하는 메서드
f.myMethod(); // MyFunction에 정의된 메서드(myMethod) 호출
}
aMethod(() -> System.out.println("myMethod()"));
MyFunction myMethod() { // 함수형 인터페이스 타입의 반환타입을 람다식으로 직접 반환
return () -> {};
}
java.util.function 패키지
- 정의
- 자주 사용되는 다양한 '함수형 인터페이스'를 제공함.
T = Type
R = Return type
java.lang.Runnable
매개변수X, 반환값X → "입력값도, 출력값도 없음."
- 매개변수도 없고, 반환값도 없는 경우에 사용함.
Supplier<T> ; 공급자
매개변수X, 반환값O → "출력값만 있음."
- 매개변수는 없으나, 반환값은 있는 경우에 사용함.
Ex. 특정 범위 내 난수 반환 필요한 경우
Supplier<Integer> f = () -> (int)(Math.random() * 100 + 1);
Consumer<T> ; 소비자
매개변수O, 반환값X → "입력값만 있음."
- 매개변수는 있으나, 반환값이 없는 경우에 사용함.
Ex. 입력값만 있는, 콘솔창에 특정값을 입력하는 경우
Consumer<Integer> f = i -> System.out.println(i + ", ");
Function<T, R> ; 함수
매개변수O, 반환값O → "입력값과 출력값 모두 있음."
- 매개변수 및 반환값 모두 있는 경우에 사용함.
- 매개변수 개수: 1개
Ex. 입력값, 출력값 모두 있는 경우
Function<Integer, Integer> f = i -> i / 10 * 10;
Predicate<T> ; 조건식
매개변수O, 반환값O → "입력값과 출력값(true/false) 모두 있음."
- 매개변수는 하나이고, 반환타입은 boolean임.
- test(T t) 메서드로 boolean 반환값 확인함.
Ex. 조건식인 경우
- Predicate<Integer> f = i -> i % 2 == 0;
Predicate<String> isEmptyStr = s -> s.length() == 0; // s가 빈문자열이면 isEmptyStr임.
String s = "";
if(isEmptyStr.test(s)) // if(s.length == 0)과 동일한 의미임.
System.out.println("This is an empty String.");
- 매개변수가 2개인 함수형 인터페이스
1) BiConsumer<T, U>
- 2개의 매개변수(T, U)는 있고, 반환값은 없음.
- 메서드: void accept(T t, U u)
2) BiPredicate<T, U>
- 2개의 매개변수(T, U)가 있고, 반환값은 boolean임.
- 메서드: boolean test(T t, U u)
3) BiFunction<T, U, R>
- 2개의 매개변수(T, U)가 있고, 1개의 반환값이 있음.
- int와 같은 기본형은 사용 불가능함.
- 메서드: R apply(T t, U u) - 매개변수의 타입과 반환타입이 일치하는 함수형 인터페이스
1) UnaryOperator<T>
- 조상: Function
- 매개변수 타입 = 반환결과 타입
2) BinaryOperator<T>
- 조상: BiFunction
- 2개의 매개변수 가짐.
- 매개변수 타입 = 반환결과 타입
import java.util.function.*;
import java.util.*;
class Ex14_2 {
public static void main(String[] args) {
Supplier<Integer> s = () -> (int)(Math.random()*100) + 1;
Consumer<Integer> c = i -> System.out.print(i + ", ");
Predicate<Integer> p = i -> i % 2 == 0;
Function<Integer, Integer> f = i -> i/10 * 10;
List<Integer> list = new ArrayList<>();
makeRandomList(s, list); // 1 ~ 100 사이의 난수 생성하여 출력
System.out.println(list);
printEvenNum(p, c, list); // 2의 배수인지 확인하고 쉼표 기준으로 출력
List<Integer> newList = doSomething(f, list); // 일의 자리 삭제한 값 출력
System.out.println(newList);
}
// printEvenNum() 메서드
static <T> void printEvenNum(Predicate<T> p, Consumer<T> c, List<T> list) {
System.out.print("[");
for(T i : list) {
if(p.test(i))
c.accept(i);
}
System.out.println("]");
}
// makeRandomList() 메서드
static <T> void makeRandomList(Supplier<T> s, List<T> list) {
for(int i = 0; i < 10; i++) {
list.add(s.get());
}
}
// doSomething() 메서드
static <T> List<T> doSomething(Function<T, T> f, List<T> list) {
List<T> newList = new ArrayList<T>(list.size());
for(T i : list) {
newList.add(f.apply(i));
}
return newList;
}
}
- Predicate (조건식)의 활용방법
1) and(), or(), negate()로 두 Predicate를 하나로 결합함.
→ 가질 수 있는 메서드의 종류: default 메서드, static 메서드, 추상 메서드
cf. and - &&, or - ||, negate - !
2) 등가비교를 위한 Predicate의 작성 시, isEqual() 사용함.
→ 가질 수 있는 메서드의 종류: static 메서드
<and(), or(), negate() 활용>
Predicate<Integer> p = i -> i < 100;
Predicate<Integer> q = i -> i < 200;
Predicate<Integer> r = i -> i % 2 == 0;
Predicate<Integer> notP = p.negate(); // !p와 동일하며, i >= 100 이라는 의미임.
Predicate<Integer> all = notP.and(q).or(r) // 100 <= i && i < 200 || i % 2 == 0
Predicate<Integer> all2 = notP.and(q.or(r)) // 100 <= i && (i < 200 || i % 2 == 0)
<isEqual() 활용>
Predicate<String> p = Predicate.isEqual(str1);
boolean result = p.test(str2); // str1과 동일한지 비교한 결과를 true/false로 반환
// 위의 코드를 다음과 같이 간략하게 작성 가능함.
boolean result = Predicate.isEqual(str1).test(str2);
cf. 항등함수(Identity Function): 입력 받은 값 그대로 반환 값으로 출력되는 것을 의미함. ★★
컬렉션 프레임웍 & 함수형 인터페이스
Collection
- boolean removeIf(Predicate<E> fileter)
- 조건에 맞는 요소를 삭제
List
- void replaceAll(UnaryOperator<E> operator)
- 모든 요소를 변환하여 대체
Iterable
- void forEach(Consumer<T> action)
- 모든 요소에 작업(action) 수행
Map
- V compute(K key, BiFunction<K, V, V> f)
- 지정된 키의 값(key)에 작업(f) 수행 - V computeAbsent(K key, Function<K, V,> f)
- 키(K key)가 없으면, 작업(f) 수행 후 추가 - V computePresent(K key, BiFunction<K, V, V> f)
- 지정된 키(K key)가 있을 때, 작업(f) 수행 - V merge(K key, V value, BiFunction<V, V, V> f)
- 모든 요소에 '병합작업(f)' 수행 - void forEach(BiConsumer<K , V> action)
- 모든 요소에 '작업(action)' 수행 - void replaceAll(BiFunction<K, V, V> f)
- 모든 요소에 '치환작업(f)' 수행
▶ 괄호() 안 내용은 람다식으로 표현하게 됨.
E = mc^2 → Error = (more code)^2
"코드가 많을수록 많은 에러가 발생한다"
메서드 참조(Method Reference)
- 정의
- 람다식을 좀 더 간단히 표현하는 것
- 클래스이름 :: 메서드이름 or 참조변수이름:: 메서드이름 - 종류
1) static 메서드 참조
2) 인스턴스 메서드 참조
- Function<String, Integer> f = (String s) -> Integer.parseInt(s); (*람다식)
→ Function<String, Integer> f =Integer :: parseInt; (*메서드 참조)
3) 생성자의 메서드 참조 (new)
■ Supplier (입력X, 출력O)
- Supplier<MyClass> s = () -> new MyClass(); // MyClass 객체를 출력함.
→ Supplier s = MyClass :: new;
■ Function (입력O, 출력O)
- Function<Integer, MyClass> s = i -> new MyClass(i); // MyClass(i) 객체를 출력함.
→ Supplier s = MyClass :: new;
4) 배열의 메서드 참조
■ Function (입력O, 출력O)
- Function<Integer, int[]> f = x -> new int[x];
→ Function<Integer, int[]> f = int[] :: new;
'LANGUAGE > Java' 카테고리의 다른 글
스트림(Stream) - 컬렉터 클래스(Collectors)의 기능 (1) | 2023.12.05 |
---|---|
스트림(Stream) (1) | 2023.12.05 |
쓰레드 (thread) (1) | 2023.11.30 |
애너테이션(Annotations) (0) | 2023.11.29 |
열거형(enum) (1) | 2023.11.29 |