[TIL - 3] 람다 표현식 + 알쓸신잡 (이제는 그만좀 까먹자)
자바 기초부터 다시 공부하고 있는 중이다. 문제를 풀면서, 또 기본적인 (약수 판별, 피보나치 등.. ) 알고리즘들도 솔직히 한번에 쭉쭉 작성해나가지 못하고 주춤거렸다. 반성하자..
또 까먹을진 모르겠지만, 최소한 6개월 안에는 그럴 일이 없도록 반복해서 작성하겠다. 학습한 내용들은 1차적으로 노션에 정리해둔 뒤, TIL이나 블로그에 2차적으로 정리해서 기록해놓는 방식으로 공부하려 한다.
쓸만한 지식
1. Deque 사용 시 poll(), remove() 차이점
- poll() : 비어있을 때 null 반환
- remove() : 비어있을 때 예외 발생 (NoSuchElementException)
2. 문자열 다중 공백 제거
문제를 풀다 보면, 문자열을 공백을 기준으로 나누어야 할 때가 있다. 이때, 만약 어떤 문장 사이에 공백이 2개 이상이 끼어버린다면, 그 문자열의 공백의 개수를 조정하자.
.replaceAll("\\s+", " ");
정규식 "\s" 는 공백들을 의미한다. (\t, \n, \x0B, \f, \r)
그리고 "+" 는 1번 이상을 의미한다.
위 표현은 "\s+" 1번 이상의 공백을 " " 띄워쓰기 1칸으로 치환한다. 라는 의미이다.
static void Problem04() {
String s = "Hi, My name is xxx";
s = s.replaceAll("\\s+", " "); // s : "Hi, My name is xxx"
}
3. 문자가 알파벳인지 판별
- Character.isAlphabetic() : 해당 문자가 알파벳인지 아닌지 판별
학습한 내용
람다 표현식
함수형 프로그래밍을 구성하기 위한 함수식, 자바의 메서드를 간결한 함수식으로 표현한 것.
아래와 같이 기본적인 메서드 표현식을 람다 표현식을 이용해 줄일 수 있다. 그래서, 익명 함수(Anonymous Function) 라고도 함.
int add(int x, int y) {
return x + y;
}
// 람다 표현식 (메서드 반환타입, 메서드 이름 생략)
(int x, int y) -> {
return x + y;
};
// 매개변수 타입 생략
(x, y) -> {
return x + y;
};
// 함수에 리턴문 한줄만 있을 경우 더 단축 가능 (중괄호, return 생략)
(x, y) -> x + y;
기존의 객체 지향 방식과도 비교해볼 수 있다.
일반적으로는 아래와 같이 [인터페이스 -> 구현 클래스 -> 인스턴스 생성 -> 메서드 사용] 의 단계를 따른다.
interface IAdd {
int add(int a, int b);
}
static class Add implements IAdd {
public int add(int a, int b) {
return a + b;
}
}
public static void main(String[] args) {
Add a = new Add();
int result = a.add(1, 2);
System.out.println(result);
}
여기서, 한번만 사용하고 버려질 클래스라면, 굳이 번거롭게 클래스를 선언하지 말고 익명 클래스로 오버라이딩 하여 사용하기도 한다.
interface IAdd {
int add(int a, int b);
}
public static void main(String[] args) {
// 익명 클래스 정의
IAdd b = new IAdd() {
public int add(int a, int b) {
return a + b;
}
};
int result = b.add(1, 2);
System.out.println(result);
}
여기서 람다는 이 익명 클래스 부분을 짧게 표현한다.
interface IAdd {
int add(int a, int b);
}
public static void main(String[] args) {
// 익명 클래스 정의
IAdd b = new IAdd() {
public int add(int a, int b) {
return a + b;
}
};
// 람다 표현식으로 함축
IAdd c = (x, y) -> { return x + y; };
int result = c.add(1, 2);
System.out.println(result);
}
그러나 이러한 람다도 아무 클래스나 추상 클래스의 메서드를 람다로 표현할 수 있는 것은 아니다.
오로지 인터페이스로 선언한 익명 구현 객체만이 람다식으로 표현 가능하다 -> 함수형 인터페이스
함수형 인터페이스
딱 하나의 추상 메서드가 선언된 인터페이스
위 예시의 IAdd 인터페이스가 함수형 인터페이스다.
// 함수형 인터페이스 가능
interface IAdd {
int add(int a, int b);
}
// 함수형 인터페이스 불가능
interface ICalc {
int add(int a, int b);
int sub(int a, int b);
}
함수형 인터페이스를 만들 때, 어노테이션을 사용하여 컴파일러의 도움을 받자. (@FunctionalInterface)
// 함수형 인터페이스 불가능
@FunctionalInterface
interface ICalc {
int add(int a, int b);
int sub(int a, int b); // 컴파일 오류 발생
}
람다식 활용
가장 큰 특징은 변수에 정수를 할당하듯이 함수를 할당할 수 있다는 것.
1. 람다식 변수 할당
interface IAdd {
int add(int a, int b);
}
public static void main(String[] args) {
IAdd lambda = (a, b) -> a + b; // 함수를 변수에 할당
lambda.add(1, 2); // 함수 사용
}
2. 람다식 매개변수 할당
interface IAdd {
int add(int a, int b);
}
public static void main(String[] args) {
int n = result((a, b) -> a + b);
System.out.println(n);
}
static int result(IAdd lambda) {
return lambda.add(1, 2);
}
3. 람다식 반환값 할당
interface IAdd {
int add(int a, int b);
}
public static void main(String[] args) {
IAdd func = makeFunction(); // 메서드의 반환값이 람다 함수
int result = func.add(1, 2);
System.out.println(result);
}
static IAdd makeFunction() {
return (a, b) -> a + b;
}