BackEnd/Java

Java 9. 주요 변경 내용 (2)

hanseom 2024. 12. 4. 23:00
반응형

Collection 기능 추가

  Collection 객체를 생성하는 간결한 방법이 추가되었습니다.

// Java 9 이전
List<Integer> oldList = Arrays.asList(1, 2);

// Java 9 이후 정적 팩토리 메소드 of가 생겼습니다.
List<Integer> newList = List.of(1, 2);

// Set
Set<Integer> oldSet = new HashSet<>(Arrays.asList(1, 2));

Set<Integer> newSet = Set.of(1, 2);

// Map
Map<String, Integer> oldMap = new HashMap<>();
oldMap.put("A", 1);
oldMap.put("B", 2);

Map<String, Integer> newMap = Map.of("A", 1, "B", 2);
// key-value가 많다면 ofEntries를 사용할 수도 있습니다.
Map.ofEntries(entry("A", 1), entry("B", 2));

  of로 만들어진 컬렉션은 불변의 특징을 가지고 있습니다. 즉, 원소를 추가, 삭제, 업데이트하려 하면 에러가 발생합니다. 또한, 기존에 불변 컬렉션을 만들기 위해 사용했던 Collections.unmodifiableXX()와 구현체가 다르기 때문에 조금 더 메모리 효율적인 구조를 가지고 있습니다.

 

Optional

  • ifPresentOrElse: 기존 ifPresent(action) 기능에서 값이 없는 경우에도 제어가 가능한 기능입니다.
public static void optional(Optional<String> str) {
  str.ifPresentOrElse(
    s -> System.out.println("값이 있으면 출력: " + s),
    () -> {
      // 값이 없으면 출력하지 않습니다.
    }
  );
}

 

  • or: 체이닝을 통해 값이 없을 경우 다른 Optional로 변환해주는 기능입니다.
public static void optional(Optional<Integer> optionalNum) {
  Optional<Integer> num = optionalNum
    .or(() -> Optional.of(3));
}

 

  • stream: Optional 안에 값이 있으면 원소 1개의 Stream, 값이 없으면 비어 있는 Stream으로 변환해주는 기능입니다.
public static void optional(Optional<Integer> str) {
  Stream<Integer> stream = str.stream();
}

 

Stream

  • takeWhile: filter와 비슷한 기능으로 false가 나오는 순간 뒤의 데이터는 모두 버립니다.
Stream.of(10, 5, 15, 3, 20)
  .takeWhile(num -> num <= 10)
  .collect(Collectors.toList());
// 15를 만나는 순간 뒤의 데이터는 모두 버립니다.

 

  • dropWhile: takeWhile과 비슷하지만 반대로 동작합니다. 즉, 조건이 true인 경우 데이터를 버리고 false를 만나면 모두 남깁니다.
Stream.of(10, 5, 15, 3, 20)
  .dropWhile(num -> num <= 10)
  .collect(Collectors.toList());
// 10, 5는 버리고 15가 나오는 순간 뒤의 데이터를 모두 남깁니다.

 

  • ofNullable: null이면 비어 있는 Stream, 값이 있으면 원소가 하나인 Stream을 생성합니다.
Stream.ofNullable("ABC");

 

  • Stream.iterate(): 기존 iterate()에서 제약조건을 추가할 수 있게 되었습니다.
// 기존
Stream.iterate(0, i -> i + 2)
  .limit(5) // limit이 없으면 무한 스트림이 됩니다.
  .forEach(System.out::println);
  
// 개선된 Stream.iterate()은 제약조건을 넣을 수 있습니다.
Stream.iterate(0, i -> i < 10, i -> i + 2)
  .forEach(System.out::println);

 

CompletableFuture API

  Java 8의 CompletableFuture에 다음과 같은 기능들이 추가되었습니다.

  • CompletableFuture 복사 기능
  • default Executor를 가져오는 기능
  • 타임아웃 / 지연 실행 기능

 

Process API

  운영 체제 프로세스를 제어하고 관리하기 위한 Process API가 개선되었습니다.

  • Process: 프로세스 자체를 표현합니다.
  • ProcessHandle: 프로세스를 제어하는 기능들이 존재합니다.
  • ProcessHandle.Info: 프로세스 관련 세부 정보를 제공합니다.

 

StackWalker API

  해당 시점의 스택 프레임을 제어하는 기능이 추가되었습니다.

public class Main {
  public static void main(String[] args) {
    callA();
  }
  private static void callA() {
    callB();
  }
  private static void callB() {
    callC();
  }
  
  private static void callC() {
    List<String> walk = StackWalker.getInstance()
        .walk(s -> s.map(StackWalker.StackFrame::getMethodName)
            .collect(Collectors.toList()));
    for (String s : walk) {
      System.out.println("Stack : " + s);
    }
  }
}

/* [실행결과]
Stack : callC
Stack : callB
Stack : callA
Stack : main
*/

 

Compact Strings

  Java 9에서는 String 클래스의 내부 표현 방식이 char[] 배열에서 byte[] 배열로 변경되었습니다. 문자열이 Latin-1 문자만 포함하는 경우 1바이트로, 그 외의 경우 2바이트로 저장됩니다. 이를 통해 메모리 사용량을 최대 50%까지 줄일 수 있습니다.

 

Flow API

  리액티브 프로그래밍 지원을 위한 Flow API가 추가 되었습니다. Flow API란 리액티브 스트림즈 인터페이스가 JDK 표준으로 들어온 것입니다.

  • 리액티브 핵심철학: https://www.reactivemanifesto.org/
  • 리액티브 스트림즈: 리액티브 프로그래밍을 위한 라이브러리 표준 (인터페이스)
  • 리액티브 프로그래밍: 응답이 빠르고, 탄력성과 회복성이 좋으며, 메시지 기반으로 통신하는 비동기 non-blocking 방식의 프로그래밍
  • Sample Code
  RxJava reactor Flow API
JDK 버전 8 미만에서 사용 가능 8 이상에서만 사용 가능 9 이상에서만 사용 가능
활용 클라이언트 Spring Webflux 호환성, 표준 라이브러리
리액티브 스트림즈 약간 다르다 완전히 동일 완전히 동일

 

반응형