[Java] Java 8 에서 자주 만나는 것들 1

Lambda

람다 표현식은 메서드를 하나의 식으로 표현한 것을 말한다.

기존의 불필요한 코드를 줄여주고, 작성된 코드의 가독성을 높여준다. 람다 표현식을 사용하여 자바에서도 함수형 프로그래밍을 할 수 있게 되었다.

기본 사용 예시

1
2
3
4
5
6
7
8
9
private static void lambdaTest1() {
  new Thread(new Runnable() {
    public void run() {
      System.out.println("전통적인 방식의 일회용 스레드 생성");
    }
  }).start();

  new Thread(() -> System.out.println("람다 표현식을 사용한 일회용 스레드 생성")).start();
}
1
2
전통적인 방식의 일회용 스레드 생성
람다 표현식을 사용한 일회용 스레드 생성

함수형 인터페이스

함수형 인터페이스는 단 하나의 추상 메서드만을 가져야 한다. 또한, 어노테이션(@FunctionalInterface)을 사용하여 함수형 인터페이스임을 명시할 수 있다.

1
2
3
4
5
6
7
8
9
private static void lambdaTest2() {
  Calc minNum = (x, y) -> x < y ? x : y;
  System.out.println(minNum.min(3, 4));
}

@FunctionalInterface
private interface Calc {
  int min(int x, int y);  // 오직 1개의 추상 메서드를 가진다.
}
1
3

메서드 참조

람다 표현식에서 불필요한 매개변수를 제거한 표현이다. 대신 ::기호를 사용한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private static void lambdaTest3() {
  DoubleUnaryOperator oper;
  oper = (n) -> Math.abs(n);
  System.out.println(oper.applyAsDouble(-5));

  oper = Math::abs;
  System.out.println(oper.applyAsDouble(-5));

  MyClass myClass = new MyClass();
//  Function<Integer, Integer> func = (a) -> myClass.makeDouble(a);
  Function<Integer, Integer> func = myClass::makeDouble;  // 매개변수 제거
  System.out.println(func.apply(10));
}

static class MyClass {
  int makeDouble(int n) {
    return n * 2;
  }
}
1
2
3
5.0
5.0
20

::에 대한 느낌이 오는가? 아니면, 갑자기 DoubleUnaryOperatorFunction과 같은 키워드가 나와서 당황스러운가?

위 예제는 람다 표현식을 변수에 담아서 apply로 실행시키는 과정도 포함되어있다.

DoubleUnaryOperator인터페이스는 한 개의 double 형 매개변수를 전달받아 한 개의 double 형 값을 반환하는 java.util.function 패키지에서 제공하는 함수형 인터페이스이다.

다시 말해 DoubleUnaryOperator는 double형 매개변수를 가지고, double형 리턴타입을 가지는 함수를 담는 타입이라는 얘기다. Javascript를 사용해봤다면 함수를 변수에 저장하는 것이 자연스럽게 느껴질 수 있다.

Function<T, R>인터페이스에서 T는 매개변수 타입, R은 결과 타입이다. R apply(T t)메소드는 함수를 실행시켜 결과를 받는다. FunctionDoubleUnaryOperator보다 더 포괄적인 개념이 될 것이다.

그러면 매개변수가 없거나 리턴 값이 없는 경우는? 이라고 생각한다면 아래 표를 참조하길 바란다. Function이나 DoubleUnaryOperator 외에도 다양한 인터페이스를 Java에서 제공한다.

Interface Table
Supplier ( ) -> x
Consumer x -> ( )
Callable ( ) -> x throws exception
Runnable ( ) -> ( )
Function x -> y
BiFunction x,y -> z
Predicate x -> boolean
UnaryOperator x1 -> x2
BinaryOperator x1,x2 -> x3

생성자 참조

생성자 호출도 화살표(람다 표현식)로 표현할 수 있지만, 단순히 인스턴스를 생성하고 반환한다면 더욱 간단하게 표현할 수 있다.

1
2
3
4
5
6
7
private static void lambdaTest5() {
  Function<Integer, double[]> func1 = a -> new double[a];
  System.out.println(Arrays.toString(func1.apply(5)));

  Function<Integer, double[]> func2 = double[]::new;
  System.out.println(Arrays.toString(func2.apply(5)));
}
1
2
[0.0, 0.0, 0.0, 0.0, 0.0]
[0.0, 0.0, 0.0, 0.0, 0.0]

댓글 남기기