
출처 : https://newrelic.com/resources/report/2022-state-of-java-ecosystem
현재 Java는 Java SE 19 (2022년 9월 출시)에 이어 Java SE 20 (2023년 3월) 출시를 앞두고 있고 2023년 9월에는 4번째 LTS 버전인 Java SE 21을 출시할 예정이다. 많은 소프트웨어/애플리케이션과 솔루션들이 Java 8 혹은 Java 11로 되어 있지만, 국내에서 많이 사용중인 Spring의 Spring Framework 6 그리고 Spring Boot 3의 Java Baseline이 Java 17로 지정되었다. 기업들에서 Java 8, 11을 고집하고 있지만 머지 않아 급격한 Version Upgrade를 진행할 것이다. 아니면, Java 8의 LTS 지원 종료 시기인 2030년 12월 31일까지 사용할 수도 있다. (ㅋㅋㅋ)
본인 회사도 Java 8로 개발을 진행하고 있지만, 미래를 위해 Java 8, 11, 17 그리고 21까지 정리를 시작한다!
Java 8에서는 int, double 같은 기본값과 객체의 참조 값에 더해 함수를 새로운 값의 형식으로 추가하였다.
객체의 참조처럼 메서드의 참조를 만들어 전달할 수 있다.
아래는 숨겨진 파일들을 가져오는 예제이다.
-- 이전
File[] hiddenFiles = new File(".").listFiles(new FileFilter() {
public boolean accept(File file) {
return file.isHidden();
}
});
-- Method Reference
File[] hiddenFiles = new File(".").listFiles(File::isHidden);
람다 또는 익명 함수를 포함하여 함수도 값으로 취급할 수 있다.
-- Ramda
File[] hiddenFiles = new File(".").listFiles(file -> file.isHidden);
인수(argument)로 값을 받아 true / false로 반환하는 함수형 인터페이스이다.
외부에서 만들어진 컴포넌트들을 이용하여 시스템을 구축하려면 보통 자바 패키지 집합을 포함하는 JAR 파일을 제공받았다. 이러한 패키지의 Interface를 바꿔야 하는 상황에서는 Interface를 구현하는 모든 Class의 구현을 바꿔야 했다.
Java 8은 Interface를 쉽게 바꾸기 위한 Default Method를 지원한다.
default void sort(Comparator<? super E> c) {
Collections.sort(this, c);
}
Java Application은 Collection을 만들고 for-each 루프를 이용하여 각 요소를 반복하면서 Collection API로 동작을 수행한다. 이를 Stream API를 이용하면 루프를 신경 쓰지 않고 모든 요소를 처리할 수 있다.
아래는 리스트에서 고가의 거래(Transaction)만 필터링한 다음에 통화(Currency)로 결과를 그룹화하는 예제이다.
-- 이전
Map<Currency, List<Transaction>> transactionByCurrencies = new HashMap<>();
for (Transaction transaction : transactions) {
if (transaction.getPrice() > 1000) {
Currency currency = transaction.getCurrency();
List<Transaction> transactionsForCurrency = transactionsByCurrencies.get(currency);
if (transactionsForCurrency == null) {
transactionsForCurrency = new ArrayList<>();
transactionsForCurrencies.put(currency, transactionsForCurrency);
}
transactionsForCurrency.add(transaction);
}
}
-- Stream API
Map<Currency, List<Transaction>> transactionByCurrencies =
transactions
.stream()
.filter((Transaction t) -> t.getPrice() > 1000)
.collect(groupingBy(Transaction::getCurrency));
또한, Stream API로 Stream 내의 요소를 쉽게 병렬로 처리할 수 있다. Collection을 필터링할 수 있는 가장 빠른 방법은 Collection을 Stream으로 바꾸고, 병렬로 처리한 다음에 List로 다시 복원하는 것이다.
-- 순차 처리
List<Apple> heavyApples = inventory.steram().filter((Apple a) -> a.getWeight() > 150).collect(toList());
-- 병렬 처리
List<Apple> heavyApples = inventory.paralleStream().filter((Apple a) -> a.getWeight() > 150).collect(toList());