Reputation: 501
I want to have failfast behavior for any unsuccessful response and if all go successful then I return the last successful response as shown in following code.
for(int i=0;i<input.size(); i++){
Data data = service.getData(input.get(i));
if(data.isSuccessful() && i==input.size()-1){
return data;
}else if(!data.isSuccessful()){
return data;
}else{
return null;
}
}
I tried to replace above mention code with streams but not been able to do so far.Main issue is that I am not able to imitate i(index) variable behavior in java8 stream code.
resp = input.stream().map((input)->{service.getData()}).filter(
(resp)->{
if(!resp.isSuccessful())
return true;
else if(resp.isSuccessful() && last resp)//if somehow I figure out last element
return true;
else
return false;}).findFirst();
Upvotes: 3
Views: 4883
Reputation: 21576
There is no need for external libraries.
return IntStream.range(0, input.size())
.mapToObj(i -> {
Data data = service.getData(input.get(i));
if (!data.isSuccessful() || i == input.size() - 1) {
return Optional.of(data);
}
return Optional.<Data>empty();
})
.filter(Optional::isPresent)
.findFirst()
.orElse(null);
Optional
, rather than the result or null
Complete example (compilable):
import java.util.Optional;
import java.util.stream.IntStream;
class Data {
public boolean isSuccessful() {return false;}
}
class Input {
public Object get(int i) {return null;}
public int size() {return 0;}
}
class Service {
public Data getData(Object object) {return null;}
}
public class T {
public static void main(String[] args) {method();}
protected static Optional<Data> method() {
Input input = new Input();
Service service = new Service();
return IntStream.range(0, input.size())
.mapToObj(i -> {
Data data = service.getData(input.get(i));
if (!data.isSuccessful() || i == input.size() - 1) {
return Optional.of(data);
}
return Optional.<Data>empty();
})
.filter(Optional::isPresent)
.findFirst()
.orElse(null);
}
}
Upvotes: 9
Reputation: 100209
Seems that you actually want the following:
for (int i = 0; i < input.size(); i++) {
Data data = service.getData(input.get(i));
if (!data.isSuccessful() || i == input.size() - 1) {
return data;
}
}
return null;
The shortest lambda-based solution I can propose involves the jOOλ library:
return Seq.seq(input)
.map(service::getData)
.limitWhileClosed(Data::isSuccessful)
.reduce((a, b) -> b)
.orElse(null);
The essential part here is limitWhileClosed
method which takes the input element while the condition holds, but also includes the first element which violates the condition. After that we use reduce((a, b) -> b)
to get the last taken element.
The limitWhileClosed
method is absent in Java-8 Stream API. Java-9 will add the takeWhile
which is similar, but does not include the violating element. So the pure Stream API solution would be much uglier than plain for
loop.
Upvotes: 4