Click here to load reader
Upload
beom-kyun-choi
View
8.325
Download
4
Embed Size (px)
DESCRIPTION
자바8의 람다식 소개 Java 8 Lambda expression
Citation preview
자바8 람다식 최범균, 2014-05-29
자바7, 6, 5, ...
Comparator<Integer> comparator = new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return o2 - o1; } };
자바8
Comparator<Integer> comparator = (o1, o2) -> o2 - o1;
람다식(lambda expression)
● 단순히 정의하면, 프로그래밍에서 식별값 없이 실행할 수 있는 함수 표현 방법 o 이미 많은 언어에서 지원: Ruby, C#, Python, o 람다식을 이용한 함수를 생성 예
§ scala: someList.filter(x => x > 0) ● 함수형(Functional) 언어에서 함수는 1급(first-
level class)임 o 함수를 변수에 할당, 파라미터로 전달하는 게 가능
● 자바는 함수가 없는데...?
자바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
람다식의 구성
(Long val1, String val2) -> val1 + val2.length()
파라미터 결과 값
몇 가지 람다식 예
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; };
람다식과 프리 변수
int multiple = 10; Operator<Integer> operator = (x) -> x * multiple; int result = operation( operator );
프리 변수(free variable): 람다식의 파라미터나 식 내부에서 선언되지 않은 변수
● 자바는 람다식에서 사용하는 프리변수의 값을 변경할 수 없음 ● 임의 객체의 경우 프리 변수를 반드시 final로 지정해야 했지만, 람다식의 경우 프리 변수의 값이 바뀌지 않으면 컴파일러가 에러를 발생하지 않음
몇 가지 미리 정의된 함수형 인터페이스
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); }
함수형 인터페이스 강제
● @FuntionalInterface 사용 o @FuntionalInterface가 붙은 인터페이스가 추상 메서드를 두 개 이상 가지면 컴파일 에러 발생!
@FunctionalInterface public interface Operator<T> { public T operate(T op1, T op2); }
메서드 레퍼런스
기존 코드 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) { ... } }
메서드 레퍼런스 종류
● 클래스::정적메서드 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) )
인터페이스의 변화
● 디폴트 메서드(default method) o 인터페이스 메서드가 구현을 가질 수 있음
● 정적 메서드 o 인터페이스가 정적 메서드를 가질 수 있음
디폴트 메서드 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);
디폴트 메서드의 우선 순위
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() } }
상속받은 인터페이스들의 같은 시그너처를 갖는 메서드 중 한 개라도 디폴트 메서드가 있으면, 하위 타입에서 재정의해 주어야 함
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)
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); } }
기타
● 자바8 스트림API: 함수형 인터페이스 천국 o filter(Predicate) o map(Function) o sorted(Comparator) o forEach(Consumer) o reduce(identity, BinaryOperator) o …