CHAP21 - Modern-Java-in-Action/Online-Study GitHub Wiki
- 자바 8의 기능과 자바 8이 프로그래밍 형식에 가져올 변화
- 새로운 자바 9 모듈 시스템
- 6개월 주기의 점진적 자바 릴리스 생명주기
- 첫 번째 점진적 릴리스 자바 10
- 미래 자바 버전에 추가되리라 기대하는 기능
- 자바 8에 추가된 대부분 기능 -> 함수형 프로그래밍을 쉽게 적용할 수 있도록 도와줌
- 큰 변화가 생긴 이유
- 개별 CPU 코어 속도가 빨라지며 병렬 실행시 코드 실행 속도 향상 가능
- 간결하게 데이터 컬렉션을 처리하기 위함(불변 객체, 불변 컬렉션)
- 함수형 프로그래밍에서 지원하는 메서드로 코드 블록을 전달하는 기법
// Apple에 Predicate의 test에 해당하는 isGreenApple, isHeavyApple 구현
public class Apple {
public boolean isGreenApple() {
return GREEN.equals(color);
}
public boolean isHeavyApple() {
return weight > 150;
}
}
// Predicate를 파라미터로 받는다
public List<Apple> filterApples(List<Apple> inventory, Predicate<Apple> applePredicate) {
List<Apple> result = new ArrayList<>();
for(Apple apple : inventory) {
if(applePredicate.test(apple)) {
result.add(apple);
}
}
return result;
}
// stream의 filter를 이용하면 더 간결하게 표현 가능
public List<Apple> filterApplesForStream(List<Apple> inventory, Predicate<Apple> applePredicate) {
return inventory.stream().filter(applePredicate::test).collect(Collectors.toList());
}
// 다른 결과를 가져올 수 있음
List<Apple> greenApples = filterApples(inventory, Apple::isGreenApple);
List<Apple> heavyApples = filterApples(inventory, Apple::isHeavyApple);
또는 람다 표현식(lambda expression)을 이용하여 표현
List<Apple> redApples = filterApples(inventory, (Apple apple) -> RED.equals(apple.getColor()));
List<Apple> heavyApples2 = filterApples(inventory, (Apple apple) -> apple.getWeight() > 150);
- 스트림 API는 파이프라인이라는 게으른 형식의 연산을 사용
- 큰 데이터 집합일수록 스트림의 데이터 처리 방식이 효율적이며, 메모리 캐시 등의 관점에서도 탐색 횟수를 최소화 하는 것이 중요함
- parallel 메서드로 스트림을 병렬로 처리
/*
* 1. 통화별로 트랜잭션을 그룹화한 다음에 해당 통화로 일어난 모든 트랜잭션 합계를 계산하시오(Map<Currency, Integer>)
* 2. 트랜잭션을 비싼 트랜잭션과 저렴한 트랜잭션 두 그룹으로 분류하시오(Map<Boolean, List<Transaction>>)
*/
// Collection 버전
Map<Currency, List<Transaction>> transactionsByCurrencies = new HashMap<>();
for (Transaction transaction : transactions) {
Currency currency = transaction.getCurrency();
List<Transaction> transactionsForCurrency = transactionsByCurrencies.get(currency);
if (transactionsForCurrency == null) {
transactionsForCurrency = new ArrayList<>();
transactionsByCurrencies.put(currency, transactionsForCurrency);
}
transactionsForCurrency.add(transaction);
}
// Stream(함수형 프로그래밍) 버전
Map<Currency, List<Transaction>> transactionsByCurrencies2 = transactions.stream().collect(groupingBy(Transaction::getCurrency));
- 자바5의 Future 인터페이스 : 여러 작업이 동시에 실행될 수 있도록 다른 스레드나 코어로 작업을 할당 가능(멀티코어 활용)
- Future와 관련된 공통 디자인 패턴을 함수형 프로그래밍으로 간결하게 표현할 수 있도록 thenCompose, thenCombine, allOf 등을 제공
- 명령형에서 발생하는 불필요한 코드 감소효과
- T 형식의 값을 반환하거나 Optional.empty(값이 없음)라는 정적 메서드를 반환할 수 있는 Optional<T> 클래스
- 값이 없을 때 에러를 발생시킬 수 있는 null 대신 정해진 데이터 형식을 제공
// BEFORE
String name = null;
if(insurance != null){
name = insurance.getName();
}
// AFTER
Optional<Insurance> optInsurance = Optional.ofNullable(insurance);
Optional<String> name = optInsurance.map(Insurance::getName);
- 참고 : Java Optional 바르게 쓰기
- 자바9의 리액티브 스트림, 리액티브 당김 기반 역압력 프로토폴 표준화
- Flow API는 호환성을 높일 수 있도록 라이브러리가 구현할 수 있는 네 개의 인터페이스 Publisher, Subscriber, Subscription, Processor 포함
- 인터페이스 설계자가 메서드의 기본 구현을 제공 가능
- 인터페이스 구현 클래스들이 새로 추가된 기능을 구현하지 않아도 됨
// 상속과 관련된 문제가 있음..
public interface A {
default void hello {
print A
}
}
public interface B extends A {
default void hello {
print B
}
}
public class C implements B, A {
public static void main(String... args) {
new C().hello(); // print B
}
}
- 자바 9에서 추가된 내용
- 스트림의 takeWhile, dropWhile 추가
- CompletableFuture의 completeOnTimeout 추가
- 모듈 시스템 - module-info.java 파일 추가
- 다른 릴리스에 비해 과거 호환성을 해쳤다는 의견
- 모듈화라는 장점을 얻기 위한 불가피한 희생
- 자바 모듈 시스템이 제공하는 장점
- 안정적 설정
- 강한 캡슐화
- 보안성 개선
- 성능 개선
- 확장성
- 자바7 : 변수가 메서드를 정의할 때 컨텍스트로 형식을 유추할 수 있는 상황에서는 생략 가능
Map<String, List<String>> myMap = new HashMap<String, List<String>>();
-> Map<String, List<String>> myMap = new HashMap<>();
- 자바10 : 로컬변수 선언을 var를 이용하여 컴파일러에게 타입을 추론하게할 수 있도록 함
var list = new ArrayList<String>(); // infers ArrayList<String>
var stream = list.stream(); // infers Stream<String>
var numbers = List.of(1, 2, 3, 4, 5);
for (var number : numbers) {
System.out.println(number);
}
for (var i = 0; i < numbers.size(); i++) {
System.out.println(numbers.get(i));
}
- 참고 : Java10 신규 기능(특징) 정리
- String 클래스의 새로운 메서드
- isBlank, lines, strip, stripLeading, stripTrailing, repeat
String multilineString = "Baeldung helps \n \n developers \n explore Java.";
List<String> lines = multilineString.lines()
.filter(line -> !line.isBlank())
.map(String::strip)
.collect(Collectors.toList());
assertThat(lines).containsExactly("Baeldung helps", "developers", "explore Java.");
- Files 클래스에 readString, writeString 추가
Path filePath = Files.writeString(Files.createTempFile(tempDir, "demo", ".txt"), "Sample text");
String fileContent = Files.readString(filePath);
assertThat(fileContent).isEqualTo("Sample text");
- 컬랙션의 toArray() 메서드를 오버로딩하는 메서드 추가 -> 원하는 타입의 배열 선택 가능
List<String> sampleList = Arrays.asList("Java", "Kotlin");
String[] sampleArray = sampleList.toArray(String[]::new);
- Predicate 인터페이스에 not 메서드 추가
- 자바 컴파일없이 실행 가능
# before
$ javac HelloWorld.java
$ java HelloWorld
Hello Java 8!
# after
$ java HelloWorld.java
Hello Java 11
- 참고 : Java8과 Java11의 특징
지금까지 배움이라는 여행을 즐겼길 바란다.
그리고 앞으로 일어날 자바의 진화를 살펴보는 데 더 많은 관심이 생겼길 희망한다