JAVA 람다(lambda)
lambda란?
함수형 프로그래밍에서 사용되는 개념입니다. 익명(Anonymous) 함수라고 불립니다.
lambda 특징
1. 추론이 가능한 코드는 제거해 코드가 간결하다 -> 가독성 향상
2. 전달되는 매개변수에 따라서 행위가 결정된다.
3. 람다식 표현 = (파라미터) -> {몸체} 몸체는 return문이 없는 단 일행 일면, {} 생략 가능
코드로 예시를 보겠습니다.
interface Calculator{ // 추상 메소드가 하나인 인터페이스 void operation(int a, int b); } public class Main { public static void main(String[] args) throws IOException { Calculator calculator = new Calculator() { // 람다를 사용하지 않은 형태 @Override public void operation(int a, int b) { System.out.println(a+b); } }; Calculator lambdaCalculator = (a,b) -> { // 추상 메소드를 람다식으로 표현 System.out.println(a+b); }; } }
lambda와 함수형 인터페이스
이미 제작되어 있는 함수형 인터페이스들이 있습니다. 해당 인터페이스를 하나씩 살펴보겠습니다.
Comparator
정렬을 하는데 이용됩니다. Comparator의 형태입니다.
해당 부분을 lambda를 이용해서 구현해보겠습니다.
public interface Comparator<T> { int compare(T o1, T o2); }
public class Main { public static void main(String[] args) throws IOException { List<Integer> list = new ArrayList<>(); list.add(1); list.add(3); list.add(5); list.add(4); list.add(2); Collections.sort(list, (a,b) -> { // comareTo(T o1, T o2)에 a와 b가 매개변수로 전달됩니다. return a-b; // 양수일 경우 바꾸므로 해당 정렬은 오름차순입니다. }); for(Integer now: list){ System.out.println(now); } // 출력 // 1 // 2 // 3 // 4 // 5 Collections.sort(list, (a,b)-> {// comareTo(T o1, T o2)에 a와 b가 매개변수로 전달됩니다. return -(a-b); //양수일 경우 바꾸므로 해당 정렬은 내림차순입니다. }); for(Integer now: list){ System.out.println(now); } // 출력 // 5 // 4 // 3 // 2 // 1 } }
매개 변수가 있고, 반환하는 람다식
interface Calculator{ int cal(int a, int b); } public class Main { public static void main(String[] args) throws IOException { Calculator c; c = (a,b) -> { // a와 b를 매개변수로 넘깁니다. return a+b; }; int cal = c.cal(1, 2); System.out.println(cal); // 3 출력 c = (a,b) ->{ return a-b; }; cal = c.cal(1,2); System.out.println(cal); // -1 출력 c = new Calculator() { // 람다식을 사용하지 않고, Calculator의 cal 함수를 구현한 것입니다. 람다와 같은 결과를 냅니다. @Override public int cal(int a, int b) { return a-b; } }; cal = c.cal(1,2); System.out.println(cal); // -1 출력 } }
@FunctionalInterface
interface에 하나의 추상 메서드만 존재해야 람다식으로 표현이 가능합니다. @FunctionalInterface를 interface에 붙여 조기 검증이 가능합니다.

- 추상 메서드가 2개 이상이므로 @FunctioanlInterface에서 컴파일 오류를 확인할 수 있습니다.
- 혹여나 @FunctionalInterface를 붙이지 않아 검증이 안돼도, 람다식에서 컴파일 오류를 확인할 수 있습니다.
단 허용되는 메서드도 있습니다.
- defalut 메소드
- static 메소드

자바에 정의되어 있는 함수형 인터페이스
자바에서 표준으로 정의하고 있는 함수형 인터페이스들이 있습니다. 하나씩 알아보겠습니다.
Predicate
public interface Predicate<T> { boolean test(T t); }
전달된 인자를 대상으로 true, false 판단합니다.
짝수와 홀수의 합을 출력하는 예시를 보겠습니다.
public class Main { public static void main(String[] args) throws IOException { List<Integer> list = new ArrayList<>(); list.add(1); list.add(2); list.add(3); list.add(4); list.add(5); list.add(6); list.add(7); int evenResult = returnOddSumOrEvenSum(a -> a % 2 == 0, list); // 짝수를 판별합니다. System.out.println(evenResult); // 2+4+6 -> 12 출력 int oddResult = returnOddSumOrEvenSum(a -> a%2==1, list); System.out.println(oddResult); // 1+3+5+7 -> 16 출력 } private static int returnOddSumOrEvenSum(Predicate<Integer> p, List<Integer> list){ int sum=0; for(Integer now: list){ if(p.test(now)){ sum+=now; } } return sum; } }
- a -> (a에 대한 판별식) 매개변수로 보낸 것을 판별하는 식을 통해 boolean을 반환합니다.
Supplier
단순히 무언가를 반환할 때 사용됩니다. 매개변수로 넘기는 것이 없습니다.
public interface Supplier<T> { T get(); }
난수를 생성하고 반환하여 출력하는 예시를 보겠습니다.
public class Main { public static void main(String[] args) throws IOException { List<Integer> list = new ArrayList<>(); list = randomList(() -> { Random random = new Random(); // T get()을 람다식으로 구현 return random.nextInt(10); // 10이하의 랜덤수 생성 }, list); for(Integer now: list){ System.out.println(now); // 만들어진 10개의 수 출력 } } private static List<Integer> randomList(Supplier<Integer> s, List<Integer> list){ for(int i=0; i<10; i++){ Integer integer = s.get(); list.add(integer); } return list; } }
- T get()을 매개변수 없이 반환하는 람다식을 표현하고, 랜덤 수를 생성하는 것을 볼 수 있습니다.
Consumer
전달된 인자를 기반으로 반환 이외의 다른 실행을 할 수 있습니다.
public interface Consumer<T> { void accept(T t); }
난수를 생성하고 출력하는 예시를 보겠습니다.
public class Main { public static void main(String[] args) throws IOException { List<Integer> list = new ArrayList<>(); Random random = new Random(); Consumer<Integer> c = (a) -> { //void accept(T o) 람다식으로 표현 System.out.println(a); }; for (int i = 0; i < 10; i++) { int num = random.nextInt(); // 난수 생성 c.accept(num); // 출력 } } }
- void accept(T o)를 구현하지만, 반환 없이 출력을 수행합니다.
Function
매개 변수와 반환 값이 모두 존재하며, 2번째 매개변수 형태를 반환합니다.
public interface Function<T, R> { R apply(T t); }
문자열이 들어오고, 문자열의 길이를 반환하는 Function을 만들겠습니다.
public class Main { public static void main(String[] args) throws IOException { List<String> list = new ArrayList<>(); list.add("robot"); list.add("cat"); list.add("university"); Function<String, Integer> f = a -> { // String인 a가 들어오고 a의 길이를 반환합니다. return a.length(); }; for(String now: list){ Integer length = f.apply(now); System.out.println(length); // 5, 3, 10 출력됩니다. } } }
- Integer apply(String s)의 형태로 진행됩니다.
정리
람다와 람다 표현식을 이용하여, 코드의 길이를 줄였습니다. 이는 코드의 가독성을 올려줍니다.
지금까지 람다와 람다 표현식을 알아봤습니다. 틀린 부분에 대해서 지적해주시면 감사합니다.
'JAVA' 카테고리의 다른 글
JAVA Enum (0) | 2022.02.24 |
---|---|
JAVA Stream (0) | 2022.02.23 |
JAVA Optional<T> (0) | 2022.02.23 |
JAVA Comparable And Comparator (0) | 2022.02.21 |
Java 제네릭(Generic) (0) | 2022.02.20 |
댓글
이 글 공유하기
다른 글
-
JAVA Stream
JAVA Stream
2022.02.23Stream이란? java에서 데이터의 흐름을 생성할 수 있습니다. 이러한 흐름을 Stream이라고 합니다. Stream을 생성하고 데이터에 연산을 진행할 수 있습니다. 1. 중간 연산 -> 마지막이 아닌 위치에서 실행되는 연산 2. 최종 연산 -> 마지막에 진행되는 연산 연산들을 이용해서 데이터를 가공하는 것이 Stream의 목표라고 할 수 있습니다. Stream 생성 Stream을 생성하는 여러 가지 방법을 살펴보겠습니다. primitive 자료형 int [] arr1 = new int[10]; IntStream stream1 = Arrays.stream(arr1); double [] arr2 = new double[10]; DoubleStream stream2 = Arrays.stream(arr2)… -
JAVA Optional<T>
JAVA Optional<T>
2022.02.23Optional 이란? Optional은 null이 올 수 있는 값을 감싸는 Wrapper 클래스입니다. 즉 개발자는 null을 검증하는 로직을 일일이 작성할 필요 없이 Optional로 감싼 후 Optional의 매소드들을 사용해 가공할 수 있습니다. 간단하게 Optional 사용하지 않은 코드와 사용한 코드를 살펴보겠습니다. Box 안에 담겨 있는 Toy를 가져오는 코드입니다. 이때 Toy가 초기화되지 않아서 NullPointerException이 발생합니다. class Box{ Toy toy; public Toy getToy(){ return toy; } } class Toy{ String name; public String getName() { return name; } } public class… -
JAVA Comparable And Comparator
JAVA Comparable And Comparator
2022.02.21Comparable And Comparator 란? 두 개 모두 interface이며, 객체를 정렬시키는데 이용됩니다. 정렬을 이용하기 위해선 함수를 구현해야 합니다. Comparable과 Comparator 기본 사용 1. Comparable public interface Comparable { // 제네릭이 사용됩니다. public int compareTo(T o); } compareTo() 구현합니다. 반환형이 int입니다. 양수, 0, 음수로 구분되어 정렬을 결정합니다. 0과 음수일 때는 순서를 바꾸지 않고 양수일 때 변경합니다. 비교하는 대상을 설정하고, 현재 객체와 다른 객체를 비교합니다. class Node implements Comparable{ int score; public Node(i… -
Java 제네릭(Generic)
Java 제네릭(Generic)
2022.02.20제네릭 (Generic)이란? 클래스 내부에서 지정하는 것이 아닌 외부에서 사용자에 의해서 지정되는 것입니다. 즉 데이터의 타입(data type)을 일반화(generalize)하는 것입니다. 글만으로는 이해가 잘 가지 않아 코드로 살펴보겠습니다. class GenericsBox{ // 제네릭을 사용하는 클래스 private T type; // 타입을 외부에서 주입받습니다. public GenericsBox(T type) { this.type = type; } @Override public String toString() { return "this is "+type.getClass()+" class"; } } public class Main { public static void main(String[] …
댓글을 사용할 수 없습니다.