함수형 인터페이스는 하나의 추상 메서드를 지정한다. (default 메서드 제외)
람다식은 메소드 이름을 생략하고 필요한 인자만 사용하기 때문에 (String s) -> { ... }
하나의 추상 메서드를 가지는 함수형 인터페이스에서만 적용이 가능하다.
(어차피 메서드가 한개이니 메소드 이름을 생략해도 컴파일러가 찾기 때문인 것 같다.)
자바에서는 다양한 함수형 인터페이스를 제공하며 람다식으로 사용하는 방법을 정리하였습니다.
<T>
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}
[사용법]
public static <T> List<T> filter(List<T> list, Predicate<T> p){
List<T> result = new ArrayList<>();
for(T t : list){
if(p.test(t)){
result.add(t);
}
}
return result;
}
Predicate는 true,false를 반환한다.
그래서 test() 로직의 조건에 따라 true,false 반환하게 하여 필터링 기능을 사용할 수 있다.
그리고 filter 메서드를 사용할 때 직접 Predicate의 test() 를 구현하면 된다.
예를 들면 아래와 같다.
List<String> list = List.of("박진영","김진영","이진영");
//List<String> stringList2 = filter(list,(String s) -> s.equals("박진영"));
List<String> stringList = filter(list,s -> s.equals("박진영"));
//아래 추상메서드를 구현한 것과 같다.
/* -> test(String s){
* return s.equals("박진영"); // 박진영이면 true 아니면 false
* }
*/
for (String str : stringList){
System.out.println(str); // 박진영만 나옴
}
<T>
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}
[사용법]
public static <T> void forEach(List<T> list, Consumer<T> c){
for (T t: list){
c.accept(t);
}
}
void accept(T t) 를 구현하면된다.
인수 t 를 한개 받아서 원하는 로직을 작성하면된다.
아래 예제는 String 인자 한개를 받아 하나씩 출력한다
List<String> list = List.of("박진영","김진영","이진영");
forEach(list,s-> System.out.println(s)); // 박진영 김진영 이진영 출력됨
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
}
apply는 T를 받아서 R로 변환한다.
반복적으로 변환이 필요할 때 사용하면 될 것 같다.
public static <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;
}
apply에 T를 받아 변환된 R이 result에 저장되도록 하였기에
아래 예제는 String 한개씩 받아 첫번째 문자만 받아 문자열 리스트로 저장한다
List<String> list = List.of("박진영","김진영","이진영");
List<String> stringList = map(list,s -> s.substring(0,1) );
// [박, 김, 이] 가 저장된다