Download - Java8 & Lambda
JAVA����������� ������������������ 8
커머스컨텐츠개발랩����������� ������������������ ����������� ������������������ ����������� ������������������ ����������� ������������������ ����������� ������������������ ����������� ������������������ ����������� ������������������ 황기현
1.����������� ������������������ JAVA8의����������� ������������������ 주요����������� ������������������ 기능����������� ������������������
2.����������� ������������������ Lambda����������� ������������������ Expression
3.����������� ������������������ Lambda����������� ������������������ Syntax
4.����������� ������������������ Stream����������� ������������������ API����������� ������������������
✓ 날짜 및 시간 API
이 새 API를 사용하여 개발자는 더 자연스럽고, 간결하고, 이해하기 쉬운 방식으로 날짜 및
시간을 처리할 수 있다.
✓ Nashorn Javascript 엔진 새로운 경량의 고성능 JavaScript 엔진이 구현되어 JDK에 통합되었으며 기존 API를 통해 JAVA
응용 프로그램에서 이 엔진을 사용할 수 있다.
✓ 향상된 보안 호출자에 의존하는 메소드를 수동으로 유지 관리하는 기존 목록을 이러한 메소드를 정확하게
식별하고 호출자를 안정적으로 검색하는 방식으로 바꾼다.
✓ Lambda 표현식 및 가상 확장 메소드 JAVA8에서 눈에 띄는 기능은 Java 프로그래밍 언어 및 플랫폼에 구현된 람다 표현식 및 지원
기능이다.
JAVA8 의 주요 기능
✓ 날짜 및 시간 API
이 새 API를 사용하여 개발자는 더 자연스럽고, 간결하고, 이해하기 쉬운 방식으로 날짜 및
시간을 처리할 수 있다.
✓ Nashorn Javascript 엔진 새로운 경량의 고성능 JavaScript 엔진이 구현되어 JDK에 통합되었으며 기존 API를 통해 JAVA
응용 프로그램에서 이 엔진을 사용할 수 있다.
✓ 향상된 보안 호출자에 의존하는 메소드를 수동으로 유지 관리하는 기존 목록을 이러한 메소드를 정확하게
식별하고 호출자를 안정적으로 검색하는 방식으로 바꾼다.
✓ Lambda 표현식 및 가상 확장 메소드 JAVA8에서 눈에 띄는 기능은 Java 프로그래밍 언어 및 플랫폼에 구현된 람다 표현식 및 지원
기능이다.
JAVA8 의 주요 기능
✓ 날짜 및 시간 API
이 새 API를 사용하여 개발자는 더 자연스럽고, 간결하고, 이해하기 쉬운 방식으로 날짜 및
시간을 처리할 수 있다.
✓ Nashorn Javascript 엔진 새로운 경량의 고성능 JavaScript 엔진이 구현되어 JDK에 통합되었으며 기존 API를 통해 JAVA
응용 프로그램에서 이 엔진을 사용할 수 있다.
✓ 향상된 보안 호출자에 의존하는 메소드를 수동으로 유지 관리하는 기존 목록을 이러한 메소드를 정확하게
식별하고 호출자를 안정적으로 검색하는 방식으로 바꾼다.
✓ Lambda 표현식 및 가상 확장 메소드 JAVA8에서 눈에 띄는 기능은 Java 프로그래밍 언어 및 플랫폼에 구현된 람다 표현식 및 지원
기능이다.
JAVA8 의 주요 기능
✓ 날짜 및 시간 API
이 새 API를 사용하여 개발자는 더 자연스럽고, 간결하고, 이해하기 쉬운 방식으로 날짜 및
시간을 처리할 수 있다.
✓ Nashorn Javascript 엔진 새로운 경량의 고성능 JavaScript 엔진이 구현되어 JDK에 통합되었으며 기존 API를 통해 JAVA
응용 프로그램에서 이 엔진을 사용할 수 있다.
✓ 향상된 보안 호출자에 의존하는 메소드를 수동으로 유지 관리하는 기존 목록을 이러한 메소드를 정확하게
식별하고 호출자를 안정적으로 검색하는 방식으로 바꾼다.
✓ Lambda 표현식 및 가상 확장 메소드 JAVA8에서 눈에 띄는 기능은 Java 프로그래밍 언어 및 플랫폼에 구현된 람다 표현식 및 지원
기능이다.
JAVA8 의 주요 기능
✓ 날짜 및 시간 API
이 새 API를 사용하여 개발자는 더 자연스럽고, 간결하고, 이해하기 쉬운 방식으로 날짜 및
시간을 처리할 수 있다.
✓ Nashorn Javascript 엔진 새로운 경량의 고성능 JavaScript 엔진이 구현되어 JDK에 통합되었으며 기존 API를 통해 JAVA
응용 프로그램에서 이 엔진을 사용할 수 있다.
✓ 향상된 보안 호출자에 의존하는 메소드를 수동으로 유지 관리하는 기존 목록을 이러한 메소드를 정확하게
식별하고 호출자를 안정적으로 검색하는 방식으로 바꾼다.
✓ Lambda 표현식 및 가상 확장 메소드 JAVA8에서 눈에 띄는 기능은 Java 프로그래밍 언어 및 플랫폼에 구현된 람다 표현식 및 지원
기능이다.
JAVA8 의 주요 기능
Java8은 Lambda 표현식을 받아들이면서
Functional Programming 특징을 갖추게 되어
OOP + FP 의 멀티 패러다임 언어(Multi paradigm language)가 됐다.
Functional Programming(함수형 프로그래밍)이란?
함수형 프로그래밍은 자료 처리를 수학적 함수의 계산으로 취급하고 상태와 가변 데이터를 멀리하는 프로그래
밍 패러다임의 하나이다. 명령형 프로그래밍에서는 상태를 바꾸는 것을 강조하는 것과는 달리, 함수형 프로그래
밍은 함수의 응용을 강조한다.
수학적 함수와 명령형 프로그래밍에서 사용되는 함수는 차이가 있는데, 명령형의 함수는 프로그램의 상태의 값
을 바꿀 수 있는 부작용이 생길 수 있다. 이 때문에 명령형 함수는 참조 투명성이 없고, 같은 코드라도 실행되는
프로그램의 상태에 따라 다른 결과값을 낼 수 있다. 반대로 함수형 코드에서는 함수의 출력 값은 그 함수에 입력
된 인수에만 의존하므로 인수 x에 같은 값을 넣고 함수 f를 호출하면 항상 f(x)라는 결과가 나온다. 부작용을 제
거하면 프로그램의 동작을 이해하고 예측하기가 훨씬 쉽게 된다. 이것이 함수형 프로그래밍으로 개발하려는 핵
심 동기 중 하나이다.
✓ 명령형 언어 : a라는 변수에 1을 담아라. (대입)
✓ 함수형 언어 : a를 1로 정의한다.
a = 1
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
Lambda Syntax(인자 목록 ) -> { 구문 }
( int x, int y ) -> { return x + y; }
(int x, int y ) -> x + y
( ) -> “Hello, World! ”
( x, y ) -> x + y
x - > x + 1
public void adder ( int x, int y ) {
return x + y;
}
( int x, int y ) -> { return x + y; } ( x, y ) -> x + y;
// 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));
⇒ Functional Interface• 단 하나의 추상 메소드를 갖는다.
• 람다 표현으로 사용하기 위해 @FunctionalInterface
주석(annotation)을 붙일 수 있다.
(이 방식이 강력 추천 됨!)
? adder = ( int x, int y ) -> x + y
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 인터페이스이기 때문에 서로 다른 타입으로 구현이 가능하다.
✓ 정의된 것을 사용
Java에서 Lambda 표현식을 사용하는 목적
변수를 직접 전달하여 그 값을 변경함으로써 흐름을 처리하지 않고, 행위 자체
(Behavior Parameter)를 전달함으로써 함수형 프로그램이 지향하는 바를 얻기 위
함.
기존에 이미 익명 클래스(Anonymous Class)를 통해 해결할 수도 있었던 문제지
만, Lambda식을 사용함으로써 코드를 좀 더 깔끔하고 가독성을 높일 수 있다.
즉, “Java에서 Lambda 표현식은 추상 메소드가 하나만 있는 인터페이스를 익명
클래스 대신 구현할 수 있게 해주는 방법”이라고 할 수 있다.
Stream APIJava에서 가장 많이 사용되는 Collection을 파이프라이닝 형태로 다룰 수 있게
해주는 Java8의 새로운 API.
Stream의 특징✓ No Storage - 데이터 보관을 위해 별도의 공간을 마련하지 않고
✓ Immutable - 기본적으로는 원본을 조작하지 않으며
✓ Laziness - 최종적인 결과를 얻을 때 필요한 동작만을 수행하고
✓ Possibly unbounded - 값을 무한히 가질 수도 있으며
✓ Consumable - 1회성이다.
즉, 스트림은 각 원소들을 단 한번만 방문한다.
등록된 상품 중에 현재 판매 중이고, 가격이 십만원 이하인 상품의 개수는?
public class Product {
private int id;private boolean usable;private String category;private int price;
getter / setter ..
}
현재 판매 중이고 십만원 이하인 상품의 개수는?
현재 판매 중이고 십만원 이하인 상품의 개수는?
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); :
}
현재 판매 중이고 십만원 이하인 상품의 개수는?public void filterBeforeJava8() {
int count = 0;
for(Product pd : products) {
if(pd.isUsable() &&
pd.getPrice() <= 100000) {
count++;}
}
System.out.println("현재 판매 중이고 가격이 십만원 이하인 상품의 개수 : " + count + "개 ");
}
상품목록에서 개별 상품을 구해서
현재 판매 중이고 십만원 이하인 상품의 개수는?public void filterBeforeJava8() {
int count = 0;
for(Product pd : products) {
if(pd.isUsable() &&
pd.getPrice() <= 100000) {
count++;}
}
System.out.println("현재 판매 중이고 가격이 십만원 이하인 상품의 개수 : " + count + "개 ");
}
상품목록에서 개별 상품을 구해서
현재 판매 중이고
현재 판매 중이고 십만원 이하인 상품의 개수는?public void filterBeforeJava8() {
int count = 0;
for(Product pd : products) {
if(pd.isUsable() &&
pd.getPrice() <= 100000) {
count++;}
}
System.out.println("현재 판매 중이고 가격이 십만원 이하인 상품의 개수 : " + count + "개 ");
}
상품목록에서 개별 상품을 구해서
현재 판매 중이고
십만원 이하라면
현재 판매 중이고 십만원 이하인 상품의 개수는?public void filterBeforeJava8() {
int count = 0;
for(Product pd : products) {
if(pd.isUsable() &&
pd.getPrice() <= 100000) {
count++;}
}
System.out.println("현재 판매 중이고 가격이 십만원 이하인 상품의 개수 : " + count + "개 ");
}
상품목록에서 개별 상품을 구해서
현재 판매 중이고
십만원 이하라면
개수를 1증가
현재 판매 중이고 십만원 이하인 상품의 개수는?
public void filterJava8() {long count = products.stream()
.filter(p -> p.isUsable()) .filter(p -> p.getPrice() <= 100000) .count();
System.out.println("현재 판매 중이고 가격이 십만원 이하인 상품의 개수 : " + count + "개 ");
}
상품 중에서
현재 판매 중이고 십만원 이하인 상품의 개수는?
public void filterJava8() {long count = products.stream()
.filter(p -> p.isUsable()) .filter(p -> p.getPrice() <= 100000) .count();
System.out.println("현재 판매 중이고 가격이 십만원 이하인 상품의 개수 : " + count + "개 ");
}
상품 중에서판매 중이고
현재 판매 중이고 십만원 이하인 상품의 개수는?
public void filterJava8() {long count = products.stream()
.filter(p -> p.isUsable()) .filter(p -> p.getPrice() <= 100000) .count();
System.out.println("현재 판매 중이고 가격이 십만원 이하인 상품의 개수 : " + count + "개 ");
}
상품 중에서판매 중이고
십만원 이상인 상품의
현재 판매 중이고 십만원 이하인 상품의 개수는?
public void filterJava8() {long count = products.stream()
.filter(p -> p.isUsable()) .filter(p -> p.getPrice() <= 100000) .count();
System.out.println("현재 판매 중이고 가격이 십만원 이하인 상품의 개수 : " + count + "개 ");
}
상품 중에서판매 중이고
십만원 이상인 상품의
개수를 구함
Stream API : 3단계 구성
products.stream().filter(p -> p.isUsable()).count();
스트림 생성 중개 연산 스트림 변환
종단 연산 스트림 사용
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의 배수를 출력
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 )- 각 요소를 확인해서 조건을 통과한 요소만으로 새 스트림 생성- 참 / 거짓을 반환하는 조건식을 인수로 전달
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 )- 각 요소를 인수로 전달된 함수에 전달해 처리- 최종연산이기 때문에 이후 스트림을 사용할 수 없음
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 로 사용
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배 한 후 합계 구하기
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 타입의 요소로 변환 후 스트림 생성- 변환을 처리하는 함수를 인수로 전달
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()
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() - 합계, 평균, 최소값, 최대값, 개수에 대한 요약 통계
// 옵션 타입별 사용중 옵션 반환 : 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
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());
}
Lambda
/** * 최소 옵션가 조회 * LambdaJ -> Lambda * @return 최소옵션가 */public long getLowestOptionPrice() {
// Java8 return getOptionCombinations().stream() .filter(s -> s.isUsable()) .mapToLong(OptionCombination::getPrice) .min() .getAsLong();
}
Lambda 표현식의 장점➢ OOP 언어인 Java에서 함수형 코드를 작성할 수 있게 해준다.
➢람다 표현식을 이용함으로써 간결하고 명확한 코드로 그 의도를
표현할 수 있다.
➢ Collection filtering, Iteration, Extraction 등에서 놀라운
코드 생산성을 보인다.
One more thing…
Lambda와 Closure의 차이
- Closure : 자신이 정의된 영역의 변수를 에워싸고(close over) 있는 것. 또는, 자신이 정의된 영역의 변수에 접근할 수 있는 것.
Closure를 사용하기 위해서 Lambda가 사용된다.
- Lambda : 익명함수 * Lambda는 람다 표현식 또는 람다 함수, 그리고 이름없는 함수(anonymous function)라고 불리우며 그 성질은 “함수 객체와 동일하다”고 할 수 있다.
감사합니다.