如何转换循环迭代n次以使用java Streams API实现列表,其中多个计数动态更改

May*_*tra 0 java java-8 java-stream

想要在下面的代码段中使用Streams API并删除当前for循环:

public List<MyObject> performSomeAction(){
    List<String> myList= Arrays.asList("abc","xyz","def");
    List<MyObject> resultList=new ArrayList<MyObject>();
    int startIndex=0;
    int totalNumOfRecords=1000; 
    for(int i=0;i<totalNumOfRecords;i++){
        SomeObject o= xService.doSomething();
        String type = o.getType();
        int length = o.getLength();
        if(myList.contains(type)){
            int[] myarray=getMyArray(startIndex+20, startIndex+length);
            String id=o.getSomeId();
            OtherObject obj= xService.performOperation(myarray,"abcd");
            resultList.add(new MyObject(obj,id));
        }
        startIndex+=length;
    }
    return resultList;
}
Run Code Online (Sandbox Code Playgroud)

我试过这样的事情:

IntStream.range(0,totalNumOfRecords).forEach(i -> xService.doSomething());
Run Code Online (Sandbox Code Playgroud)

但我陷入困境,没有得到进一步的进展,需要从派生对象'o'中取出多个值,并使用它在它上面执行过滤器再次使另一个方法调用得到一些数组,将其传递给其他方法返回我需要创建resultList的其他对象

And*_*ner 5

这一行:

startIndex+=length;
Run Code Online (Sandbox Code Playgroud)

意味着下一次迭代的行为取决于当前迭代之后的状态.

这基本上意味着迭代必须连续发生.因此,在这里扼杀Streams没有任何好处.

坚持使用现有代码.


我已经看到许多问题,其中OP询问如何重写代码以使用流.隐含的假设是流优于循环,因此流应始终优先于循环使用.

这是不正确的.

与循环相比,流是:

  • 更多的限制:你不能使用像流量控制break,continue; 从周围的上下文重新分配局部变量; 抛出检查异常; 从包含方法返回; 循环某些原始类型.
  • 更重量级:您在构建流时创建了大量对象
  • 结构较少:使用平面映射的流比嵌套循环IMO更难阅读
  • 不太了解:我的经验是很多人看到代码中的流,并认为它们很难理解,有点神奇.这将随着时间的推移而变化,因为它们对于仍然相对较新的API变得更加舒适; 但在某种程度上,它们是正确的:流API是大型的,特定于Java的,并且提供了许多方法来自己射击.另一方面,(Basic)循环实际上与所有类C语言中的语法相同:一旦你在一个语言中学习它,你就会立即"获得"循环在Java中所做的事情.即使增强的for循环也基本上与C++,Python等相同.

但是,流可以是:

  • 更简洁:有时您可以将"循环体"表示为lambda或方法引用,它可以更短.
  • 并行化平行:虽然Effective Java 3rd Ed有一个关于为什么应该非常谨慎地使用此功能的项目.

流是一种工具,具有有限的好处和许多缺点.重写现有的工作代码以使用它们确实不是一个好主意.