How to make this Java summation stream more compact? - java

I have this stream from a Map that sums the integers from a method call on an object based on a certain condition.
I would like to know how to make it more compact and efficient.
int total = myMap.values().stream()
.filter(obj -> obj.countsInt())
.mapToInt(MyObject::getInt)
.sum();

You can use a method reference for obj.countsInt() and also use Collectors.summingInt() for your reducing method
int total = myMap.values()
.stream()
.filter(MyObject::countsInt)
.collect(summingInt(MyObject::getInt));

Compactness:
Use method references:
obj -> obj.countsInt()
can be replace by
MyObject::countsInt
Ignoring that, you could go straight to ints replacing:
.filter(obj -> obj.countsInt()).mapToInt(MyObject::getInt)
with
.mapToInt(obj -> obj.countsInt() ? 0 : obj.getInt())
But if you want efficiency, don't use streams.

Related

JAVA-STREAM : re-use double a DoubleStream

I need a trick to solve this problem i'm using Java 1.8 And I retrieved a an object from a method that returns a DoubleStream object. So, the problem is I could not reuse the stream after it has been consumed.
Here is the first version of the code :
DoubleStream stream = object.getvalueStream(a,b);
if(condtion)
stream.map(v -> v * 2);
stream.forEach(value -> {
// do something
}
The problem is that once the condition is true, the stream is consumed And I can not reuse it. So I tried to use a supplier to return a doubleStream from supplier and iterate overt it.
But still the same problem as I try to recover the stream from my stream object which is already used.
Here is my updated code :
DoubleStream stream = object.getvalueStream(a,b);
if(condtion)
stream.map(v -> v * 2);
Supplier>DoubleStream> streamSupplier = () -> DoubleStream.of(stream.toArray());
streamSupplier.get().forEach(value -> {
//Do something
But I still have the same problem since I create my supplier from my stream already used if the condition is true.
Thanks for your help.
once the condition is true, the stream is consumed And I can not reuse it
Intermediate operations (e.g. map) return a new stream, so you need to reassign the stream after the intermediate operation (map).
I.e.
DoubleStream stream = object.getvalueStream(a,b);
if (condition) {
stream = stream.map(v -> v * 2);
}
stream.forEach(value -> {
// do something
}
Note terminal operations (e.g. foreach) do not return a stream. So if you want many terminal operations, you should collect the stream so it can be reused.
Note also, there is also an intermediate version of foreach called peek if you wish to chain foreach (peek) calls.
Streams in Java are not up to be reused. You should collect the result and stream twice like
List<Double> doubles = object.getvalueStream(a,b).boxed().collect(toList());
if(condition) {
doubles = doubles.stream().map(v -> v * 2).boxed().collect(toList);
}
// and further processing here
doubles.stream().forEach(v ->
...
);
You can use map() if it is important for you to keep the stream without collecting it. The only drawback in this approach is that you have to check the condition each time
DoubleStream stream = object.getvalueStream(a,b).map(v-> condition ? v*2 : v).forEach(...);
Or just assign the right Stream to the variable
DoubleStream stream = condition ? object.getvalueStream(a,b).map(v->v*2) : object.getvalueStream(a,b).map(v->v*2).forEach(...);

Create a object initialization loop using Stream API

I have a set of constant values that are available as a list. Using these values I have to create a key value pair object and this object has to be added to a list. I would like to achieve this using Stream API in JAVA 8. Below is the sample implementation using a for loop
for (int i=0; i<length; i+=2){
list.add(new sampleObject(constant[i],constant[i+1]);
}
Can this be implemented using Stream reduction operations?
Chain IntStream.iterate() that produces a infinite IntStream with IntStream.limit() to make it finite :
List<sampleObject> list =
IntStream.iterate(0, i -> i + 2)
.limit(Math.ceil(length / 2D))
.mapToObj(i -> new sampleObject(constant[i], constant[i+1]))
.collect(Collectors.toList());
Of course it can!
IntStream.iterate(0, i -> i < length, i -> i + 2)
.mapToObj(i -> new sampleObject(constant[i], constant[i+1]))
.collect(Collectors.toList());
I'm not sure off the top of my head, but constant may have to be final or effectively final for this to compile.
Note: I just realized, this overloaded iterate method was added in Java 9. Please see davidxxx's answer for a Java 8 solution!

iterating over list with streams base of the length of another list

I'd like to perform such action using streams:
List<String> listX = new ArrayList<>();
for(int i=0;i<listY.size();i++){
listX.add(String.format(ABC,i));
}
so I have to iterate over a list using the length of another list and additionally use counter i. After all i'd like to return the new list
using IntStream.range & IntStream.mapToObj methods. and don't operates variables out of lambda expression in stream api, that will resulting in Thread Interference or Memory Consistency Errors in parallel stream.
List<String> listX = IntStream.range(0, listY.size())
.mapToObj(i -> String.format(ABC,i))
.collect(Collectors.toList());
You can use IntStream to iterate using index of listY as shown below:
IntStream.range(0, listY.size()).forEach(i -> listX.add(String.format(ABC,i)));
You could also use Collectors.mapping, something like this:
IntStream.range(0, listY.size())
.collect(Collectors.mapping(i -> String.format(ABC,i),
Collectors.toList()));

Java Stream API storing lambda expression as variable

This title sounds stupid even to me, but there must be at least somewhat clever way to achieve such effect and I don't know how else to explain it. I need to sort array using sorted in stream API. Here is my stream so far:
Arrays.stream(sequence.split(" "))
.mapToInt(Integer::parseInt)
.boxed()
.sorted((a, b) -> a.compareTo(b))
.forEach(a -> System.out.print(a + " "));
Now I have two different sorts of course - ascending and descending and the sort I need to use is specified in the user input. So what I want to do is having something like switch with 2 cases: "ascending" and "descending" and a variable to store the lambda expression respectively:
switch(command) {
case "ascending": var = a.compareTo(b);
case "descending": var = b.compareTo(a);
}
Then I my sorted looks like:
.sorted((a, b) -> var)
I got the idea in a python course I attended. There it was available to store an object in variable, thus making the variable "executable". I realize that this lambda is not an object, but an expression, but I'm asking is there any clever way that can achieve such result, or should I just have
if(var)
and two diferent streams for each sort order.
The question is not stupid at all. Answering it in a broader sense: Unfortunately, there is no generic solution for that. This is due to the type inference, which determines one particular type for the lambda expression, based on the target type. (The section about type inference may be helpful here, but does not cover all details regarding lambdas).
Particularly, a lambda like x -> y does not have any type. So there is no way of writing
GenericLambdaTypefunction = x -> y;
and later use function as a drop-in replacement for the actual lambda x -> y.
For example, when you have two functions like
static void useF(Function<Integer, Boolean> f) { ... }
static void useP(Predicate<Integer> p) { ... }
you can call them both with the same lambda
useF(x -> true);
useP(x -> true);
but there is no way of "storing" the x -> true lambda in a way so that it later may be passed to both functions - you can only store it in a reference with the type that it will be needed in later:
Function<Integer, Boolean> f = x -> true;
Predicate<Integer> p = x -> true;
useF(f);
useP(p);
For your particular case, the answer by Konstantin Yovkov already showed the solution: You have to store it as a Comparator<Integer> (ignoring the fact that you wouldn't have needed a lambda here in the first place...)
You can switch between using Comparator.reverseOrder() and Comparator.naturalOrder:
Comparator<Integer> comparator = youWantToHaveItReversed ? Comparator.reverseOrder(): Comparator.naturalOrder();
Arrays.stream(sequence.split(" "))
.map(Integer::valueOf)
.sorted(comparator)
.forEach(a -> System.out.print(a + " "));
In Lambdas you can use a functionblock
(a,b) -> { if(anything) return 0; else return -1;}

Java - Find Element in Array using Condition and Lambda

In short, I have this code, and I'd like to get an specific element of the array using a condition and lambda. The code would be something like this:
Preset[] presets = presetDALC.getList();
Preset preset = Arrays.stream(presets).select(x -> x.getName().equals("MyString"));
But obviously this does not work. In C# would be something similar but in Java, how do I do this?
You can do it like this,
Optional<Preset> optional = Arrays.stream(presets)
.filter(x -> "MyString".equals(x.getName()))
.findFirst();
if(optional.isPresent()) {//Check whether optional has element you are looking for
Preset p = optional.get();//get it from optional
}
You can read more about Optional here.
Like this:
Optional<Preset> preset = Arrays
.stream(presets)
.filter(x -> x.getName().equals("MyString"))
.findFirst();
This will return an Optional which might or might not contain a value. If you want to get rid of the Optional altogether:
Preset preset = Arrays
.stream(presets)
.filter(x -> x.getName().equals("MyString"))
.findFirst()
.orElse(null);
The filter() operation is an intermediate operation which returns a lazy stream, so there's no need to worry about the entire array being filtered even after a match is encountered.
Do you want first matching, or all matching?
String[] presets = {"A", "B", "C", "D", "CA"};
// Find all matching
List<String> resultList = Arrays.stream(presets)
.filter(x -> x.startsWith("C"))
.collect(Collectors.toList());
System.out.println(resultList);
// Find first matching
String firstResult = Arrays.stream(presets)
.filter(x -> x.startsWith("C"))
.findFirst()
.orElse(null);
System.out.println(firstResult);
Output
[C, CA]
C
One-liner since Java 8:
Preset found = Stream.of(presets)
.filter(p -> p.getName().equals("MyString"))
.findFirst().orElseThrow();
Avoid declaring Optional<>, that returned from findFirst as a variable or a parameter. It is designed for return types / "one-liner" styles.
see javadoc API Note
see 26 Reasons Why Using Optional Correctly

Categories

Resources