Lambda
개요
람다를 알기 이전에 우리는 Funtional Interface 에 대해서 짚고 넘어갈 필요가 있습니다.
Funtional Interface 란 재정의될 추상 메서드가 딱 하나뿐인 인터페이스를 이릅니다.
이는 Single Abstract Method (SAM) 라기도 하며, 아주 구체적이고 전문적인 기능을 하는 메서드를 만들고 싶을 때 사용합니다.
https://docs.oracle.com/javase/8/docs/api/
우리가 알아볼 Comparable 인터페이스가 그런 형식입니다.
이게 근데 람다와 무슨 관련이 있을까요?
바로 sorting 을 하기 위해 Comparable<T> 를 사용할 때, Comparator<T> 인터페이스를 매개변수로 받는데
이를 람다식으로 표현하여 편리하게 넘길 수 있기 때문입니다.
람다식
만약 javascript 나 python 을 이용해보신 분이라면 익명함수 (Anonymous Funtions) 가 무엇인지 알고 계실 것입니다.
java 에서도 마찬가지로 람다식이 이용이 됩니다. 람다식은 익명함수의 통칭입니다.
람다식을 이용하면 굳이 부차적인 코딩을 하지 않아도 돼서 개발에 용이성을 높여주죠.
public int add(int a, int b) {
return a + b;
}
예를 들어 위와 같은 함수식이 있다고 가정합시다. 이를 익명함수로 바꾼다면 아래와 같이 변경할 수 있습니다.
int n = (a, b) -> a + b;
무척 간단하죠?
int n = (a, b) -> { return a + b; }
java 에서는 {} 를 많이 사용하니 위와 같이 나타낼 수도 있을 것입니다.
예제
// Functional Interface
package first.m07.subject01.lambda;
public interface MyNote {
String write(int no, String content);
}
// MyNote 를 implements 하는 MyNoteImpl 클래스
package first.m07.subject01.lambda;
public class MyNoteImpl implements MyNote {
@Override
public String write(int no, String content) {
return String.format("%d %s", no, content);
}
}
package first.m07.subject01.lambda;
public class Test {
public static void main(String[] args) {
{
MyNote note = new MyNoteImpl();
String str = note.write(1, "노트1");
System.out.println(str);
}
{
MyNote note = new MyNoteImpl() {
@Override
public String write(int no, String content) {
return String.format("%d %s 입니다.", no, content);
};
};
String str = note.write(2, "노트2");
System.out.println(str);
}
{
MyNote note = (no, content) -> {
return String.format("%d %s 입니다요.", no, content);
};
String str = note.write(3, "노트3");
System.out.println(str);
}
}
}
저런식으로 람다 클래스를 만들고, 람다식 함수로 확장을 할 수 있습니다.
Comparable<T> 와 Comparator<T>
위 인터페이스를 이용해서 람다식이 얼마나 간편한지 한번 알아보겠습니다.
객체를 정렬할 때, 비교 기준을 제시하지 않는다면 객체를 정렬할 수 없을 것 입니다.
이러한 비교 기준을 자바에서는 Comparable 와 Comparator 가 제시합니다.
보시면 아시겠지만 Comparable 와 Comparator 모두 Interface 입니다.
여기서 우리가 구현해서 사용해야 할 것은 딱 두가지의 메서드 입니다.
1. Comparable<T> 의 compareTo()
2. Comparator<T> 의 compare()
Comparator 는 다른 메서드가 많아 다른 것도 재정의를 해야하지않나? 라고 생각이 들 수 있지만
compare() 을 제외하고는 다 default 나 static 으로 정의되어 구현부가 작성되어 있기 때문에 재정의 하지 않아도 됩니다.
비교되는 값
그리고 또 api document 를 참조하면 알 수 있는 점이 compare(T o1, T o2) 로 매개변수가 2개 이고,
compareTo(T o) 는 매개변수가 하나 입니다.
즉, compareTo() 해당 메서드가 사용되는 클래스 객체와 비교가 되는 것입니다.
예를 들어 o1.compareTo(o2); 라고 한다면 o1 와 o2 가 비교되는 것이지요.
compare() 은 어떻게 될까요? o3.compare(o1, o2); 라면 o1 와 o2 가 비교됩니다.
반환 값
정수를 반환한다. -1 (음수), 0, 1 (양수)
둘 다 int 값을 반환하는 것을 확인할 수 있습니다.
따라서 비교되는 기준을 세울 때 정수로 반환되도록 세워야 합니다.
Arrays.sort(T[] a, Comparator<? super T> c)
여기까지 왔는데도 감이 잘 안잡힙니다. 그래서 Comparable 과 Comparator 가 뭐 어쩌라는 것일까요.
바로 그 해답은 Arrays.sort() 에 있습니다. Arrays api 를 보면 sort() 메서드가 있는 것을 확인할 수 있습니다.
보면 첫번째를 제너릭으로 받고, 두번째는 Comparator<T> 로 받습니다.
Arrays.sort() 를 이용해서 객체 배열을 정렬할 수 있는데
여기서 Comparator<T> 에 람다식을 사용하면 쉽게 원하는 비교 기준으로 정렬을 할 수 있게 됩니다.
Arrays.sort(strs, (o1, o2) -> {o1.length() - o2.length()});
예를 들어 String[] 타입의 strs 배열을 문자열의 길이를 기준으로 정렬을 하고 싶다고 합시다.
그러면 저런식으로 뒤에 Comparator<T> 를 받는 매개변수 부분에 람다식을 사용하여
비교기준을 길이로 설정을 하면 되는 것입니다.
return 이 정수이니 만약 음수를 리턴하면 o1.length() - o2.length() < 0 이 되어 o1 보다 o2 의 길이가 더 길다. 이런식으로 정렬을 할 수가 있게 되겠죠. 이렇게 객체 배열을 람다식을 이용하여 정렬할 수 있게 됩니다.
# java lambda # java anonymous functions # 자바 comparable # 자바 comparator
# java comparable comparator
'🧑💻 𝗣𝗿𝗼𝗴𝗿𝗮𝗺𝗺𝗶𝗻𝗴 > Java' 카테고리의 다른 글
Java 2진수, 8진수, 16진수, 10진수 변환 (0) | 2022.09.28 |
---|---|
Java HashSet 정렬하기 (0) | 2022.09.28 |
Java 객체지향 프로그래밍 - 다형성 (Polymorphism) (0) | 2022.07.31 |
Java 객체지향 프로그래밍 - 싱글톤 패턴 (Singleton) (0) | 2022.07.31 |
Java 객체지향 프로그래밍 - 은닉화(Encapsulation) 와 접근 제한자 (modifier) (0) | 2022.07.31 |