Java 8 bug with Stream.of()-like stream and concatenating them? [duplicate] - java

This question already has answers here:
Java 8 Stream IllegalStateException: Stream has already been operated on or closed
(6 answers)
Closed 4 years ago.
Why is the following java 8 code showing a bug at the second call to get()?
Stream<String> aStream = Stream.concat(Stream.of("A"), Stream.of("B"));
String a = stream.findFirst().get();
String b = stream.findFirst().get();
The "aStream" stream should see two values: "A" and "B". However, trying to read anything, after the first element has already been consumed, gives
java.lang.IllegalStateException: stream has already been operated upon or closed
Isn't it a bug in Java 8? First, why doesn't a consumed Stream.of()-created stream return an Optional with isPresent()==false? Second, why doesn't Stream.concatenate() correctly concatenate such Stream.of()-created streams?

Stream.concatenate() does concatenate the two Streams. However, once you execute a terminal operation of the combined Stream - stream.findFirst() - you can't do anything else with that Stream. You can only run one terminal operation of a Stream. That's why it's called "terminal".
If you want to obtain more than one element of the combined Stream, use a different terminal operation, such as collect:
List<String> list = stream.collect(Collectors.toList());
To clarify, the combined Stream is a single Stream<String>, not a Stream of Streams. Therefore findFirst() consumes the entire combined Stream, not just the first Stream that was uses to create the combined Stream.

Because Stream.findFirst() is a terminal operation, and terminal operations can only be run once on a given stream.

Related

Is it possible to create and infinite stream without limiting the size? [duplicate]

This question already has answers here:
How to create an infinite stream with Java 8
(4 answers)
How to create an infinite Stream<E> out of an Iterator<E>?
(4 answers)
Closed 1 year ago.
Can we create a Java stream with an infinite source of data (e.g. Health signals)?
Yes.
Of course, limiting the size would cause the stream to be finite.
With, for example, Stream.generate(() -> "tick") you have an infinite stream.
However, the actual implementation heavily depends on the shape of the source. If, for instance, for heart beats, I expect the stream coming from some external device, so then you'll need to setup the transmission as well.

Reusing Streams in Java 8 [duplicate]

This question already has answers here:
Java 8 Stream IllegalStateException: Stream has already been operated on or closed
(6 answers)
Closed 6 years ago.
I need to calculate the ratio of two parts of the big List, wherein the first part contains the second:
Stream<Element> part1 = list.stream().filter(x -> x.getN1() < x.getN2);
int result = part1.filter(y -> y.isRight()).count() / part1.count();
But this code throws the Exception: java.lang.IllegalStateException: stream has already been operated upon or closed
Can I write a code without creating the same part1 stream in result?
You can only reuse a collection as it has memoriation of results.
List<Element> part1 = list.stream().filter(x -> x.getN1() < x.getN2).collect(toList());
double result = (double) part1.stream().filter(y -> y.isRight()).count() / part1.size();
A Stream is a builder for some code which is optimised at run time. It's execution isn't as dynamic as it appears.
Streams are not supposed to be reused, or if you want something seemed to it, you can use suppliers as mentioned here : Copy a stream to avoid "stream has already been operated upon or closed" (java 8)

Stream has already been operated upon or closed - Java 8 [duplicate]

This question already has answers here:
Why is this java Stream operated upon twice?
(4 answers)
Closed 6 years ago.
Why I have next exception?
Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed
at java.util.stream.AbstractPipeline.<init>(AbstractPipeline.java:203)...
com.search.offer.OffersSelector.isGood(OffersSelector.java:23)
How change the code to fix it?
Stream<String> titleExclusions = ResourceUtility.contentToUtf8TreeSet("+.txt").
stream().filter(item -> item.length() == 0).collect(Collectors.toSet()).stream();
//...
titleExclusions.filter(tittle::contains).collect(Collectors.toSet()).size() == 0;//line 23
You can't operate on Streams more than once so you are better off using Collections as these can be used more than once.
Set<String> titleExclusions = ResourceUtility.contentToUtf8TreeSet("+.txt")
.stream()
.filter(item -> !item.isEmpty())
.collect(Collectors.toSet());
// uses titleExclusions
boolean noMatches = titleExclusions.stream()
.noneMatch(tittle::contains);
// uses titleExclusions again.
Note: I assume you wanted the non-blank lines from your source file instead of the sets of blank ones. filter takes a Predicate of what is retained rather than what is discarded.
Thank you #Holger for simplifying the second statement.

Java 8 stream to file [duplicate]

This question already has an answer here:
Modify file using Files.lines
(1 answer)
Closed 7 years ago.
Suppose I have a java.util.stream.Stream of objects with some nice toString method:
What's the shortest/most elegant solution to write this stream to a file, one line per stream element?
For reading, there is the nice Files.lines method, so I thought there must be a symmetric method for writing to file, but could not find one.
Files.write only takes an iterable.
Probably the shortest way is to use Files.write along with the trick which converts the Stream to the Iterable:
Files.write(Paths.get(filePath), (Iterable<String>)stream::iterator);
For example:
Files.write(Paths.get("/tmp/numbers.txt"),
(Iterable<String>)IntStream.range(0, 5000).mapToObj(String::valueOf)::iterator);
If it looks too hackish, use more explicit approach:
try(PrintWriter pw = new PrintWriter(Files.newBufferedWriter(
Paths.get("/tmp/numbers.txt")))) {
IntStream.range(0, 5000).mapToObj(String::valueOf).forEach(pw::println);
}
If you have stream of some custom objects, you can always add the .map(Object::toString) step to apply the toString() method.

Is there a way to find the first element to match a Predicate? [duplicate]

This question already has answers here:
Find first element by predicate
(8 answers)
Closed 8 years ago.
With Java 8+, you can easily find all elements of a collection that match a Predicate.
someCollection.stream().filter(somePredicate)
You could then find the first element:
someCollection.stream().filter(somePredicate).findFirst()
The problem with this, though, is that it runs the Predicate against all the elements. Is there a clean way to only run the Predicate against elements until the first match is found, and then return it, like anyMatch does (but returns a boolean telling if one was found)?
It does exactly what you want. It doesn't run over all the elements. The filter method creates a stream and on top of it findFirst creates another stream.
So when you try to get the element of the stream that was created after findFirst() you'll get only the first one that matches the predicate.
Best way to check that is to add a print line or something like that inside the predicate.
Create a stream of integers for example from 0 to 10 and create a predicate that prints the number and then checks if it's divided by 3. You'll get this printed out: 0, 1, 2, 3 and that's it.
I wrote a question + answer in the past to explain in more details how it works: Understanding java 8 stream's filter method

Categories

Resources