본문 바로가기
개발 지식/Java

[Java] 함수형 인터페이스 @FunctionalInterface - 1. Predicate

by 에르주 2022. 3. 11.
반응형

개발을 진행하다보면 람다 표현식을 많이 쓰게 된다. 특히 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));

필터링 Predicate 활용 1

 

결과 값은 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));

Predicate lambda&amp;amp;nbsp;

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를 활용하기 때문이다.

stream filter 구현
stream filter 결과값

 

이렇게 자바 1.8과 함께 도입된 함수형 인터페이스 Predicate에 대해서 간단히 정리하였다.

그 다음은 Consumer로 이 것 또한 Predicate와 같은 함수형 인터페이스를 이해 했다면 간단한 내용이다.

 

git 코드 주소 : 

https://github.com/pminsu01/JavaStudy/tree/master/src/functionInterface

 

GitHub - pminsu01/JavaStudy: 자바 자체 스터디

자바 자체 스터디. Contribute to pminsu01/JavaStudy development by creating an account on GitHub.

github.com

끝.

반응형

댓글