Is there a way to peek the next element in a stream? The idea rose from a stream of a list of objects, where two following objects should be compared (to smooth some diffs, but that shouldn't matter here). As an old for
loop this would look like:
List<Car> autobahn = getCars();
for (int i = 0; i < autobahn.size()-1; i++) {
if(autobahn.get(i).speed>autobahn.get(i+1).speed)
autobahn.get(i).honk();
}
The best way so far as stream would be:
autobahn.stream()
.limit(autobahn.size()-1)
.filter(car -> car.speed < autobahn.get(autobahn.indexOf(car)+1).speed)
.forEach(car -> car.honk());
The main-problem with this solution is the indexOf
method, since there might be twice the same car on the autobahn. A better solution would be some way to peek the next (or the one before) element (with an helping class, this might be even possible, but looks horrible)
BoxedCar boxedCar = new BoxedCar(autobahn.get(0));
autobahn.stream()
.skip(1)
.filter(car -> boxedCar.setContent(car))
.forEach(car -> car.winTheRace());
with helperclass
class BoxedCar {
Car content;
BoxedCar(Car content) {
this.content = content;
}
boolean setContent(Car content) {
double speed = this.content.speed;
this.content = content;
return content.speed > speed;
}
}
or to divert the Stream<Car>
into a kind of Stream<(Car,Car)>
with the second stream somehow created by the first one (this sounds also awful and here I have no idea, how this would look).
Is there a nice way to do this with streams, or are we stuck to the for
-loop?
Java Stream peek() Java Stream peek() method returns a new Stream consisting of all the elements from the original Stream after applying a given Consumer action. Note that the peek() method is an intermediate Stream operation so, to process the Stream elements through peek() , we must use a terminal operation.
peek() method in Java is used to retrieve or fetch the first element of the Stack or the element present at the top of the Stack. The element retrieved does not get deleted or removed from the Stack.
To get the first element, you can use the reduce() method to ignore the second element, repeatedly, till there is no second element. This reduces the set of elements in a Stream to a single element, which is first. Hence the only single element will be remain in the stream which is the first element.
foreach, you can also change the internal property value of each item in the list, etc., but you need to perform "secondary flow processing" to get the smallest item in the list (filter according to age). (2): stream. peek can get the smallest item directly compared with stream. foreach().
Sticking with the for
loop wouldn't be a bad idea. The Stream API isn't designed for this type of requirement. You can refer to that answer for more insight.
However, a simple way to do this using the Stream API would be to use a Stream over the indexes of your list, supposing that you have random access.
IntStream.range(0, autobahn.size() - 1)
.filter(i -> autobahn.get(i).speed > autobahn.get(i+1).speed)
.forEach(i -> autobahn.get(i).honk());
Note that this highly resemble the for
loop.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With