Java

[Java 9] 주요 변경내용 : Collection / Optional / Stream 관련 기능, 내부 문자열 처리방식, G1 GC

Collection 정적 팩토리 메서드 추가

  • 자바 9 이전에는 List를 만들기 위해 Arrays.asList(1, 2) 사용
  • Set, Map 등의 타입에 대해서도 new 키워드를 통해 생성 및 초기화 필요했음
  • 자바 9부터는 Collection 관련 인터페이스에 정적 팩토리 메서드 of 추가되어 간결하게 생성 및 초기화 가능
// AS-IS (Java 9 미만)
List<Integer> list = Arrays.asList(1, 2);
Set<Integer> set = new HastSet<>(Arrays.asList(1, 2));
Map<String, Integer> map = new HashMap<>();
map.put("A", 1);
map.put("B", 2);

// TO-BE (Java 9)
List<Integer> list = List.of(1, 2);
Set<Integer> set = Set.of(1, 2);
Map<String, Integer> map = Map.of("A", 1, "B", 2);
Map<String, Integer> map2 = Map.ofEntires(entry("A", 1), entry("B", 2));

 

  • 이 때 of로 만들어진 컬렉션은 모두 불변 (원소 추가/삭제/수정 불가)
  • 기존 불변 Collection을 생성하는 Collections.unmodifiableXX() 과 구현체가 다름
  • Set.of(1, 2)의 경우 기존 내부적으로 HashMap을 거쳐 데이터를 저장하는 방식과 다르게 내부적으로 데이터를 필드에 바로 저장하므로 메모리 효율적

 

Optional 기능 추가

  • ifPresentOrElse() : Optional 내 값이 존재할 때 / 존재하지 않을 때의 메서드를 각각 정의 가능
    • 기존 값이 있는 경우 액션을 정의하는 ifPresent(action) 기능이 확대
public void optional(Optional<String> data) {
    data.ifPresentOrElse(
        s -> System.out.println("값이 있음." + s),
        () -> System.out.println("값이 없음.")
    );
}

 

  • or() : Optional 내 값이 존재하지 않을 때 다른 Optional을 반환
public void optional(Optional<String> data) {
    data.or(() -> Optional.of("New"));
}

 

  • stream() : Optional 내 값이 존재할 때 원소 1개 가진 스트림 / 없을 때 비어있는 스트림으로 변환
public void optional(Optional<String> data) {
    data.stream().forEach(System.out::println);
}

 

 

 

Stream 기능 추가

  • takeWhile() : filter와 비슷한 기능. false가 나오는 순간 뒤의 데이터 모두 버림
public void stream() {
        List<Integer> list = List.of(11, 15, 5, 17, 13, 2);
        list.stream()
                .takeWhile(n -> n > 10)
                .forEach(System.out::println); // 11, 15
}

 

  • dropWhile() : filter와 비슷한 기능. false가 나오는 순간 해당 데이터 및 이후 데이터 모두 남김
public void stream() {
        List<Integer> list = List.of(11, 15, 5, 17, 13, 2);
        list.stream()
                .dropWhile(n -> n > 10)
                .forEach(System.out::println); // 5, 17, 13, 2
}

 

 

  • ofNullable() : 파라미터 값이 null이면 비어있는 스트림, 값이 있으면 원소가 하나인 스트림 반환
  • 개선된 iterate : 기존 iterate에서 limit()이 없으면 무한 스트림에 빠질 수 있어 기존 interate에 종료 조건 추가 가능
public void stream() {
        // AS-IS (Java 9 미만)
        Stream.iterate(0, i -> i + 2)
                .limit(5) // 없으면 무한스트림
                .forEach(System.out::println);

        // TO-Be (Java 9)
        Stream.iterate(0, i -> i < 10, i -> i + 2) // 종료조건 추가 가능
                .forEach(System.out::println);
}

 

 

 

내부 문자열 처리 방식 개선

  • 자바 9 이전에는 문자 저장 시 UTF-16 char 배열을 통해 문자에 상관없이 모두 2byte 사용
  • 자바 9부터는 내부적으로 isLatin1() 메서드를 통해 알파벳인 경우 1byte만 사용하도록 변경
  • 알파벳으로만 이루어진 문자열의 경우 메모리 공간 최대 50% 절약 가능

 

 

default GC => G1 GC로 변경

  • 자바 9 이전에는 Parallel GC가 default GC
    • Serial GC와 기본적인 알고리즘은 같으나, GC를 처리하는 스레드가 여러개
    • Young, Old 영역을 물리적으로 분할
  • 자바 9부터는 G1 GC가 default GC
    • 바둑판 형태의 각 영역에 객체 할당 및 GC 실행
    • 해당 영역이 가득차면 다른 영역에 객체 할당 및 GC 실행
    • Young, Old 영역이 물리적으로 분할되지 않음
    • Region을 일정 크기로 나누어 객체를 할당하고 런타임에 필요에 따라 영역을 튜닝하므로 STW 타임 최소화

 

 

 


Reference

인프런 - 자바 9부터 자바 21까지