Java 8 스트림이 비어 있는지 확인하는 방법
요?Stream
비어있고, 그렇지 않으면 예외를 발생시킬 수 있습니까?
기본적으로 아래의 코드와 동등한 것을 찾고 있습니다만, 중간 스트림을 실현하지 않고 있습니다.특히 터미널 조작에 의해 스트림이 실제로 소비되기 전에는 체크가 실행되지 않아야 합니다.
public Stream<Thing> getFilteredThings() {
Stream<Thing> stream = getThings().stream()
.filter(Thing::isFoo)
.filter(Thing::isBar);
return nonEmptyStream(stream, () -> {
throw new RuntimeException("No foo bar things available")
});
}
private static <T> Stream<T> nonEmptyStream(Stream<T> stream, Supplier<T> defaultValue) {
List<T> list = stream.collect(Collectors.toList());
if (list.isEmpty()) list.add(defaultValue.get());
return list.stream();
}
많은 경우 이 정도면 충분합니다.
stream.findAny().isPresent()
다른 답변과 코멘트는 스트림의 내용을 조사하려면 터미널 조작을 추가하여 스트림을 "소비"해야 한다는 점에서 정확합니다.그러나 이를 통해 스트림의 전체 내용을 버퍼링하지 않고 결과를 스트림으로 되돌릴 수 있습니다.다음은 몇 가지 예입니다.
static <T> Stream<T> throwIfEmpty(Stream<T> stream) {
Iterator<T> iterator = stream.iterator();
if (iterator.hasNext()) {
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), false);
} else {
throw new NoSuchElementException("empty stream");
}
}
static <T> Stream<T> defaultIfEmpty(Stream<T> stream, Supplier<T> supplier) {
Iterator<T> iterator = stream.iterator();
if (iterator.hasNext()) {
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), false);
} else {
return Stream.of(supplier.get());
}
}
기본적으로 스트림을 변환합니다.Iterator
hasNext()
에 '인 '참'인 경우 '참'을 .Iterator
로 Stream
의 Iterator(Iterator)를 통과하기 hasNext()
★★★★★★★★★★★★★★★★★」next()
또한 스트림은 (나중에 병렬로 변환되더라도) 효과적으로 순차적으로 처리된다는 것을 의미합니다.단, 모든 요소를 버퍼링하지 않고 스트림을 테스트할 수 있습니다.
을 은 아마 거예요.Spliterator
Iterator
이를 통해 반환된 스트림은 병렬 실행을 포함하여 입력 스트림과 동일한 특성을 가질 수 있습니다.
제한된 병렬 기능을 사용할 수 있는 경우 다음과 같은 솔루션이 작동합니다.
private static <T> Stream<T> nonEmptyStream(
Stream<T> stream, Supplier<RuntimeException> e) {
Spliterator<T> it=stream.spliterator();
return StreamSupport.stream(new Spliterator<T>() {
boolean seen;
public boolean tryAdvance(Consumer<? super T> action) {
boolean r=it.tryAdvance(action);
if(!seen && !r) throw e.get();
seen=true;
return r;
}
public Spliterator<T> trySplit() { return null; }
public long estimateSize() { return it.estimateSize(); }
public int characteristics() { return it.characteristics(); }
}, false);
}
다음으로 이를 사용하는 코드 예를 제시하겠습니다.
List<String> l=Arrays.asList("hello", "world");
nonEmptyStream(l.stream(), ()->new RuntimeException("No strings available"))
.forEach(System.out::println);
nonEmptyStream(l.stream().filter(s->s.startsWith("x")),
()->new RuntimeException("No strings available"))
.forEach(System.out::println);
는 (의) 입니다.Spliterator
에는, 어느쪽인가의 fragment가 스레드 세이프한 방법으로 값을 인식했는지 아닌지를 통지하는 스레드 세이프한 방법이 필요합니다. 후, 「」를 실행하고 있는 .tryAdvance
적절한 예외를 발생시킬 수 있는 마지막 사람이라는 것을 깨달아야 합니다(또한 진행되지도 못했습니다).그래서 나는 여기서 갈라지는 것에 대한 지원을 추가하지 않았다.
필터를 적용하려면 스트림에서 터미널 작업을 수행해야 합니다.따라서 소비하기 전에는 비어있을지 알 수 없습니다.
입니다.findAny()
어떤 요소가 발견되면 정지되지만 존재하지 않으면 모든 입력 목록에서 반복하여 검출해야 합니다.
스트림이 비어 있지 않은 것을 알기 전에 목록의 작은 서브셋만 소비해야 하므로 입력 목록에 많은 요소가 있고 처음 몇 개 중 하나가 필터를 통과한 경우에만 도움이 됩니다.
물론 출력 목록을 작성하려면 새 스트림을 생성해야 합니다.
부울 맵을 만들기에 충분할 것 같습니다.
코드에서는 다음과 같습니다.
boolean isEmpty = anyCollection.stream()
.filter(p -> someFilter(p)) // Add my filter
.map(p -> Boolean.TRUE) // For each element after filter, map to a TRUE
.findAny() // Get any TRUE
.orElse(Boolean.FALSE); // If there is no match return false
Stuart의 아이디어에 따라, 이 작업을 수행할 수 있습니다.Spliterator
다음과 같습니다.
static <T> Stream<T> defaultIfEmpty(Stream<T> stream, Stream<T> defaultStream) {
final Spliterator<T> spliterator = stream.spliterator();
final AtomicReference<T> reference = new AtomicReference<>();
if (spliterator.tryAdvance(reference::set)) {
return Stream.concat(Stream.of(reference.get()), StreamSupport.stream(spliterator, stream.isParallel()));
} else {
return defaultStream;
}
}
병렬 스트림과 함께 사용할 수 있습니다.stream.spliterator()
작업을 수행하면 스트림이 종료되고 필요에 따라 재구축됩니다.
사용 예에서는 기본값이 필요했습니다.Stream
디폴트값이 아닌이것이 당신이 필요로 하는 것이 아니라면, 그것은 꽤 쉽게 바꿀 수 있다.
간단하게 다음 항목을 사용합니다.
stream.count()>0
스트림을 소비하거나 반복기로 변환하지 않는 가장 간단한 솔루션은 다음과 같습니다.
public Stream<Thing> getFilteredThings() {
AtomicBoolean found = new AtomicBoolean(false);
Stream<Thing> stream = getThings().stream()
.filter(Thing::isFoo)
.filter(Thing::isBar)
.forEach(x -> {
found.set(true);
// do useful things
})
;
if (!found.get()) {
throw new RuntimeException("No foo bar things available");
}
}
개선점을 자유롭게 제안해 주십시오.
언급URL : https://stackoverflow.com/questions/26649062/how-to-check-if-a-java-8-stream-is-empty
'sourcecode' 카테고리의 다른 글
javax.validation 입니다.확인예외:HV000183:'javax.el'을 로드할 수 없습니다.Expression Factory ' (0) | 2022.11.07 |
---|---|
"wait_timeout"이 감소했음에도 불구하고 MariaDB 프로세스 목록에서 sleep 상태의 쿼리 수가 다수 감소함 (0) | 2022.11.07 |
SQL에서 다른 테이블의 테이블에 데이터 삽입 (0) | 2022.11.06 |
bash: pip: 명령을 찾을 수 없습니다. (0) | 2022.11.06 |
목록 인스턴스 방법 (0) | 2022.11.06 |