1. 개요

이 사용방법(예제)에서는 Java 컬렉션에서 null-safe 스트림을 만드는 방법을 배웁니다.

이 자료를 완전히 이해하려면 Java 8의 메서드 참조, 람다 식, 선택적 및 스트림 API에 대한 어느 정도의 지식이 필요합니다.

이러한 주제에 익숙하지 않은 경우 이전 기사 인 Java 8의 새로운 기능 , Java 8 사용방법(예제) 옵션Java 8 스트림 소개를 먼저 살펴볼 수 있습니다 .

2. 메이븐 의존성

시작하기 전에 특정 시나리오에 필요한 Maven 의존성이 하나 있습니다.

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-collections4</artifactId>
    <version>4.2</version>
</dependency>

commons-collections4 라이브러리 는 Maven Central에서 다운로드할 수 있습니다.

3. 컬렉션에서 스트림 만들기

모든 유형의 Collection 에서 Stream 을 생성하는 기본 접근 방식은 필요한 스트림 유형에 따라 컬렉션에서 stream() 또는 parallelStream() 메서드 를 호출하는 것 입니다.

Collection<String> collection = Arrays.asList("a", "b", "c");
Stream<String> streamOfCollection = collection.stream();

우리 컬렉션은 어느 시점에서 외부 소스를 가질 가능성이 큽니다. 컬렉션에서 스트림을 생성할 때 아래와 유사한 방법으로 끝날 것입니다.

public Stream<String> collectionAsStream(Collection<String> collection) {
    return collection.stream();
}

이로 인해 몇 가지 문제가 발생할 수 있습니다. 제공된 컬렉션이 null 참조를 가리키면 코드는  런타임 에 NullPointerException 을 발생시킵니다.

다음 섹션에서는 이를 방지하는 방법을 설명합니다.

4. 생성된 컬렉션 스트림을 Null-Safe로 만들기

4.1. Null 역참조 를 방지하기 위한 검사 추가

의도하지 않은 null 포인터 예외 를 방지하기 위해 컬렉션에서 스트림을 생성할 때 null  참조 를 방지하는 검사를 추가하도록 선택할 수 있습니다 .

Stream<String> collectionAsStream(Collection<String> collection) {
    return collection == null 
      ? Stream.empty() 
      : collection.stream();
}

그러나 이 방법에는 몇 가지 문제가 있습니다.

첫째, null 검사는 비즈니스 논리를 방해하여 프로그램의 전반적인 가독성을 떨어뜨립니다.

둘째, 값이 없음을 나타내기 위해 null 을 사용하는 것은 Java SE 8 이후의 잘못된 접근 방식으로 간주됩니다. 값의 부재 및 존재를 모델링하는 더 좋은 방법이 있습니다.

빈 Collection 은 null  Collection 과 같지 않다는  점을 기억하는 것이 중요합니다 . 첫 번째는 쿼리에 표시할 결과나 요소가 없음을 나타내는 반면 두 번째는 프로세스 중에 일종의 오류가 발생했음을 나타냅니다.

4.2. CollectionUtils 라이브러리 에서 emptyIfNull 메소드 사용

Apache Commons의 CollectionUtils 라이브러리를 사용하여 스트림이 null 로부터 안전한지 확인할 수 있습니다. 이 라이브러리는 null 컬렉션을 인수로 지정하거나 컬렉션 자체를 인수로 지정하여 변경할 수 없는 빈 컬렉션을 반환하는 emptyIfNull 메서드를 제공합니다.

public Stream<String> collectionAsStream(Collection<String> collection) {
    return emptyIfNull(collection).stream();
}

이것은 채택하기에 매우 간단한 전략입니다. 그러나 외부 라이브러리에 따라 다릅니다. 소프트웨어 개발 정책이 그러한 라이브러리의 사용을 제한하는 경우 이 솔루션은 무효 가 됩니다.

4.3. Java 8의 선택 사항 사용

Java SE 8의 선택 사항 은 값을 포함하거나 포함하지 않는 단일 값 컨테이너입니다. 값이 누락된 경우 선택적 컨테이너가 비어 있다고 합니다.

선택 사항 을 사용 하는 것은 스트림에서 null-safe 컬렉션을 만드는 가장 좋은 전체 전략으로 간주될 수 있습니다.

어떻게 사용할 수 있는지 살펴보고 아래에서 간단히 논의해 보겠습니다.

public Stream<String> collectionToStream(Collection<String> collection) {
    return Optional.ofNullable(collection)
      .map(Collection::stream)
      .orElseGet(Stream::empty);
}
  • Optional.ofNullable(collection) 은 전달된 컬렉션에서 Optional 객체를생성합니다컬렉션이 null 이면 빈 Optional 개체가 생성됩니다
  • map(Collection::stream) 은 optional 객체에 포함된 값을 map 메서드( Collection.stream() ) 에 대한 인수로추출합니다.
  • orElseGet(Stream::empty) 는 Optional 객체가 비어 있는 경우, 즉 전달된 컬렉션이 null 인 경우 폴백 값을 반환합니다.

결과적으로 의도하지 않은 포인터 예외로부터 코드를 사전에 보호합니다.

4.4. Java 9의 Nullable 스트림 사용

섹션 4.1의 이전 삼항 예제를 검토하고 일부 요소가 Collection 대신 null 일 수 있는 가능성을 고려 하면 Stream  클래스 에 ofNullable 메서드를  마음대로 사용할 수 있습니다.

위의 예를 다음과 같이 변환할 수 있습니다.

Stream<String> collectionAsStream(Collection<String> collection) {  
  return collection.stream().flatMap(s -> Stream.ofNullable(s));
}

5. 결론

이 기사에서는 주어진 컬렉션에서 스트림을 만드는 방법에 대해 간략하게 설명했습니다. 그런 다음 생성된 스트림이 컬렉션에서 생성될 때 null-safe인지 확인하기 위한 세 가지 주요 전략을 탐색했습니다.

마지막으로 각 전략을 적절하게 사용할 때의 단점을 지적했습니다.

평소와 같이 기사와 함께 제공되는 전체 소스 코드는 GitHub 에서 사용할 수 있습니다 .

Generic footer banner