끄적이기

[TIL - 3] 람다 표현식 + 알쓸신잡 (이제는 그만좀 까먹자)

배씌 2025. 2. 27. 10:23

자바 기초부터 다시 공부하고 있는 중이다. 문제를 풀면서, 또 기본적인 (약수 판별, 피보나치 등.. ) 알고리즘들도 솔직히 한번에 쭉쭉 작성해나가지 못하고 주춤거렸다. 반성하자..

 

또 까먹을진 모르겠지만, 최소한 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;
}