개발을 진행하다보면 람다 표현식을 많이 쓰게 된다. 특히 Stream API를 활용할 때 자주 쓰게 된다.
관련된 서적이나 구글에서 보면 "함수형 인터페이스를 람다 표현식을 사용할 수 있다" 라고 하는데 자바 API에서 제공하는 다양한 함수형 인터페이스가 있지만 자버 1.8부터 등장한 함수형 인터페이스 중 일부분을 살펴보고자 한다.
1. Predicate
2. Consumer
3. Function
세개로 나뉘어 진행할 생각이다.
1. Predicate
Predicate<T> 인터페이스는 test라는 추상 메서드를 정의하며 test는 제네릭 형식 T의 객체를 인수 받아 True / False를 반환한다. 라고 한다.
(해당 인터페이스에 구현된 메소드의 이름은 test이지만 단순히 "boolean 형태로 리턴하는 메소드다" 라고 이해하면 편하다.)
코드를 통해 살펴보자.
내가 구현하고 싶은 것은 2가지로
1) List<String> 에서 "e"가 포함 된 String 값
2) List<Integer>에서 10보다 작은 Integer 값 (git 코드 참고)
이며 입력 데이터는 다음과 같다.
List<String> stringList = Arrays.asList("er", "juer", "min", "lg","uplus","mac","iphone");
List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5, 6, 10, 11, 12, 13);
// stringList : [er, juer, min, lg, uplus, mac, iphone]
// integerList : [1, 2, 3, 4, 5, 6, 10, 11, 12, 13]
1-1. filterString 메소드를 통해 List<String>을 Filtering하기
Predicate 인터페이스를 활용하는 것이 아닌 filterString 메소드를 직접 구현하고 매개변수 List<String> 값을 filtering 하는 가장 기본적인 방법이다.
// List<String> 객체를 filtering 메소드 활용
// 문자열에서 "e"를 포함하면 True, 포함하지 않으면 False
public static boolean stringEq(String str) {
if( str.contains("e")) return true;
return false;
}
public static <T> List<T> filterString(List<T> list) {
List<T> result = new ArrayList<>();
for( T t: list){
// stringEq : "e"가 포함된 문자열 찾기
if(stringEq((String) t)){
result.add(t);
}
}
return result;
}
// filtering 된 List<String> 확인
System.out.println(filterString(stringList));
List<String> 중 "e"가 포함된 문자열값의 List가 출력 되는 것을 확인 할 수 있다.
1-2. Predicate<String> 함수형 인터페이스 활용
이번에는 Predicate 인터페이스를 활용해보자. 이번에는 앞 방법과 다르게 매개변수 값으로 (List<String> list, Predicate<String>) 두개 값을 가지고 Filtering을 해보려고 한다.
Predicate 인터페이스의 test 메소드를 Override 하여 문자열에서 "e"가 포함하는지 하지 않는지 체크하는 기능을 구현하였다.
// Return : Predicate<String>
public static Predicate<String> PredicateStringEq() {
return new Predicate<String>() {
@Override
public boolean test(String t) {
// 메소드를 활용할 것인지 객체간 boolean을 판별할지 모르겠지만 무조건 boolean값을 반환해야함.
// 문자열에서 "e"를 포함하면 True, 포함하지 않으면 False
return t.contains("e");
}
};
}
// Input : List<T> list, Predicate<T> p
public static <T> List<T> filter(List<T> list, Predicate<T> p) {
List<T> result = new ArrayList<>();
for( T t: list){
// test 메소드 즉 내가 Override하여 구현한 로직이 실행된다.
// 여기서는 문자열이 "e" 포함 여부를 판단한다.
if(p.test(t)){
result.add(t);
}
}
return result;
}
filter 함수는 List<T>, Predicate<T> T 객체 즉 제네릭을 사용하여 String, Integer, Long 등 어떠한 변수형태가 올 수 있게 하였다.
// Predicate<String> 함수형 인터페이스 활용
Predicate<String> predicateStringEq = PredicateStringEq();
System.out.println(filter(stringList, predicateStringEq));
결과 값은 1번 메소드를 활용한 것과 동일한 것으로 확인할 수 있다.
1-3. Predicate<Integer> lambda 표현식
이번이 함수형 인터페이스를 활용하려는 이유이기도 하다. lambda를 표현식을 활용하면 구현하는 코드가 너무 간단해진다.
// lambda 표현식
Predicate<String> predicateStringLambda = (String str) -> str.contains("e");
끝이다.
해당 lambda 표현식은 다음과 같은 test 메소드와 같은 로직을 수행한다.
// method override 구현
public static Predicate<String> PredicateStringEq() {
return new Predicate<String>() {
@Override
public boolean test(String t) {
return t.contains("e"); // 메소드를 활용할 것인지 객체간 boolean을 판별할지 모르겠지만 무조건 boolean값을 반환해야함.
}
};
}
List, Predicate T 을 매개변수로 받는 filter 함수에 대입해보면
Predicate<String> predicateStringLambda = (String str) -> str.contains("e");
System.out.println(filter(stringList, predicateStringLambda));
1,2번과 같은 결과값이 나오는 것으로 확인할 수 있다.
1-4. Predicate<Integer> lambda 표현식 그리고 Stream filter 활용
filter 메소드를 구현해야 하고 sout 메소드 또한 쓰는 것도 귀찮아 한다면 다음과 같이 간단히 구현해 낼 수 도 있다.
stringList.stream().filter(s-> s.contains("e")).forEach(
System.out::println
);
그 이유는 stream의 filter 메소드는 Predicate를 활용하기 때문이다.
이렇게 자바 1.8과 함께 도입된 함수형 인터페이스 Predicate에 대해서 간단히 정리하였다.
그 다음은 Consumer로 이 것 또한 Predicate와 같은 함수형 인터페이스를 이해 했다면 간단한 내용이다.
git 코드 주소 :
https://github.com/pminsu01/JavaStudy/tree/master/src/functionInterface
끝.
'개발 지식 > Java' 카테고리의 다른 글
[Java] The server selected protocol version TLS10 is not accepted by client preferences [TLS13, TLS12] (0) | 2022.03.28 |
---|---|
[Java] 함수형 인터페이스 @FunctionalInterface - 2. Consumer (1) | 2022.03.26 |
[Java] 제네릭(Generic)이 무엇일까 그리고 활용법 (0) | 2022.01.09 |
[Optional] orElse와 orElseGet의 차이 (0) | 2021.12.30 |
[Java] 자바란 무엇일까? JVM 메모리, 각 명칭 및 기능 (0) | 2020.07.29 |
댓글