是否可以用java 8流替换一个简单的java for循环(带索引)

时间:2016-01-13 09:22:09

标签: lambda java-8 java-stream

我想对任何不成功的响应都有失败的行为,如果一切都成功,那么我将返回上一个成功的响应,如下面的代码所示。

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;
  }
 }

我试图用流替换上面提到的代码,但是到目前为止还没能做到。主要问题是 我无法模仿java8流代码中的i(索引)变量行为。

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();

2 个答案:

答案 0 :(得分:5)

不需要外部库。

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);

完整示例(可编辑):

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);
    }
}

答案 1 :(得分:4)

似乎您确实需要以下内容:

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;

我可以提出的最短的基于lambda的解决方案涉及jOOλ库:

return Seq.seq(input)
          .map(service::getData)
          .limitWhileClosed(Data::isSuccessful)
          .reduce((a, b) -> b)
          .orElse(null);

这里必不可少的部分是limitWhileClosed方法,它在条件成立时接受输入元素,但也包括违反条件的第一个元素。之后我们使用reduce((a, b) -> b)来获取最后一个元素。

Java-8 Stream API中缺少limitWhileClosed方法。 Java-9将添加类似的takeWhile,但不包括违规元素。因此纯粹的Stream API解决方案将比普通的for循环更加丑陋。