람다식을 이용한 함수형 프로그래밍2 : 메서드

표준 함수형 인터페이스 메서드

  • java.util.function패키지의 인터페이스들은 모두 하나 이상의 default 또는 static 메서드를 포함하고 있는데 이들 메서드를 이용해서 동일한 계열의 여러 동작을 연결해서 사용할 수 있다.




andThen()와 compose()

  • andThen()와 compose() : Consumer, Function, Operator계열에 서언된 dafault메서드.

    • 두 개의 함수형 인터페이스를 순차적으로 연결함.
    • 첫번째 함수의 연산의 결과를 두번째 함수의 파라미터로 제공해서 최종 결과 값을 도출함.
    • 최종 값의 타입은 두번째 함수의 리턴 타입임.
  • 두 메서드의 차이점 : 적용순서.

    • A 인터페이스에 선언되 andThen()을 사용해서 B인터페이스를 연결할 때 = A.andThen(B)
      • A의 결과가 B의 파라미터로 활용되고 B의 리턴값이 AB리턴한 값과 동일함.
    • A 인터페이스에 선언된 compose()를 사용해서 B인터페이스를 연결할 때 = A.compose(B)
      • B의 리턴이 A의 파라미터로 사용되고 A의 리턴값은 AB리턴값과 동일함.

https://palpit.tistory.com/674




Consumer 계열에서의 연결

  • Consumer계열은 리턴값이 존재하지 않기때문에 최초의 파라미터가 그대로 두번째 인터페이스의 파라미터가 됨.
  • 첫번째 인터페이스의 동작은 두번째 인터페이스의 동작에 영향을 주지 않음.
1
2
3
4
5
6
7
8
DoubleConsumer con1 = num -> System.out.println(Math.pow(num, 2));
DoubleConsumer con2 = num -> System.out.println(num+num);
DoubleConsumer andThen = con1.andThen(con2);
andThen.accept(10);

//출력값
100.0
20.0




Function 계열의 연결

  • Function계열 : andThen()과 compose()를 모두 사용가능.
  • 순서차이 확인
1
2
3
4
5
6
7
8
9
10
11
Function<String, String> func1 = name -> "Hi, "+name;
Function<String, String> func2 = data -> "리턴값 : "+data;
Function<String, String> func3 = func1.andThen(func2);
System.out.println(func3.apply("수박"));

Function<String, String> func4 = func1.compose(func2);
System.out.println(func4.apply("수박"));

//출력값
리턴값 : Hi, 수박
Hi, 리턴값 : 수박




Predicate계열의 연결

  • 디폴트 메서드 : and(), or(), negate()
    • and() : 두 개의 predicate를 연결하며 &&연산자와 동일하게 동작
    • or() : 두 개의 predicate를 연결하며 ||연산자와 동일하게 동작
    • negate() : 두 개의 predicate를 연결하며 !연산자(부정)와 동일하게 동작
  • 클래스 메서드 : isEqual() : 대상 객체와 기준 객체를 비교.
  • 위의 메서드들 서로 다른 두개의 predicate를 연결하거나 새로운 predicate반환한다.




메서드와 생성자 참조

  • 더블콜론(::)연산자 : 단순히 기존에 사용된 코드를 재사용하는 경우 더블콜론연산자를 이용해 기존 메서드 참조가능.
1
2
3
클래스 :: 인스턴스_메서드
클래스 :: 클래스_메서드
객체 :: 인스턴스_메서드




클래스 :: 인스턴스_메서드

  • 람다식에 전달된 o1의 타입인 String 클래스가 가지는 compareTo()메서드에 두번째 파라미터인 o2가 전달된다.
1
2
3
4
5
6
7
8
9
10
String[] langs = {"py", "js", "java", "db"};

//1. 기본적인 람다식
Arrays.sort(langs, (o1,o2) -> {
return o1.compareTo(o2);
})


//2. 더블콜론 연산자를 사용한 람다식
Arrays.sort(langs, String::compareTo);




클래스 :: 클래스_메서드

  • f0 : 기본적인 람다식
  • f1 : 최대한 축약한 람다식. 파라미터가 하나이므로 괄호()생략가능. 구현부가 return한 문장이므로 대괄호화 return키워드 생략가능
  • f2 : 더클론론::연산자를 활용한 람다식
1
2
3
4
5
6
7
8
9
10
11
12
13
Function<String, Integer> f0 = (str) -> {return Integer.parseInt(str);};
System.out.println(f0.apply("100"));

Function<String, Integer> f1 = str -> Integer.parseInt(str);
System.out.println(f1.apply("200"));

Function<String, Integer> f2 = Integer::parseInt;
System.out.println(f2.apply("300"));

//출력값
100
200
300




객체 :: 인스턴스_메서드

  • 주어진 객체의 메서드가 호출되며 람다식에 전달된 파라미터는 메서드에 그대로 전달됨.
1
2
3
4
5
6
7
8
9
10
11
12
13
String base ="람다";

//1. 기본적인 람다식
Function<String, Boolean> f11 = str -> base.equals(str);
System.out.println(f11.apply("람다"));

//2. 더블콜론사용한 람다식
Function<String, Boolean> f22 = base::equals;
System.out.println(f22.apply("람다"));

//3. Consumer<T>에서 메서드 참조를 사용한 예시
Consumer<String> f33 = System.out::println;
f33.accept("람다");




클래스 :: new

  • 생성자 참조함.
    • 배열을 만들때 사용 가능 -> 이때, 파라미터 = 배열의 길이.
  • 클래스 타입의 새로운 객체를 생성함.
  • 호출되는 생성자는 전달되는 파라미터의 타입과 개수에 근거하여 결정됨.