18

Click here to load reader

자바8 람다식 소개

Embed Size (px)

DESCRIPTION

자바8의 람다식 소개 Java 8 Lambda expression

Citation preview

Page 1: 자바8 람다식 소개

자바8 람다식 최범균, 2014-05-29

Page 2: 자바8 람다식 소개

자바7, 6, 5, ...

Comparator<Integer> comparator = new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return o2 - o1; } };

Page 3: 자바8 람다식 소개

자바8

Comparator<Integer> comparator = (o1, o2) -> o2 - o1;

Page 4: 자바8 람다식 소개

람다식(lambda expression)

●  단순히 정의하면, 프로그래밍에서 식별값 없이 실행할 수 있는 함수 표현 방법 o  이미 많은 언어에서 지원: Ruby, C#, Python, o  람다식을 이용한 함수를 생성 예

§  scala: someList.filter(x => x > 0) ●  함수형(Functional) 언어에서 함수는 1급(first-

level class)임 o  함수를 변수에 할당, 파라미터로 전달하는 게 가능

●  자바는 함수가 없는데...?

Page 5: 자바8 람다식 소개

자바8의 람다식

●  함수형(Functional) 인터페이스의 임의 객체를 람다식으로 표현 o  함수형 인터페이스: 추상 메서드가 1개인 인터페이스

public interface Comparator<T> { int compare(T o1, T o2); }

Comparator<Long> comp = (Long o1, Long o2) -> o2 - o1 < 0 ? -1 : 1

Page 6: 자바8 람다식 소개

람다식의 구성

(Long val1, String val2) -> val1 + val2.length()

파라미터 결과 값

Page 7: 자바8 람다식 소개

몇 가지 람다식 예

public interface Operator<T> { public T operate(T op1, T op2); } public interface Callable<V> { V call() throws Exception; } public interface Runnable { public void run(); } public interface Predicate<T> { boolean test(T t); }

// 파라미터 타입 지정 Comparator<Long> longComparator = (Long first, Long second) -> Long.compare(first, second); // 파라미터 타입 지정하지 않음, 문맥에서 유추 Comparator<Long> longComparator = (first, second) -> Long.compare(first, second); // 파라미터가 한 개인 경우, 파라미터 목록에 괄호 생략 Predicate<String> predicate = t -> t.length() > 10; // 파라미터가 없는 경우 Callable<String> callable = () -> "noparam"; // 결과 값이 없는 경우 Runnable runnable = () -> System.out.println("no return"); // 코드 블록을 사용할 경우, return을 이용해서 결과 값을 리턴 Operator<Integer> plusSquareOp = (op1, op2) -> { int result = op1 + op2; return result * result; };

Page 8: 자바8 람다식 소개

람다식과 프리 변수

int multiple = 10; Operator<Integer> operator = (x) -> x * multiple; int result = operation( operator );

프리 변수(free variable): 람다식의 파라미터나 식 내부에서 선언되지 않은 변수

●  자바는 람다식에서 사용하는 프리변수의 값을 변경할 수 없음 ●  임의 객체의 경우 프리 변수를 반드시 final로 지정해야 했지만, 람다식의 경우 프리 변수의 값이 바뀌지 않으면 컴파일러가 에러를 발생하지 않음

Page 9: 자바8 람다식 소개

몇 가지 미리 정의된 함수형 인터페이스

java.util.function 패키지에 다양한 상황에 사용할 수 있는 함수형 인터페이스 정의됨

public interface Function<T, R> { R apply(T t); } public interface Predicate<T> { boolean test(T t); } public interface BiFunction<T, U, R> { R apply(T t, U u); } public interface Supplier<T> { T get(); } public interface Consumer<T> { void accept(T t); }

Page 10: 자바8 람다식 소개

함수형 인터페이스 강제

●  @FuntionalInterface 사용 o  @FuntionalInterface가 붙은 인터페이스가 추상 메서드를 두 개 이상 가지면 컴파일 에러 발생!

@FunctionalInterface public interface Operator<T> { public T operate(T op1, T op2); }

Page 11: 자바8 람다식 소개

메서드 레퍼런스

기존 코드 public class SomeView implements OnClickListener { private void init() { myBtn.setOnClickListener(this); youBtn.setOnClickListener(this); } @Override public void onClick(ClickEvent e) { … if (e.getSource() == myBtn) { ... } } }

메서드 레퍼런스 사용 public class SomeView { private void init() { myBtn.setOnClickListener(this::onMyBtnClick); youBtn.setOnClickListener(this::onYouBtnClick); } private void onMyBtnClick(ClickEvent e) { ... } private void onYouBtnClick(ClickEvent e) { ... } }

Page 12: 자바8 람다식 소개

메서드 레퍼런스 종류

●  클래스::정적메서드 o  someOperation( Op::square );

§  someOperation( (x, y) -> Op.square(x, y) ); ●  객체::인스턴스메서드

o  someOperation( obj::square ); §  someOperation( (x, y) -> obj.square(x, y) );

o  someOperation( this::square ); o  someOperation( super::square );

●  클래스::인스턴스메서드 o  someOperation( XClass::double )

§  someOperation( (x, y) -> x.double(y) )

Page 13: 자바8 람다식 소개

인터페이스의 변화

●  디폴트 메서드(default method) o  인터페이스 메서드가 구현을 가질 수 있음

●  정적 메서드 o  인터페이스가 정적 메서드를 가질 수 있음

Page 14: 자바8 람다식 소개

디폴트 메서드 public interface Collection<E> extends Iterable<E> { Iterator<E> iterator();

default boolean removeIf(Predicate<? super E> filter) { Objects.requireNonNull(filter); boolean removed = false; final Iterator<E> each = iterator(); while (each.hasNext()) { if (filter.test(each.next())) { each.remove(); removed = true; } } return removed; }

LinkedList<Long> list = ….; list.removeIf((e) -> e > 10L);

Page 15: 자바8 람다식 소개

디폴트 메서드의 우선 순위

class Team { public int version() { return 0; } }

interface Verion { default int version() { return -1; } }

interface Lockable { default int version() { return 1; } }

class ExtTeam extends Team implements Version { }

항상 클래스가 우선순위 가짐 - ExtTeam 객체의 getVersion()은 Team 클래스의 getVersion() 사용

class Job implements Version, Lockable { @Override public int version() { return Version.super.getName() } }

상속받은 인터페이스들의 같은 시그너처를 갖는 메서드 중 한 개라도 디폴트 메서드가 있으면, 하위 타입에서 재정의해 주어야 함

Page 16: 자바8 람다식 소개

Optional과 람다식의 만남

●  java.util.Optional이란? o  값이 있거나 또는 없는 경우를 표현하기 위한 클래스 o  간단한 예

§  Optional<Long> value = someMethod(); if (value.isPresent()) { Long val = value.get(); }

o  map, filter 등의 고차원(higher order) 함수를 가짐 §  public<U> Optional<U> map(Function<? super T, ? extends U> mapper) §  public Optional<T> filter(Predicate<? super T> predicate) §  public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper)

Page 17: 자바8 람다식 소개

Optional과 람다식의 만남

●  Optional과 고차원 함수의 조합 Optional<Member> mem = findMemberById(1L); Coord result = mem.map(Member::getAddress) .map(address -> address.getZipCode()) .map(zipCode -> findCoord(zipCode)) .orElse(null);

Member mem = findMemberById(1L); Coord result = null; if (mem != null) { if (mem.getAddress() != null) { String zipCode = mem.getAddress().getZipCode(); if (zipCode != null) result = findCoord(zipCode); } }

Page 18: 자바8 람다식 소개

기타

●  자바8 스트림API: 함수형 인터페이스 천국 o  filter(Predicate) o  map(Function) o  sorted(Comparator) o  forEach(Consumer) o  reduce(identity, BinaryOperator) o  …