람다 실습하기 (Comparator, Compose, andThen)
Comparator를 적용해서 람다 실습하기
Chat GPT에게 람다 실습을 위한 문제를 달라고 요청했더니 comparator를 적용하는 문제를 줘서 공부하게 됐다.
기존의 Collections.sort()나 stream().sorted()는 자연적인 순서로 정렬해준다면,
Comparator는 내가 어떤 기준으로 정렬할지 직접 설정할 수 있다.
public class RamdaPrac {
public static void main(String[] args) {
List<String> words = Arrays.asList("banana", "apple", "cherry", "blueberry");
Comparator comparator = (word1, word2) -> {
if (word1.toString().length() > word2.toString().length()) {
return 1;
}else if(word1.toString().length() < word2.toString().length()){
return -1;
}
else{
return 0;
}
};
Collections.sort(words, comparator);
System.out.println(words);
}
}
람다식을 사용해서 Comparator 인터페이스를 구현했다.
두 개의 인자를 받아서, 첫 번째 인자가 큰 경우 1을 반환하고 더 작은 경우는 -1을, 동일한 경우는 0을 반환하도록 했다.
숫자로 리턴하는 이유는 Comparator의 compare() 가 int형을 반환하는 메서드이기 때문이다.
compare() 메서드의 반환값이 음수이면 두 번째 인자가 더 크다고 판단, 양수이면 첫 번째 인자가 더 크다고 판단, 0이면 동일하다고 판단하는 메서드이다.
Collections.sort() 메서드는 인자가 하나만 올 때는 인자로 전달된 리스트를 자연 정렬하는 메서드이다.
하지만 인자가 두 개인 경우는 두 번째 인자로 전달된 Comparator 내부의 compare() 메서드가 실행되어 개발자가 정의한 기준대로 리스트를 정렬한다.
위의 리스트를 자연 정렬했다면 알파벳 순서로 정렬해서 출력하지만, 위의 실습 코드는 정의한대로 문자열의 길이를 기준으로 정렬해서 출력하게 된다.
package study;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
class Person {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public static void main(String[] args) {
List<Person> personList = new ArrayList<>(
List.of(
new Person("김땡땡", 27),
new Person("이땡땡", 25),
new Person("홍길동", 30)
)
);
Comparator<Person> comparator = (p1, p2) -> {
if(p1.age > p2.age){
return 1;
}else if(p1.age < p2.age){
return -1;
}else{
return 0;
}
};
Collections.sort(personList, comparator);
for(Person person : personList){
System.out.println(person.name);
}
}
}
andThen(), compose() 적용해서 람다 실습하기
import java.util.function.Function;
public class AndThen {
public static void main(String[] args) {
Function<String, String> toUpperCase = str -> str.toUpperCase();
Function<String, String> addExclamation = str -> str + "!";
// andThen() 실습
String input1 = "hello";
Function<String, String> output1 = toUpperCase.andThen(addExclamation);
System.out.println(output1.apply(input1));
// compose() 실습
String input2 = "java";
Function<String, String> output2 = toUpperCase.compose(addExclamation);
System.out.println(output2.apply(input2));
}
}
Function<T, R>은 자바에서 제공하는 고차 함수형 인터페이스로, 입력값을 받아 변환하는 함수형 객체를 생성할 수 있다.
여기서 제네릭 T는 입력값에 대한 타입 파라미터이고, R은 출력값에 대한 타입 파라미터다.
이 인터페이스를 활용하면 compose(), andThen() 같이 함수 조합 기능을 사용할 수 있다.
compose(), andThen()은 스트림처럼 여러 개의 함수를 연결해서 순차적으로 실행할 수 있도록 해준다.
andThen()은 앞에 있는 함수를 먼저 수행하고 인자에 있는 함수를 이어 수행한다.
compose()는 인자로 있는 함수를 먼저 수행하고 앞에 있는 함수를 수행한다.
Function<String, String> toUpperCase = str -> str.toUpperCase();
Function<String, String> addExclamation = str -> str + "!";
Function<String, String> output1 = toUpperCase.andThen(addExclamation);
Function<String, String> output2 = toUpperCase.compose(addExclamation);
즉 위의 4줄의 코드는 모두 Function 인터페이스의 apply() 추상 메서드를 구현한 것이지만,
위의 두 줄은 단순 구현한 것이고, 뒤의 두 줄은 함수와 함수를 연결하는 기능을 구현한 것이다.