java8 & lambda

44
JAVA 8 커머스컨텐츠개발랩 황기현

Upload: -

Post on 14-Aug-2015

133 views

Category:

Engineering


7 download

TRANSCRIPT

Page 1: Java8 & Lambda

JAVA����������� ������������������  8

커머스컨텐츠개발랩����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  황기현

Page 2: Java8 & Lambda

1.����������� ������������������  JAVA8의����������� ������������������  주요����������� ������������������  기능����������� ������������������  

2.����������� ������������������  Lambda����������� ������������������  Expression

3.����������� ������������������  Lambda����������� ������������������  Syntax

4.����������� ������������������  Stream����������� ������������������  API����������� ������������������  

Page 3: Java8 & Lambda

✓ 날짜 및 시간 API

이 새 API를 사용하여 개발자는 더 자연스럽고, 간결하고, 이해하기 쉬운 방식으로 날짜 및

시간을 처리할 수 있다.

✓ Nashorn Javascript 엔진 새로운 경량의 고성능 JavaScript 엔진이 구현되어 JDK에 통합되었으며 기존 API를 통해 JAVA

응용 프로그램에서 이 엔진을 사용할 수 있다.

✓ 향상된 보안 호출자에 의존하는 메소드를 수동으로 유지 관리하는 기존 목록을 이러한 메소드를 정확하게

식별하고 호출자를 안정적으로 검색하는 방식으로 바꾼다.

✓ Lambda 표현식 및 가상 확장 메소드 JAVA8에서 눈에 띄는 기능은 Java 프로그래밍 언어 및 플랫폼에 구현된 람다 표현식 및 지원

기능이다.

JAVA8 의 주요 기능

Page 4: Java8 & Lambda

✓ 날짜 및 시간 API

이 새 API를 사용하여 개발자는 더 자연스럽고, 간결하고, 이해하기 쉬운 방식으로 날짜 및

시간을 처리할 수 있다.

✓ Nashorn Javascript 엔진 새로운 경량의 고성능 JavaScript 엔진이 구현되어 JDK에 통합되었으며 기존 API를 통해 JAVA

응용 프로그램에서 이 엔진을 사용할 수 있다.

✓ 향상된 보안 호출자에 의존하는 메소드를 수동으로 유지 관리하는 기존 목록을 이러한 메소드를 정확하게

식별하고 호출자를 안정적으로 검색하는 방식으로 바꾼다.

✓ Lambda 표현식 및 가상 확장 메소드 JAVA8에서 눈에 띄는 기능은 Java 프로그래밍 언어 및 플랫폼에 구현된 람다 표현식 및 지원

기능이다.

JAVA8 의 주요 기능

Page 5: Java8 & Lambda

✓ 날짜 및 시간 API

이 새 API를 사용하여 개발자는 더 자연스럽고, 간결하고, 이해하기 쉬운 방식으로 날짜 및

시간을 처리할 수 있다.

✓ Nashorn Javascript 엔진 새로운 경량의 고성능 JavaScript 엔진이 구현되어 JDK에 통합되었으며 기존 API를 통해 JAVA

응용 프로그램에서 이 엔진을 사용할 수 있다.

✓ 향상된 보안 호출자에 의존하는 메소드를 수동으로 유지 관리하는 기존 목록을 이러한 메소드를 정확하게

식별하고 호출자를 안정적으로 검색하는 방식으로 바꾼다.

✓ Lambda 표현식 및 가상 확장 메소드 JAVA8에서 눈에 띄는 기능은 Java 프로그래밍 언어 및 플랫폼에 구현된 람다 표현식 및 지원

기능이다.

JAVA8 의 주요 기능

Page 6: Java8 & Lambda

✓ 날짜 및 시간 API

이 새 API를 사용하여 개발자는 더 자연스럽고, 간결하고, 이해하기 쉬운 방식으로 날짜 및

시간을 처리할 수 있다.

✓ Nashorn Javascript 엔진 새로운 경량의 고성능 JavaScript 엔진이 구현되어 JDK에 통합되었으며 기존 API를 통해 JAVA

응용 프로그램에서 이 엔진을 사용할 수 있다.

✓ 향상된 보안 호출자에 의존하는 메소드를 수동으로 유지 관리하는 기존 목록을 이러한 메소드를 정확하게

식별하고 호출자를 안정적으로 검색하는 방식으로 바꾼다.

✓ Lambda 표현식 및 가상 확장 메소드 JAVA8에서 눈에 띄는 기능은 Java 프로그래밍 언어 및 플랫폼에 구현된 람다 표현식 및 지원

기능이다.

JAVA8 의 주요 기능

Page 7: Java8 & Lambda

✓ 날짜 및 시간 API

이 새 API를 사용하여 개발자는 더 자연스럽고, 간결하고, 이해하기 쉬운 방식으로 날짜 및

시간을 처리할 수 있다.

✓ Nashorn Javascript 엔진 새로운 경량의 고성능 JavaScript 엔진이 구현되어 JDK에 통합되었으며 기존 API를 통해 JAVA

응용 프로그램에서 이 엔진을 사용할 수 있다.

✓ 향상된 보안 호출자에 의존하는 메소드를 수동으로 유지 관리하는 기존 목록을 이러한 메소드를 정확하게

식별하고 호출자를 안정적으로 검색하는 방식으로 바꾼다.

✓ Lambda 표현식 및 가상 확장 메소드 JAVA8에서 눈에 띄는 기능은 Java 프로그래밍 언어 및 플랫폼에 구현된 람다 표현식 및 지원

기능이다.

JAVA8 의 주요 기능

Page 8: Java8 & Lambda

Java8은 Lambda 표현식을 받아들이면서

Functional Programming 특징을 갖추게 되어

OOP + FP 의 멀티 패러다임 언어(Multi paradigm language)가 됐다.

Functional Programming(함수형 프로그래밍)이란?

함수형 프로그래밍은 자료 처리를 수학적 함수의 계산으로 취급하고 상태와 가변 데이터를 멀리하는 프로그래

밍 패러다임의 하나이다. 명령형 프로그래밍에서는 상태를 바꾸는 것을 강조하는 것과는 달리, 함수형 프로그래

밍은 함수의 응용을 강조한다.

수학적 함수와 명령형 프로그래밍에서 사용되는 함수는 차이가 있는데, 명령형의 함수는 프로그램의 상태의 값

을 바꿀 수 있는 부작용이 생길 수 있다. 이 때문에 명령형 함수는 참조 투명성이 없고, 같은 코드라도 실행되는

프로그램의 상태에 따라 다른 결과값을 낼 수 있다. 반대로 함수형 코드에서는 함수의 출력 값은 그 함수에 입력

된 인수에만 의존하므로 인수 x에 같은 값을 넣고 함수 f를 호출하면 항상 f(x)라는 결과가 나온다. 부작용을 제

거하면 프로그램의 동작을 이해하고 예측하기가 훨씬 쉽게 된다. 이것이 함수형 프로그래밍으로 개발하려는 핵

심 동기 중 하나이다.

Page 9: Java8 & Lambda

✓ 명령형 언어 : a라는 변수에 1을 담아라. (대입)

✓ 함수형 언어 : a를 1로 정의한다.

a = 1

Page 10: Java8 & Lambda

Lambda Expression람다식은 메서드와 유사

형식 매개변수의 목록과 이 매개변수로 표현된 본문(식이나 코드 블록)을 제공

A lambda expression is like a method : it provides a list of formal parameters and a body - an expression or block - expressed in terms of those parameters.

- jsr335, /spec/B.html

Page 11: Java8 & Lambda

Lambda Syntax(인자 목록 ) -> { 구문 }

( int x, int y ) -> { return x + y; }

(int x, int y ) -> x + y

( ) -> “Hello, World! ”

( x, y ) -> x + y

x - > x + 1

Page 12: Java8 & Lambda

public void adder ( int x, int y ) {

return x + y;

}

( int x, int y ) -> { return x + y; } ( x, y ) -> x + y;

Page 13: Java8 & Lambda

// Java8 이전 Collections.sort(strings, new Comparator<String>() {

@Overridepublic int compare(String s1, String s2) {

return s1.compareTo(s2);}

});

// Java8Collections.sort(strings, (s1, s2) -> s1.compareTo(s2));

Page 14: Java8 & Lambda

⇒ Functional Interface• 단 하나의 추상 메소드를 갖는다.

• 람다 표현으로 사용하기 위해 @FunctionalInterface

주석(annotation)을 붙일 수 있다.

(이 방식이 강력 추천 됨!)

? adder = ( int x, int y ) -> x + y

Lambda의 타입은?

Page 15: Java8 & Lambda

@FunctionalInterface public interface IAddable<T> {

// To add two objects public T add(T t1, T t2);

}

IAddable<String> stringAdder = (String s1, String s2) -> s1 + s2;IAddable<Integer> intAdder = (i1, i2) -> i1 + i2;

public void addStrings(String s1, String s2) {System.out.println(stringAdder.add(s1, s2));

}public void addIntegers(Integer i1, Integer i2) {

System.out.println(intAdder.add(i1, i2));}

✓ 인터페이스 정의

✓ 람다 표현식을 이용하여 Functional Interface 구현IAddable이 generic type 인터페이스이기 때문에 서로 다른 타입으로 구현이 가능하다.

✓ 정의된 것을 사용

Page 16: Java8 & Lambda

Java에서 Lambda 표현식을 사용하는 목적

변수를 직접 전달하여 그 값을 변경함으로써 흐름을 처리하지 않고, 행위 자체

(Behavior Parameter)를 전달함으로써 함수형 프로그램이 지향하는 바를 얻기 위

함.

기존에 이미 익명 클래스(Anonymous Class)를 통해 해결할 수도 있었던 문제지

만, Lambda식을 사용함으로써 코드를 좀 더 깔끔하고 가독성을 높일 수 있다.

즉, “Java에서 Lambda 표현식은 추상 메소드가 하나만 있는 인터페이스를 익명

클래스 대신 구현할 수 있게 해주는 방법”이라고 할 수 있다.

Page 17: Java8 & Lambda

Stream APIJava에서 가장 많이 사용되는 Collection을 파이프라이닝 형태로 다룰 수 있게

해주는 Java8의 새로운 API.

Stream의 특징✓ No Storage - 데이터 보관을 위해 별도의 공간을 마련하지 않고

✓ Immutable - 기본적으로는 원본을 조작하지 않으며

✓ Laziness - 최종적인 결과를 얻을 때 필요한 동작만을 수행하고

✓ Possibly unbounded - 값을 무한히 가질 수도 있으며

✓ Consumable - 1회성이다.

즉, 스트림은 각 원소들을 단 한번만 방문한다.

Page 18: Java8 & Lambda

등록된 상품 중에 현재 판매 중이고, 가격이 십만원 이하인 상품의 개수는?

Page 19: Java8 & Lambda

public class Product {

private int id;private boolean usable;private String category;private int price;

getter / setter ..

}

현재 판매 중이고 십만원 이하인 상품의 개수는?

Page 20: Java8 & Lambda

현재 판매 중이고 십만원 이하인 상품의 개수는?

public void setProduct() {Product p1 = new Product(1, true, "fashion", 50000);Product p2 = new Product(2, true, "fashion", 38000);Product p3 = new Product(3, true, "it", 250000);Product p4 = new Product(4, true, "it", 85000);Product p5 = new Product(5, true, "it", 99000);Product p6 = new Product(6, true, "it", 75000);Product p7 = new Product(7, true, "furniture", 350000);Product p8 = new Product(8, false, "furniture", 210000);Product p9 = new Product(9, false, "furniture", 58000);Product p10 = new Product(10, false, "it", 120000);

products.add(p1);products.add(p2); :

}

Page 21: Java8 & Lambda

현재 판매 중이고 십만원 이하인 상품의 개수는?public void filterBeforeJava8() {

int count = 0;

for(Product pd : products) {

if(pd.isUsable() &&

pd.getPrice() <= 100000) {

count++;}

}

System.out.println("현재 판매 중이고 가격이 십만원 이하인 상품의 개수 : " + count + "개 ");

}

상품목록에서 개별 상품을 구해서

Page 22: Java8 & Lambda

현재 판매 중이고 십만원 이하인 상품의 개수는?public void filterBeforeJava8() {

int count = 0;

for(Product pd : products) {

if(pd.isUsable() &&

pd.getPrice() <= 100000) {

count++;}

}

System.out.println("현재 판매 중이고 가격이 십만원 이하인 상품의 개수 : " + count + "개 ");

}

상품목록에서 개별 상품을 구해서

현재 판매 중이고

Page 23: Java8 & Lambda

현재 판매 중이고 십만원 이하인 상품의 개수는?public void filterBeforeJava8() {

int count = 0;

for(Product pd : products) {

if(pd.isUsable() &&

pd.getPrice() <= 100000) {

count++;}

}

System.out.println("현재 판매 중이고 가격이 십만원 이하인 상품의 개수 : " + count + "개 ");

}

상품목록에서 개별 상품을 구해서

현재 판매 중이고

십만원 이하라면

Page 24: Java8 & Lambda

현재 판매 중이고 십만원 이하인 상품의 개수는?public void filterBeforeJava8() {

int count = 0;

for(Product pd : products) {

if(pd.isUsable() &&

pd.getPrice() <= 100000) {

count++;}

}

System.out.println("현재 판매 중이고 가격이 십만원 이하인 상품의 개수 : " + count + "개 ");

}

상품목록에서 개별 상품을 구해서

현재 판매 중이고

십만원 이하라면

개수를 1증가

Page 25: Java8 & Lambda

현재 판매 중이고 십만원 이하인 상품의 개수는?

public void filterJava8() {long count = products.stream()

.filter(p -> p.isUsable()) .filter(p -> p.getPrice() <= 100000) .count();

System.out.println("현재 판매 중이고 가격이 십만원 이하인 상품의 개수 : " + count + "개 ");

}

상품 중에서

Page 26: Java8 & Lambda

현재 판매 중이고 십만원 이하인 상품의 개수는?

public void filterJava8() {long count = products.stream()

.filter(p -> p.isUsable()) .filter(p -> p.getPrice() <= 100000) .count();

System.out.println("현재 판매 중이고 가격이 십만원 이하인 상품의 개수 : " + count + "개 ");

}

상품 중에서판매 중이고

Page 27: Java8 & Lambda

현재 판매 중이고 십만원 이하인 상품의 개수는?

public void filterJava8() {long count = products.stream()

.filter(p -> p.isUsable()) .filter(p -> p.getPrice() <= 100000) .count();

System.out.println("현재 판매 중이고 가격이 십만원 이하인 상품의 개수 : " + count + "개 ");

}

상품 중에서판매 중이고

십만원 이상인 상품의

Page 28: Java8 & Lambda

현재 판매 중이고 십만원 이하인 상품의 개수는?

public void filterJava8() {long count = products.stream()

.filter(p -> p.isUsable()) .filter(p -> p.getPrice() <= 100000) .count();

System.out.println("현재 판매 중이고 가격이 십만원 이하인 상품의 개수 : " + count + "개 ");

}

상품 중에서판매 중이고

십만원 이상인 상품의

개수를 구함

Page 29: Java8 & Lambda

Stream API : 3단계 구성

products.stream().filter(p -> p.isUsable()).count();

스트림 생성 중개 연산 스트림 변환

종단 연산 스트림 사용

Page 30: Java8 & Lambda

List<Integer> numbers = Arrays.asList(1,2,3,4,5,6,7,8,9,10);

public static void filter(List<Integer> numbers) {numbers.stream()

.filter(value -> value % 3 == 0) .forEach(System.out::println);

}

3의 배수를 출력

Page 31: Java8 & Lambda

List<Integer> numbers = Arrays.asList(1,2,3,4,5,6,7,8,9,10);

public static void filter(List<Integer> numbers) {numbers.stream()

.filter(value -> value % 3 == 0) .forEach(System.out::println);

}

3의 배수를 출력

중개 연산 : Stream <T> filter ( T -> boolean )- 각 요소를 확인해서 조건을 통과한 요소만으로 새 스트림 생성- 참 / 거짓을 반환하는 조건식을 인수로 전달

Page 32: Java8 & Lambda

List<Integer> numbers = Arrays.asList(1,2,3,4,5,6,7,8,9,10);

public static void filter(List<Integer> numbers) {numbers.stream()

.filter(value -> value % 3 == 0) .forEach(System.out::println);

}

3의 배수를 출력

최종 연산 : void forEach ( T -> void )- 각 요소를 인수로 전달된 함수에 전달해 처리- 최종연산이기 때문에 이후 스트림을 사용할 수 없음

Page 33: Java8 & Lambda

List<Integer> numbers = Arrays.asList(1,2,3,4,5,6,7,8,9,10);

public static void filter(List<Integer> numbers) {numbers.stream()

.filter(value -> value % 3 == 0) .forEach(System.out::println);

}

3의 배수를 출력

메소드 참조 : 람다 표현식의 다른 형태 class :: method 로 사용

Page 34: Java8 & Lambda

List<Integer> numbers = Arrays.asList(1,2,3,4,5,6,7,8,9,10);

public static void map(List<Integer> numbers) {int sum = numbers.stream()

.mapToInt(value -> value * 2) .sum();

System.out.println("Sum : " + sum);}

리스트의 모든 값을 2배 한 후 합계 구하기

Page 35: Java8 & Lambda

List<Integer> numbers = Arrays.asList(1,2,3,4,5,6,7,8,9,10);

public static void map(List<Integer> numbers) {int sum = numbers.stream()

.mapToInt(value -> value * 2) .sum();

System.out.println("Sum : " + sum);}

리스트의 모든 값을 2배 한 후 합계 구하기

중개 연산 : Stream <R> map ( T -> R )- T 타입의 요소를 1:1로 R 타입의 요소로 변환 후 스트림 생성- 변환을 처리하는 함수를 인수로 전달

Page 36: Java8 & Lambda

List<Integer> numbers = Arrays.asList(1,2,3,4,5,6,7,8,9,10);

public static void map(List<Integer> numbers) {int sum = numbers.stream()

.mapToInt(value -> value * 2) .sum();

System.out.println("Sum : " + sum);}

리스트의 모든 값을 2배 한 후 합계 구하기

최종 연산 : sum(), average(), min(), max()- 합계 : [ int, long, double ] sum() - 평균 : OptionalDouble average()- 최소값 : Optional[ Int, Long, Double ] min()- 최대값 : Optional[ Int, Long, Double ] max()

Page 37: Java8 & Lambda

List<Integer> numbers = Arrays.asList(1,2,3,4,5,6,7,8,9,10);

public static void statistics(List<Integer> numbers) {IntSummaryStatistics stats = numbers.stream()

.mapToInt(value -> value * 2) .summaryStatistics();

System.out.println("Sum : " + stats.getSum());System.out.println("Average : " + stats.getAverage());System.out.println("Max Value : " + stats.getMax());System.out.println("Min Value : " + stats.getMin());

}

리스트의 모든 값을 2배 한 후 합계, 평균, 최대 / 최소값 구하기

최종 연산 : summaryStatistics()- [ Int, Long, Double ] SummaryStatistics summaryStatstics() - 합계, 평균, 최소값, 최대값, 개수에 대한 요약 통계

Page 38: Java8 & Lambda

// 옵션 타입별 사용중 옵션 반환 : JAVA8 이전private List<Option> getUsableOptionsByType(OptionType type) { return select(this.options,

having(on(Option.class).isUsable(), equalTo(true)).and(having(on(Option.class).getOptionType(),

equalTo(type))));

}

// 옵션 타입별 사용중 옵션 반환 : JAVA8 private List<Option> getUsableOptionsByType(OptionType type) { return options.stream()

.filter(o -> o.isUsable())

.filter(o -> type == o.getOptionType())

.collect(Collectors.toList());

}

LambdaJ

Page 39: Java8 & Lambda

LambdaJ

/** * 최소 옵션가 조회 * LambdaJ -> Lambda * @return 최소옵션가 */public long getLowestOptionPrice() {

// Java8 이전 : LambdaJ 사용 List<OptionCombination> activeOptionCombinations =

select(getOptionCombinations(), having(on(OptionCombination.class).isUsable(), equalTo(true)));

return min(activeOptionCombinations, on(OptionCombination.class).getPrice());

}

Page 40: Java8 & Lambda

Lambda

/** * 최소 옵션가 조회 * LambdaJ -> Lambda * @return 최소옵션가 */public long getLowestOptionPrice() {

// Java8 return getOptionCombinations().stream() .filter(s -> s.isUsable()) .mapToLong(OptionCombination::getPrice) .min() .getAsLong();

}

Page 41: Java8 & Lambda

Lambda 표현식의 장점➢ OOP 언어인 Java에서 함수형 코드를 작성할 수 있게 해준다.

➢람다 표현식을 이용함으로써 간결하고 명확한 코드로 그 의도를

표현할 수 있다.

➢ Collection filtering, Iteration, Extraction 등에서 놀라운

코드 생산성을 보인다.

Page 42: Java8 & Lambda

One more thing…

Page 43: Java8 & Lambda

Lambda와 Closure의 차이

- Closure : 자신이 정의된 영역의 변수를 에워싸고(close over) 있는 것. 또는, 자신이 정의된 영역의 변수에 접근할 수 있는 것.

Closure를 사용하기 위해서 Lambda가 사용된다.

- Lambda : 익명함수 * Lambda는 람다 표현식 또는 람다 함수, 그리고 이름없는 함수(anonymous function)라고 불리우며 그 성질은 “함수 객체와 동일하다”고 할 수 있다.

Page 44: Java8 & Lambda

감사합니다.