Reputation: 470
How to get the next element from a List
using Java 8 Streams?
If I am iterating over a List
, I want to compare current with next element of the list.
Is it doable using Java 8 Stream?
Upvotes: 33
Views: 49828
Reputation: 716
If you had a list of Integers for example and wanted to check if they are sorted ascending, you could do as follows:
@Test
public void test_listIsSorted() {
// create integer list for testing purposes: 0,1,2,3, .., 10
List<Integer> integerList = IntStream.range(0, 10)
.boxed()
.collect(Collectors.toList());
// stream list and compare item n with n+1
integerList.stream()
.reduce((integer1, integer2) -> {
assert integer1 < integer2 : "ordering must be ascending";
// return second value (which will be processed as "integer1" in the next iteration
return integer2;
});
}
This will compare pairs like: (0,1),(1,2),...
Upvotes: 2
Reputation: 1108
I had to do the same and compare the differences of the elements of a stream (originally an array). So I used a method as a parameter to the UnaryOperator that .map() expects as follows...and it worked for me without any special gizmo's:
import java.util.Arrays;
class streamDiffUtil {
public static void main(String[] args) {
int[] elements = {1,2,5};
int result = Arrays.stream(elements)
.map(value -> calcMaxDiff(value, elements))
.max()
.getAsInt();
System.out.println(result);
}
private static int calcMaxDiff(int j, int[] elements) {
return Arrays.stream(elements)
.map(value -> Math.abs(j-value))
.max().getAsInt();
}
}
What would be nice is to know how the method calcMaxDiff equates to a UnaryIntOperator in the .map signature. That is a little beyond me. Hope this helps you.
Upvotes: 0
Reputation: 435
Stream.reduce could be used, depending on the goal. As you said, you'd like to compare consecutive elements, the following would print "Same 3":
Stream.of(1,2,3,3).reduce((a,b)->{
if(a==b) System.out.println("Same "+a);
return b; // will be "a" for next reduction
});
Upvotes: 9
Reputation: 4942
You always do one of following:
Implementations of both solutions can be seen in this thread: Is it possible to get next element in the Stream?
Upvotes: 0
Reputation: 100339
My free StreamEx library allows you to process the pairs of the stream elements using additional pairMap
intermediate operation. Like this:
StreamEx.of(input).pairMap((current, next) -> doSomethingWith(current, next));
Where input
is a Collection
, array or Stream
. For example, this way you can easily check whether input is sorted:
boolean isSorted = StreamEx.of(input)
.pairMap((current, next) -> next.compareTo(current))
.allMatch(cmp -> cmp >= 0);
There's also forPairs
terminal operation which is a forEach
analog to all pairs of input elements:
StreamEx.of(input).forPairs((current, next) -> doSomethingWith(current, next));
These features work nicely with any stream source (either random access or not) and fully support the parallel streams.
Upvotes: 17
Reputation: 394156
One way is to generate an IntStream
of the indices, and fetch the List
elements by their index. This is only efficient if the List
supports random access (i.e. if your List
is a LinkedList
, it would be a bad idea, since list.get(i)
doesn't take constant time).
For example :
IntStream.range(0,list.size()-1).forEach(i -> {
doSomething(list.get(i),list.get(i+1));
});
Another way is to store the last element in an array :
List<Element> list = ...
Element[] arr = new Element[1];
list.stream().forEach(e -> {
if (arr[0] != null)
doSomething(arr[0],e);
arr[0]=e;
});
This will only work for sequential streams.
Upvotes: 14