참고
자바 8~11 에서 무슨 일이 일어나고 있는가?
역사의 흐름은 무엇인가?
NOTE
자바 8에서는 매우 큰 변화가 일어났다!!
// 고전적인 코드
Collections.sort(inventory, new Comparator<Apple>() {
public int compare(Apple a1, Apple a2) {
return a1.getWeight().compareTo(a2.getWeight());
}
});
// Java 8
inventory.sort(comparing(Apple::getWeight));
Java
복사
자바8을 이용해 코드가 획기적으로 간단해졌다!
병렬처리 → 멀티 코어를 활용하는 방법!
•
멀티코어 CPU의 대중화와 같은 하드웨어의 변화가 자바8에 영향을 미쳤다.
◦
지금까지의 대부분 자바 프로그램은 코어 중 하나만을 사용했다.
◦
나머지 코어는 유휴상태이거나, 다른 프로그램과 나눠서 사용됨
•
자바 8이 등장하기전에는 나머지 코어를 활용하려면 스레드를 사용하는게 권장되었다.
◦
하지만 스레드를 관리하는건 매우 어려운일이다.
•
자바 8이 등장하고 병렬 실행을 새롭고 단순한 방식으로 접근할 수 있게된다.
◦
자바 9에서는 리액티브 프로그래밍이라는 병렬 실행 기법 지원
◦
고성능 병렬 시스템에서 특히 인기를 얻는 RxJava를 표준적 방식으로 지원한다.
자바 8의 새로운 기술
•
스트림 처리
◦
스트림 → 한 번에 한 개씩 만들어지는 연속적인 데이터항목의 모임
◦
코드가 동시에 실행될 때 안전하게 실행되려면, 공유된 가변 데이터에 접근하면 안된다.
◦
자바8에서는 스트림을 이용해서 기존 자바 스레드보다 쉽게 병렬성을 처리한다.
•
메서드에 코드를 전달하는 기법 (메서드 참조, 람다)
•
인터페이스의 디폴트 메서드
자바 함수(일급시민)
NOTE
자바8에서는 함수를 새로운 값의 형식으로 추가했다!
•
멀티코어에서 병렬 프로그래밍을 활용할 수 있는 스트림과 연계될 수 있도록 함수를 만들었기 때문
•
함수를 값처럼 취급하면 어떤점이 좋은가?
◦
프로그래밍 언어의 핵심은 값을 바꾸는 것 → 이 값을 일급 시민이라고한다.
◦
기존의 이급 객체인 메서드, 클래스, 등을 일급 시민으로 만들 수 있다면, 즉 런타임에 메서드를 전달할 수 있다면 프로그래밍에서 유용하게 활용가능!
메서드 참조
class Chain{
public static void staticChain(String s1, String s2) {
System.out.println(s1+", "+s2);
}
public void instanceChain(String s1, String s2) {
System.out.println(s1+", "+s2);
}
}
Java
복사
사용한 클래스와 메서드
BiConsumer<String, String> consumer;
// 정적(static) 메소드 참조
consumer= (s1,s2) -> Chain.staticChain(s1,s2); // 람다식
consumer = Chain::staticChain; // 메소드 참조
consumer.accept("static", "method");
// instance 메소드 참조
Chain chain = new Chain();
consumer = (s1,s2) -> chain.instanceChain(s1,s2); // 람다식
consumer = chain::instanceChain; //메소드 참조
consumer.accept("instance", "method");
Java
복사
클래스::메서드 형식으로 사용한다
함수 넘겨주기
// 자바 8 이전 (요구조건마다 함수생성)
public static List<Apple> filterGreenApples(List<Apple> inventory) {
List<Apple> result = new ArrayList<>();
for (Apple apple : inventory) {
if ("green".equals(apple.getColor())) {
result.add(apple);
}
}
return result;
}
public static List<Apple> filterHeavyApples(List<Apple> inventory) {
List<Apple> result = new ArrayList<>();
for (Apple apple : inventory) {
if (apple.getWeight() > 150) {
result.add(apple);
}
}
return result;
}
// 자바 8 이후 (함수를 인자로 받음)
public static List<Apple> filterApples(List<Apple> inventory, Predicate<Apple> p) {
List<Apple> result = new ArrayList<>();
for (Apple apple : inventory) {
if (p.test(apple)) {
result.add(apple);
}
}
return result;
}
// 사용한 함수
public static boolean isGreenApple(Apple apple) {
return "green".equals(apple.getColor());
}
public static boolean isHeavyApple(Apple apple) {
return apple.getWeight() > 150;
}
Java
복사
함수를 인자값으로 쓰는 경우와 하지 않는 경우
// 자바 8 이전(다른 필터링을 하려면 함수를 복붙해서 고쳐야함)
filterGreenApples(inventory)
filterHeavyApples(inventory)
// 자바 8 이후 (필요한 함수를 인자값으로 넘겨줌)
fileterApples(inventory, Apple::isGreenApple);
fileterApples(inventory, Apple::isHeavyApple);
Java
복사
메서드 전달 → 람다
filterApples(inventory, (Apple a) -> "green".equals(a.getColor()));
filterApples(inventory, (Apple a) -> a.getWeight() > 150);
filterApples(inventory, (Apple a) -> a.getWeight() < 80 || "brown".equals(a.getColor()));
Java
복사
함수를 선언하지 않고 람다로 사용하는 경우!
스트림
NOTE
외부반복 (for-each), 내부반복 비교
•
외부 반복
◦
기존 컬렉션 API는 for-each 루프를 통한 반복 과정을 직접 처리했다.
◦
단일 CPU만 이용하여 순차적 처리
•
내부 반복
◦
스트림 API는 루프를 신경 쓸 필요가 없다.
◦
내부 반복 방식을 이용해서 API 내부에서 모두 처리가 되기 때문
◦
멀티 CPU를 이용하여 병렬로 처리한다.
디폴트 메서드와 자바 모듈
NOTE
자바8에서는 인터페이스를 쉽게 바꾸기 위해 이폴트 메서드를 지원한다!
default void sort(Comparator<? super E> C) {
Collections.sort(this, c);
}
Java
복사
자바8에서 List에 직접 sort가 가능해진건 다음과 같이 추가했기 때문