본문 바로가기
JAVA

Java 람다 알아보자

by 얍얍1234 2024. 6. 2.

오늘은 자바 프로그래밍에서 람다 표현식 에 대해 이야기해보려고 해요.

자바를 사용하면서 종종 "람다"라는 말을 들어보셨을 텐데요, 이게 뭘 의미하는지, 그리고 어떻게 사용하면 되는지 한 번 살펴봅시다.

 

람다 표현식이란?

람다 표현식은 간단히 말해 익명 함수(Anonymous Function)예요. 즉, 이름이 없는 함수죠. 주로 코드의 간결성과 가독성을 높이기 위해 사용됩니다. 자바 8에서 처음 도입된 이 기능은 특히 컬렉션을 처리할 때 매우 유용합니다.

기존에 자바에서 익명 내부 클래스를 사용해 이벤트 리스너나 쓰레드 작업을 정의했었는데, 람다 표현식을 사용하면 훨씬 더 간결하게 작성할 수 있어요.

 

람다 표현식의 기본 문법

람다 표현식은 아래와 같은 형태를 가집니다.

(parameters) -> expression
혹은
(parameters) -> { statements; }

조금 더 구체적으로 살펴보면:

- `(parameters)`는 함수의 매개변수입니다.
- `->`는 람다 표현식을 나타내는 화살표 연산자입니다.
- `expression` 또는 `{ statements; }`는 함수 본문을 나타냅니다.

이해하기 쉽게 예를 들어볼게요. 숫자를 받아 두 배로 만드는 함수를 람다로 표현하면 다음과 같습니다:

(int x) -> x * 2


자바에서의 람다 표현식 사용 예제

자바에서 람다 표현식을 실제로 어떻게 사용하는지 예제를 통해 살펴봅시다.


1. Runnable 인터페이스 구현

기존 방식:

Runnable r = new Runnable() {
    @Override
    public void run() {
        System.out.println("Hello, world!");
    }
};
new Thread(r).start();


람다 표현식 사용:

Runnable r = () -> System.out.println("Hello, world!");
new Thread(r).start();


2. 이벤트 리스너

기존 방식:

button.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("Button clicked!");
    }
});


람다 표현식 사용:

button.addActionListener(e -> System.out.println("Button clicked!"));


3. 컬렉션 정렬

기존 방식:

List<String> list = Arrays.asList("banana", "apple", "cherry");
Collections.sort(list, new Comparator<String>() {
    @Override
    public int compare(String s1, String s2) {
        return s1.compareTo(s2);
    }
});


람다 표현식 사용:

List<String> list = Arrays.asList("banana", "apple", "cherry");
Collections.sort(list, (s1, s2) -> s1.compareTo(s2));


람다 표현식의 장점

람다 표현식을 사용하면 여러 가지 장점을 누릴 수 있어요:

1. 간결성: 코드가 훨씬 짧고 간결해집니다.
2. 가독성: 코드가 더 직관적이고 읽기 쉬워집니다.
3. 유연성: 람다 표현식은 함수형 인터페이스와 잘 어울리며, 더 유연한 코드 작성을 가능하게 합니다.

함수형 인터페이스

람다 표현식이 자바에서 어떻게 동작하는지 이해하려면 함수형 인터페이스 에 대해 알아야 합니다. 함수형 인터페이스는 단 하나의 추상 메서드만을 가지는 인터페이스를 말합니다. 자바 8에서는 `@FunctionalInterface` 어노테이션을 사용해 이를 명시적으로 선언할 수 있습니다.

예를 들어, 다음은 함수형 인터페이스의 예입니다:

@FunctionalInterface
interface MyFunctionalInterface {
    void myMethod();
}



이제 이 인터페이스를 람다 표현식으로 구현할 수 있습니다:

MyFunctionalInterface func = () -> System.out.println("Hello, Functional Interface!");
func.myMethod();

 


자바 8에서는 여러 가지 기본 제공 함수형 인터페이스도 제공됩니다.

대표적으로 `Function`, `Predicate`, `Consumer`, `Supplier` 등이 있습니다.

기본 제공 함수형 인터페이스 예제

Function 인터페이스

`Function<T, R>` 인터페이스는 입력 타입 `T`와 출력 타입 `R`을 가지는 함수를 나타냅니다. 주로 매핑 작업에 사용됩니다.

Function<Integer, String> intToString = (i) -> "Number: " + i;
System.out.println(intToString.apply(5)); // 출력: Number: 5


Predicate 인터페이스

`Predicate<T>` 인터페이스는 입력 타입 `T`를 받아 `boolean` 값을 반환하는 함수를 나타냅니다. 주로 조건 검사에 사용됩니다.

Predicate<String> isLongerThanFive = (s) -> s.length() > 5;
System.out.println(isLongerThanFive.test("Hello")); // 출력: false
System.out.println(isLongerThanFive.test("Hello, World!")); // 출력: true

Consumer 인터페이스

`Consumer<T>` 인터페이스는 입력 타입 `T`를 받아서 어떤 동작을 수행하고, 반환값은 없는 함수를 나타냅니다.

Consumer<String> printString = (s) -> System.out.println(s);
printString.accept("Hello, Consumer!"); // 출력: Hello, Consumer!


Supplier 인터페이스

`Supplier<T>` 인터페이스는 입력은 없고, 출력 타입 `T`만을 반환하는 함수를 나타냅니다.

Supplier<Double> randomValue = () -> Math.random();
System.out.println(randomValue.get()); // 예시 출력: 0.7234652476

 

스트림과 람다 표현식

자바 8에서 도입된 또 하나의 멋진 기능은 스트림 API 입니다. 스트림을 사용하면 컬렉션을 더욱 효율적이고 선언적으로 처리할 수 있습니다. 스트림과 람다 표현식을 결합하면 매우 강력한 기능을 사용할 수 있죠.

예제: 리스트 필터링 및 매핑

List<String> names = Arrays.asList("John", "Jane", "Jack", "Doe");
List<String> filteredNames = names.stream()
                                  .filter(name -> name.startsWith("J"))
                                  .map(String::toUpperCase)
                                  .collect(Collectors.toList());
System.out.println(filteredNames); // 출력: [JOHN, JANE, JACK]

 

마무리

람다 표현식은 자바 코드의 간결성과 가독성을 높이는 매우 유용한 도구입니다. 함수형 인터페이스와 함께 사용하면 더욱 강력한 기능을 발휘하죠. 아직 람다 표현식을 사용해보지 않았다면, 이번 기회에 꼭 한 번 시도해보세요. 코드 작성이 훨씬 즐거워질 거예요!

여기까지 자바 람다 표현식에 대해 알아보았습니다.