Lets say I have the following array: {1,2,3,4,6,7,8}
which is put in a Stream<Integer> s = Stream.of(1,2,3,4,6,7,8);
How can I use in Java lambda expressions and Stream functions to calculate the difference between each element and the next (in this case {1,1,1,2,1,1}
)?
This is not really a reduce operation as reduce transforms the entire list to 1 element; it also isn't a map operation as it requires two elements to calculate the difference and not just one.
Lambda Expressions were added in Java 8. A lambda expression is a short block of code which takes in parameters and returns a value. Lambda expressions are similar to methods, but they do not need a name and they can be implemented right in the body of a method.
The "this" and "super" references within a lambda expression are the same as in the enclosing context. Since the lambda expression doesn't define a new scope, "this" keyword within a lambda expression signifies "this" parameter of a method where the lambda expression is residing.
You can use my StreamEx library which has a pairMap
method specially for this case:
StreamEx<Integer> s = StreamEx.of(1,2,3,4,6,7,8);
s = s.pairMap((a, b) -> b-a);
s.forEach(System.out::println);
The StreamEx
class implements Stream
and is fully compatible with it. The same thing works with primitive streams as well:
IntStreamEx s = IntStreamEx.of(1,2,3,4,6,7,8);
s = s.pairMap((a, b) -> b-a);
s.forEach(System.out::println);
The other answer seems to be accepted already, but had an idea so I post it anyway. You can make a Collector
that collects it directly to another Stream<Integer>
.
Then you can just write like:
s.collect(intDifferences()).forEach(d -> System.out.print(d + ","));
Here's an implementation I wrote:
public static Collector<Integer, List<Integer>, Stream<Integer>> intDifferences() {
return new Collector<Integer, List<Integer>, Stream<Integer>>() {
@Override
public BiConsumer<List<Integer>, Integer> accumulator() {
return List::add;
}
@Override
public Set<Collector.Characteristics> characteristics() {
return EnumSet.noneOf(Collector.Characteristics.class);
}
@Override
public BinaryOperator<List<Integer>> combiner() {
return (left, right) -> {
left.addAll(right);
return left;
};
}
@Override
public Function<List<Integer>, Stream<Integer>> finisher() {
return list -> {
List<Integer> differences = new ArrayList<>();
for (int i = 1; i < list.size(); i++) {
differences.add(list.get(i) - list.get(i - 1));
}
return differences.stream();
};
}
@Override
public Supplier<List<Integer>> supplier() {
return ArrayList::new;
}
};
}
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