How to check if a Java 8 Stream is empty?
If you can live with limited parallel capablilities, the following solution will work:
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);
}
Here is some example code using it:
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);
The problem with (efficient) parallel execution is that supporting splitting of the Spliterator
requires a thread-safe way to notice whether either of the fragments has seen any value in a thread-safe manner. Then the last of the fragments executing tryAdvance
has to realize that it is the last one (and it also couldn’t advance) to throw the appropriate exception. So I didn’t add support for splitting here.
Java - Check Not Null/Empty else assign default value
If using JDK 9 +, use Objects.requireNonNullElse(T obj, T defaultObj)
Do we need to check if a Stream in java 8 if it is null and not iterate
No, it's not necessary¹.
As long as you use empty Streams instead of null (for example as method parameters), everything works just fine. You don't need to check if a Stream
is empty, just like you don't need to check if a Collection
is empty, if you use empty collections instead of nulls in your code (and you should).
¹ Now this is assuming "original" streams coming from a continuous source (collection, generator). You can easily create a null-containing Stream with something like map(o -> o.getPossiblyNull())
. In this case you may want to use .filter(Objects::nonNull)
to remove any null elements from the Stream.
Java Lambda - check if an ArrayList to Stream is empty
Stream.findFirst
returns an Optional
, its up to you to check if the optional has a value rather than just calling get.
You could use the orElse
method to return a default value if the optional is empty.
Checking if a list is empty in java 8
You are asking an obsolete question. Streams process all elements of a source, hence, if there are no elements, no action will be taken. Therefore, you don’t need to check whether the list is empty.
Still, you can simplify your code:
list.stream().filter(Objects::nonNull)
.map(listElement -> listElement.getCandyType())
.forEach(candyType -> Assert.assertEquals(ValueType.CANDY, candyType));
or
Assert.assertTrue(list.stream().filter(Objects::nonNull)
.map(listElement -> listElement.getCandyType())
.allMatch(Predicate.isEqual(ValueType.CANDY));
allMatch
follows the rules required for this check. If there are no elements, there is no contradicting element, hence all match. Note that listElement -> listElement.getCandyType()
also can be replaced by a method reference of the form ClassName::getCandyType
; I didn’t do it here as I don’t know the correct class name.
There is no performance difference between both variants. allMatch
will return immediately when encountering the first non-matching element, and assertEquals
will throw on the first non matching element. In the second case, the stack trace won’t show artifacts of the stream API implementation.
The second one is preferred when you provide checks for production code rather than unit tests and allow to turn these checks off, as with the Java Language assert
feature, e.g.
assert list.stream().filter(Objects::nonNull)
.map(listElement -> listElement.getCandyType())
.allMatch(Predicate.isEqual(ValueType.CANDY));
as this form guarantees that there will be no overhead when assertions are turned off, whereas the first variant, having an assert
statement with the forEach
action may still cause iterating over all elements and performing the intermediate steps of the pipeline.
if stream().filter is empty
I would suggest creating a constructor for Foo
accepting name
.
You can then extract the name with default value of Optional
:
Foo foo = dep.getFoo()
.stream()
.filter(f -> f.getName().equals(doo.getName))
.findAny().orElse(new Foo("Exp"));
user.setFoo(foo);
As Holger cleverly noticed using orElseGet
would avoid executing the Supplier
in case the Optional
is not empty (beneficial if the computation is complex or side effects occur):
Foo foo = dep.getFoo()
.stream()
.filter(f -> f.getName().equals(doo.getName))
.findAny().orElseGet(() -> new Foo("Exp"));
user.setFoo(foo);
Since java 11 you can use ifPresentOrElse
:
dep.getFoo()
.stream()
.filter(f -> f.getName().equals(doo.getName))
.findAny()
.ifPresentOrElse(user::setFoo, () -> user.setFoo(new Foo("Exp")));
P.S.: If you cannot create the constructor, you can just create the method to provide it and use it in the above snippet:
public static Foo defaultFoo() {
Foo foo = new Foo();
foo.setName("Exp");
return foo;
}
Java 8 stream operation on empty list
collect
is a terminal operation, so it must be evaluated.
When terminating a Stream
pipeline with collect(Collectors.toList())
, you'll always get an output List
(you'll never get null
). If the Stream
is empty (and it doesn't matter if it's empty due to the source of the stream being empty, or due to all the elements of the stream being filtered out prior to the terminal operation), the output List
will be empty too.
Null safe Collection as Stream in Java 8
You can use org.apache.commons.collections4.CollectionUtils::emptyIfNull function:
import static org.apache.commons.collections4.CollectionUtils.emptyIfNull;
emptyIfNull(list).stream()
.filter(...);
Java 8 throw exception if stream returns no results
You could try this:
Collection<Foo> foo = blah.stream().filter(somePredicate)
.collect(Collectors.collectingAndThen(Collectors.toList(), Optional::of))
.filter(l -> !l.isEmpty())
.orElseThrow(() -> new Exception("blah"))
Note that comparing to your code this allocates an extra Optional
instance.
Related Topics
Converting Exponential Value in Java to a Number Format
How to Resolve Java.Lang.Noclassdeffounderror: Javax/Xml/Bind/Jaxbexception
Parse Xml to Java Pojo in Efficient Way
The Import Org.Junit Cannot Be Resolved
How to Create Comma Separated String in Single Quotes from Arraylist of String in Java
How to Replace Dot (.) in a String in Java
Eclipse No Tests Found Using Junit 5 Caused by Noclassdeffounderror for Launcherfactory
Kafka: How to Delete Records from a Topic Using Java API
Java.Time.Format.Datetimeparseexception: Text Could Not Be Parsed At Index 3
Java.Lang.Noclassdeffounderror: Com/Fasterxml/Jackson/Databind/Exc/Invaliddefinitionexception
Update Elements in a Jsonobject
Refactor Multiple If' Statements in Java-8
Gson Expected Begin_Array But Was String At Line 1 Column 62
How to Access Variable Outside a Try Catch Block
How to Call an Excel Vba Macro from Java Code
In Java How to Extract Exact Domain Name from Url