75
나에 첫번째 자바8 람다식 - @blueiur(twitter)

2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

Embed Size (px)

Citation preview

Page 1: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

나에 첫번째 자바8 람다식 - @blueiur(twitter)

Page 2: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

오! 벌써 새벽 3시네, 컴퓨터 끄고 자야겠어!

한 시간 후 ...

정대원@blueiur(twitter)● like ..

○ programming language○ functionl programming○ elixir○ scala○ ruby

Page 3: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

람다

● 람다 계산법● 익명 함수● 함수 리터럴● 클로저

Page 4: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

익명 함수Wikipedia

● 특정 식별자 없이 정의되거나 호출될 수 있는 함수

Page 5: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

람다가 왜 필요할가?● 행위 매개변수(코드 블럭) 전달

Page 6: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

// 1. 컬렉션 정렬 (익명 클래스 사용)

Collections.sort(names, new Comparator<String>() { @Override public int compare(String a, String b) { return a.compareTo(b); }});

컬렉션 정렬 - 익명 클래스 사용

Page 7: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

// 1. 컬렉션 정렬 (익명 클래스 사용)Collections.sort(names, ...);

Collections.sort + a.compareTo(b)

new Comparator<String>() { @Override public int compare(String a, String b) { return a.compareTo(b); }}

Page 8: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

// 1. 컬렉션 정렬 (익명 클래스 사용)Collections.sort(names, ...);

Collections.sort + [a.compareTo(b), b.compareTo(a)]

new Comparator<String>() { @Override public int compare(String a, String b) { return a.compareTo(b); }}

new Comparator<String>() { @Override public int compare(String a, String b) { return b.compareTo(a); }}

Page 9: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

새 쓰레드 생성 - 익명 클래스 사용

// 쓰레드 생성 (익명 클래스 사용)new Thread(new Runnable() { @Override public void run() { System.out.println("I consume memory, therefore i am!"); } }).start();

Page 10: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

// 1. 쓰레드 생성 (익명 클래스 사용)new Thread(...);

new Thread(...) + System.out.println("...");

new Thread(new Runnable() { @Override public void run() { System.out.println("I consume memory, therefore i am!"); } }).start();

Page 11: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

// 1. 쓰레드 생성 (익명 클래스 사용)new Thread(...);

new Thread(...) + [System.out.println("..."), DB.write("...")]

new Thread(new Runnable() { @Override public void run() { System.out.println("I consume memory, therefore i am!"); } }).start();

new Thread(new Runnable() { @Override public void run() { DB.write("I consume memory, therefore i am!"); } }).start();

Page 12: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

행위 매개변수 사용에 장점● 고정된 코드 + 행위 매개변수(익명 클래스) 조합을 사용한 다양한 확장

a. 더 일반화된 메서드b. 더 유연한 인터페이스 c. 코드 중복 제거

Page 13: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

요구사항 - 리스트 정렬

● 정수형 리스트 정렬● 문자열 리스트 정렬● comparable을 상속받지 않은 객체 정렬

a. 서로 다른 필드를 기준으로 정렬(ex: price, name)

Page 14: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

public static <T extends Comparable<T>> List<T> sort(List<T> list) { ArrayList<T> ls = new ArrayList<>(list); for(int i=0; i<ls.size(); i++) { int minIndex = i; for(int j=i+1; j<ls.size(); j++) { if (ls.get(j).compareTo(ls.get(minIndex)) < 0) { minIndex = j; } } T tmp = ls.get(i); ls.set(i, ls.get(minIndex)); ls.set(minIndex, tmp); } return ls;}

sort(Arrays.asList("c", "b", "d", "a"))sort(Arrays.asList(1, 3, 2, 4))

Generic을 사용한 정렬 구현

comparable을 상속

Page 15: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

요구사항 - 리스트 정렬

● 정수형 리스트 정렬● 문자열 리스트 정렬● comparable을 상속받지 않은 객체 정렬

a. 서로 다른 필드를 기준으로 정렬(ex: price, name)

Page 16: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

정렬 기준을 변경하고 싶다

sort(Arrays.asList(k7, k5, k3, i30), 가격 순으로 정렬)sort(Arrays.asList(k7, k5, k3, i30), 이름 순으로 정렬)

public class Car { public String name; public int price;

public Car(String name, int price) { this.name = name; this.price = price; }}

Page 17: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

public static <T extends Comparable<T>> List<T> sort(List<T> list) { ArrayList<T> ls = new ArrayList<>(list); for(int i=0; i<ls.size(); i++) { int minIndex = i; for(int j=i+1; j<ls.size(); j++) { if (ls.get(j).compareTo(ls.get(minIndex)) < 0) { minIndex = j; } } T tmp = ls.get(i); ls.set(i, ls.get(minIndex)); ls.set(minIndex, tmp); } return ls;}

코드 분석

값 2개를 비교해서 [-1, 0, 1]중 하나를 반환

Page 18: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

public static <T extends Comparable<T>> List<T> sort(List<T> list) { ArrayList<T> ls = new ArrayList<>(list); for(int i=0; i<ls.size(); i++) { int minIndex = i; for(int j=i+1; j<ls.size(); j++) { if (ls.get(j).compareTo(ls.get(minIndex)) < 0) { minIndex = j; } } T tmp = ls.get(i); ls.set(i, ls.get(minIndex)); ls.set(minIndex, tmp); } return ls;}

인터페이스로 분리

interface Comparator<T> { int compare(T a, T b);}

값 2개를 비교해서 [-1, 0, 1]중 하나를 반환

Page 19: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

public static <T> List<T> sort(List<T> list, Comparator<T> comp) { ArrayList<T> ls = new ArrayList<>(list); for(int i=0; i<ls.size(); i++) { int minIndex = i; for(int j=i+1; j<ls.size(); j++) { if (comp.compare(ls.get(j),ls.get(minIndex) < 0) { minIndex = j; } } T tmp = ls.get(i); ls.set(i, ls.get(minIndex)); ls.set(minIndex, tmp); } return ls;}

Comparator 인터페이스를 사용

interface Comparator<T> { int compare(T a, T b);}

값 2개를 비교해서 [-1, 0, 1]중 하나를 반환

Page 20: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

// 2. 이름으로 정렬sort(cars, new Comparator<Car>() { @Override public int compare(Car a, Car b) { return a.name.compareTo(b.name); }});

익명 클래스를 사용한 행동 전달

// 1. 가격으로 정렬sort(cars, new Comparator<Car>() { @Override public int compare(Car a, Car b) { return a.price.compareTo(b.price); }});

다른 부분가격/이름 으로 비교

Page 21: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

요구사항 - 리스트 정렬● 정수형 리스트 정렬● 문자열 리스트 정렬● comparable을 상속받지 않은 객체 정렬

a. 서로 다른 필드를 기준으로 정렬(ex: price, name)

Page 22: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

행위 매개변수 사용에 장점● 고정된 코드 + 행위 매개변수(코드 블럭) 조합을 사용한 다양한 확장

a. 더 일반화된 메서드b. 더 유연한 인터페이스 c. 코드 중복 제거

Page 23: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

람다가 왜 필요할가?● 행위 매개변수(코드 블럭) 전달● 자바8 이전에는 익명 클래스를 사용

Page 24: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

익명 함수Wikipedia

● 특정 식별자 없이 정의되거나 호출될 수 있는 함수● 자바에 함수가 있나? -> 람다!

Page 25: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

(인자 목록) -> { 구문 }● x -> x + 1● (x) -> x + 1● (int x) -> x + 1● (int x, int y) -> x + y● (x, y) -> { System.out.println(x + y) }● () -> { System.out.println("runnable!"); }

람다 문법

Page 26: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

@Functional Interface● 추상 메서드가 1개 뿐인 인터페이스● 인터페이스를 함수처럼 사용하자

Page 27: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

@FunctionalInterfaceinterface Action { void run(String param); void stop(String param);}

@FunctionalInterfaceinterface Runnable() { void run();}

메서드 1개 OK!

메서드 2개 NO!

Page 28: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

익명 클래스를 람다로 변환해 주는 IntelliJ

Page 29: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

// 1. 람다 사용 (자바8)Collections.sort(names, (a, b) -> a.compareTo(b));

// 1. 익명 클래스 사용 (자바8 이전)

Collections.sort(names, new Comparator<String>() { @Override public int compare(String a, String b) { return a.compareTo(b); }});

행위 매개변수 전달: 클래스 -> 람다

1:1 대응

Page 30: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

interface Comparator<T> { int compare(T a, T b);}

함수형 인터페이스를 사용한 정렬

// 1. 익명 클래스 사용 (자바8 이전)

Collections.sort(names, new Comparator<String>() { @Override public int compare(String a, String b) { return a.compareTo(b); }});

Page 31: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

// 1. 익명 클래스 사용 (자바8 이전)

Collections.sort(names, new Comparator<String>() { @Override public int compare(String a, String b) { return a.compareTo(b); }});

interface Comparator<T> { int compare(T a, T b);}

불필요한 객체 생성 제거, 메서드도 1개뿐이니 별도 이름 불필요

객체 이름 제거메서드 이름 제거

Page 32: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

// 1. 익명 클래스 사용 (자바8 이전)

Collections.sort(names, new Comparator<String>() { @Override public int compare(String a, String b) { return a.compareTo(b); }});

interface Comparator<T> { int compare(T a, T b);}

반환 타입과 파라미터 타입도 이미 정해져 있으니 제거

객체 이름 제거메서드 이름 제거반환 값 및 파라미터 타입 추론

Page 33: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

// 1. 람다 사용 (자바8)Collections.sort(names, (a, b) -> { return a.compareTo(b); });

비슷하다

// 1. 익명 클래스 사용 (자바8 이전)

Collections.sort(names, new Comparator<String>() { @Override public int compare(String a, String b) { return a.compareTo(b); }});

Page 34: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

람다 문법: (인자 목록) -> { 구문 }● x -> {return x * 2}● x -> x * 2● (int x) -> x + 1● (int x, int y) -> x + y● (x, y) -> { System.out.println(x + y) }● () -> { System.out.println("runnable!"); }

실행문이 1개인 경우 {} 와 return 키워드 생략 가능

Page 35: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

// 1. 람다 사용 (자바8)Collections.sort(names, (a, b) -> a.compareTo(b));

익명 클래스 -> 람다

// 1. 익명 클래스 사용 (자바8 이전)

Collections.sort(names, new Comparator<String>() { @Override public int compare(String a, String b) { return a.compareTo(b); }});

Page 36: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

@FunctionalInterfaceinterface Adder { int add(int a, int b);}

????? func = (int a, int b) -> { return a + b };????? shortFunc = (a, b) -> a + b;

람다 타입

Page 37: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

@FunctionalInterfaceinterface Adder { int add(int a, int b);}

Adder func = (int a, int b) -> { return a + b };Adder shortFunc = (a, b) -> a + b;

람다 타입

Page 38: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

Q: 람다는 단순히 익명 클래스에 문법 치환인가?

A: No! 실제로는 익명 클래스에 비효율을 제거하기 위해서 사용

invoke dynamic

Page 39: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

interface Comparator<T> { int compare(T a, T b);}

함수형 인터페이스 - 추상 메서드를 1개만 들고 있다

@FunctionalInterfaceinterface Runnable<T> { void run();}

???

Page 40: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

@FunctionalInterface 어노테이션은 붙이는 이유?● 컴파일러가 추상 메서드가 2개인 경우 컴파일 오류 발생● Javadoc에 @FunctionalInterface 글 추가

Page 41: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

Target typing● 람다 -> 익명 클래스 변환시 가장 유사한 타입을 찾아가는것

Page 42: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

public static <X, Y> void processElements( Iterable<X> source, Predicate<X> tester, Function <X, Y> mapper, Consumer<Y> block) { for (X p : source) { if (tester.test(p)) { Y data = mapper.apply(p); block.accept(data); } }}

Target typing

processElements( roster, p -> p.getGender() == Person.Sex.MALE // Predicate p -> p.getEmailAddress(), // Function email -> System.out.println(email) // Consumer);

람다 두개 모두 같은 모습이지만알아서 잘 찾아간다

Page 43: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

Target typing and Method arguments

predicate가 왜 필요할가?

Function<String, Boolean> isDaewon = s -> "daewon".equals(s);Predicate<String> isDaewon = s -> "daewon".equals(s);

Page 44: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

Target typing and Method arguments

interface Runnable { void run();}

interface Callable<V> { V call();}

void invoke(Runnable r) { r.run();}

<T> T invoke(Callable<T> c) { return c.call();}

invoke(() -> {});invoke(() -> "done");

Page 45: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

Target typing and Method arguments

interface Runnable { void run();}

interface Callable<V> { V call();}

void invoke(Runnable r) { r.run();}

<T> T invoke(Callable<T> c) { return c.call();}

invoke(() -> {});invoke(() -> "done");

반환값을 참고해서오버로드된 메서드도 잘 찾아간다

Page 46: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

변수 포획

Page 47: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

public static void thread(String msg) { int tmp = 10; new Thread( () -> System.out.println(msg) ).start(); }

람다 내부에 선언되지 않은 변수를 참조할 수 있다● 자유변수: 나를 감싸고 있는 유효 범위 변수

a. String msg, int tmp

자신은 감싸고 있는 유효 범위 변수에 접근 가능

Page 48: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

public static void thread(String msg) { new Thread( () -> { msg = "must be final"; System.out.println(msg) ).start(); }}

컴파일 에러: 포획된 변수를 수정

포획된 변수는 언제나 final이여야 한다

Page 49: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

Function<String, Predicate<String>> startsWithFactory = s1 -> { return (s2) -> s2.indexOf(s1) > -1;};

Predicate<String> isIncludeGoogle = startsWithFactory.apply("google");Predicate<String> isIncludeApple = startsWithFactory.apply("apple");

System.out.println(isIncludeApple.test("microsoft.com apple.com")); // trueSystem.out.println(isIncludeGoogle.test("microsoft.com apple.com")); // false

변수 참조를 활용해서 동적으로 새로운 람다를 생성하는 람다

자신은 감싸고 있는 유효 범위 변수에 접근 가능

Page 50: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

미리 정의된 함수형 인터페이스● 람다를 사용하려면 항상 인터페이스를 필요할가? ● 람다 사용시 새로운 인터페이스를 매번 만들어야 하나?

Page 51: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

미리 정의된 함수형 인터페이스● 람다를 사용하려면 항상 인터페이스를 필요할가? - yes● 람다 사용시 새로운 인터페이스를 매번 만들어야 하나? - no(반만 yes)

Page 52: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

Car price price > 3000 sum

cars.stream().map(c -> c.gerPrice()).filter(p -> p > 3000).reduce((a, b) -> a + b));

람다를 위해 3개 인터페이스 필요

interface Function interface Predicate interface BinaryOperator

Page 53: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

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

IntPredicateIntSupplierIntToDoubleFunctionIntToLongFunctionIntUnaryOperatorLongBinaryOperatorLongConsumerLongFunction<R>LongPredicateLongSupplierLongToDoubleFunctionLongToIntFunctionLongUnaryOperatorObjDoubleConsumer<T>ObjIntConsumer<T>ObjLongConsumer<T>Predicate<T>Supplier<T>

BiConsumer<T,U>BiFunction<T,U,R>BinaryOperator<T>BiPredicate<T,U>BooleanSupplierConsumer<T>DoubleBinaryOperatorDoubleConsumerDoubleFunction<R>DoublePredicateDoubleSupplierDoubleToIntFunctionDoubleToLongFunctionDoubleUnaryOperatorFunction<T,R>IntBinaryOperatorIntConsumerIntFunction<R>

Page 54: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

지연 연산

Page 55: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

// 디버그 모드에서만 실행public void debug(String message) { if (log.isDebugEnabled()) { log.log(message); }}

debug(some.expensive("operation"));

디버그 모드에서만 동작하는 함수

디버그 모드에서는 동작

Page 56: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

// 디버그 모드에서만 실행public void debug(String message) { if (log.isDebugEnabled()) { log.log(message); }}

debug(some.expensive("operation"));

평가 시점

함수 인자는 호출 시점에 평가가 된다

Page 57: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

// 디버그 모드에서만 실행public void debug(Consumer<String> consumer) { if (log.isDebugEnabled()) { log.log(consumer.accept()); }}

debug(() -> some.expensive("operation"));

람다로 평가 시점 조절

람다를 사용해서 평가를 뒤로 미룬다

Page 58: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

// 람다가 없는 경우debug(some.expensive("operation"));

// 람다 사용debug(() -> some.expensive("operation"));

호출 하는 쪽이 조금 불편해 졌다

Page 59: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

문제 다시 보기● 빌려쓰기 패턴

Page 60: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

public void withFile(String fileName) { BufferedReader bufferedReader = null; try { bufferedReader = new BufferedReader(new FileReader(filename)); String line = null; while ((line = bufferedReader.readLine()) != null) { System.out.println(line); } } catch (IOException ex) { ex.printStackTrace(); } finally { if (bufferedReader != null) bufferedReader.close(); }}

파일을 한 라인씩 읽어서 STDOUT으로 출력

Page 61: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

public void withFile(String fileName) { BufferedReader bufferedReader = null; try { bufferedReader = new BufferedReader(new FileReader(filename)); String line = null; while ((line = bufferedReader.readLine()) != null) { DB.write(line); } } catch (IOException ex) { ex.printStackTrace(); } finally { if (bufferedReader != null) bufferedReader.close(); }}

파일을 한 라인씩 읽어서 DB에 저장

Page 62: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

public void withFile(String fileName) { BufferedReader bufferedReader = null; try { bufferedReader = new BufferedReader(new FileReader(filename)); String line = null; while ((line = bufferedReader.readLine()) != null) { // 이 부분 외 모두 중복! } } catch (IOException ex) { ex.printStackTrace(); } finally { if (bufferedReader != null) bufferedReader.close(); }}

중복 발생!

DB.write(line);

System.out.println(line);

현재 라인으로 무엇인가를 처리

Page 63: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

public void withFile(String fileName) { BufferedReader bufferedReader = null; try { bufferedReader = new BufferedReader(new FileReader(filename)); String line = null; while ((line = bufferedReader.readLine()) != null) { // 이 부분 외 모두 중복! } } catch (IOException ex) { ex.printStackTrace(); } finally { if (bufferedReader != null) bufferedReader.close(); }}

중복 발생!

interface Consumer<T> { void accept(T a); }

DB.write(line);System.out.println(line);

Page 64: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

어떤 값을 받아서 소비한다.

interface Consumer<T> { void accept(T a); }

각 라인을 인자로 넘겨 받아서 소비한다 public void accept(String line) { System.out.println(line); }

Page 65: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

class DBWorker class PrintWorker class DBAndPrintWorker

interface Consumer

클래스로 구현

Page 66: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

interface Consumer<T> { void accept(T a); }

class DBWorker implements Consumer<String> { public void accept(String line) { db.store(line); } }

class PrintWorker implements Consumer<String> { public void accept(String line) { System.out.println(line); } };

class DBAndPrintWorker implements Consumer<String> { public void accept(String line) { db.store(line); System.out.println(line); } };

withFile("input.txt", new DBWorker()); withFile("input.txt", new PrintWorker()); withFile("input.txt", new DBAndPrintWorker());

다양한 종류에 클래스 구현

Page 67: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

interface Consumer<T> { void accept(T a);}

withFile("input.txt", new Consumer<String> { public void accept(String line) { db.store(line); } });

withFile("input.txt", new Consumer<String> { public void accept(String line) { System.out.println(line); } });

withFile("input.txt", new Consumer<String> { public void accept(String line) { db.store(line); System.out.println(line); } });

익명 클래스 사용

Page 68: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

interface Consumer<T> { void accept(T a);}

메서드 딱 1개!

함수형 인터페이스

Page 69: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

withFile("input.txt", new Consumer<String> { public void accept(String line) { db.store(line); } });

withFile("input.txt", new Consumer<String> { public void accept(String line) { System.out.println(line); } });

withFile("input.txt", new Consumer<String> { public void accept(String line) { db.store(line); System.out.println(line); } });

interface Consumer<T> { void accept(T a);}

익명 클래스 사용

Page 70: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

withFile("input.txt", new Consumer<String> { public void accept(String line) { db.store(line); } });

withFile("input.txt", new Consumer<String> { public void accept(String line) { System.out.println(line); } });

withFile("input.txt", new Consumer<String> { public void accept(String line) { db.store(line); System.out.println(line); } });

interface Consumer<T> { void accept(T a);}

중복되는 객체 이름 제거

Page 71: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

withFile("input.txt", new Consumer<String> { public void accept(String line) { db.store(line); } });

withFile("input.txt", new Consumer<String> { public void accept(String line) { System.out.println(line); } });

withFile("input.txt", new Consumer<String> { public void accept(String line) { db.store(line); System.out.println(line); } });

interface Consumer<T> { void accept(T a);}

중복되는 메서드 이름 제거

Page 72: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

withFile("input.txt", new Consumer<String> { public void accept(String line) { db.store(line); } });

withFile("input.txt", new Consumer<String> { public void accept(String line) { System.out.println(line); } });

withFile("input.txt", new Consumer<String> { public void accept(String line) { db.store(line); System.out.println(line); } });

interface Consumer<T> { void accept(T a);}

실제로 다른 부분은 함수 본체

Page 73: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

interface Consumer<T> { void accept(T a);}

람다 사용

withFile("input.txt", line -> db.store);withFile("input.txt", line -> System.out.println);withFile("input.txt", line -> {

db.store(line);System.out.println(line);

});

Page 74: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

interface Consumer<T> { void accept(T a); }

class DBWorker implements Consumer<String> { public void accept(String line) { db.store(line); } }

class PrintWorker implements Consumer<String> { public void accept(String line) { System.out.println(line); } };

class DBAndPrintWorker implements Consumer<String> { public void accept(String line) { db.store(line); System.out.println(line); } };

// 클래스 사용 withFile("input.txt", new DBWorker()); withFile("input.txt", new PrintWorker()); withFile("input.txt", new DBAndPrintWorker());

불필요 코드가 많이 사라짐

// 람다 사용withFile("input.txt", line -> db.store);withFile("input.txt", line -> System.out.println);withFile("input.txt", line -> {

db.store(line);System.out.println(line);

});

Page 75: 2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)

감사합니다. - @blueiur(twitter)