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 에서 사용할 수 있습니다 .