如何使用java Streams API在多个计数动态变化的情况下转换for循环n次以实现列表
要使用Streams API并删除下面代码段中的当前for循环:如何使用java Streams API在多个计数动态变化的情况下转换for循环n次以实现列表,java,java-8,java-stream,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 tota
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;
}
但我陷入了困境,无法进一步了解如何继续,需要从派生对象“o”中获取多个值,并使用它在其上执行筛选,然后再次进行另一个方法调用获取一些数组,该数组将传递给其他方法以返回创建结果列表所需的其他对象
startIndex+=length;
意味着下一次迭代的行为取决于当前迭代后的状态
这基本上意味着迭代必须连续进行。因此,在这里堵住溪流没有任何好处
只需使用现有代码即可
我已经看到了OP询问如何重写代码以使用流的许多问题。隐式假设是流优于循环,因此流应该总是优先于循环使用 事实并非如此 与循环相比,流是:
- 更严格的限制:不能使用流控制,如
,中断
;从周围环境中重新分配局部变量;抛出已检查的异常;从包含方法返回;在某些基本类型上循环继续
- 更重量级:在构建流时创建了许多对象
- 结构化程度较低:IMO称,使用平面映射的流比嵌套循环更难读取
- 不太容易理解:我的经验是,许多人看到代码中的流,并认为它们很难理解,而且有点神奇。这将随着时间的推移而改变,因为他们对仍然相对较新的API更加熟悉;但在某种程度上,它们是正确的:streams API是大型的、特定于Java的,并且提供了许多方法来攻击自己。另一方面,(基本)循环实际上与所有类似C语言中的语法相同:一旦在其中一种语言中学习了它,您就可以立即“了解”循环在Java中的作用。对循环的增强甚至与C++、Python等 基本相同。
- 更简洁:有时可以将“循环体”表示为lambda或方法引用,可以更短
- 简单地并行化:虽然有效的Java3rded有一条关于为什么要非常小心地使用这个特性的条款
startIndex+=length;
意味着下一次迭代的行为取决于当前迭代后的状态
这基本上意味着迭代必须连续进行。因此,在这里堵住溪流没有任何好处
只需使用现有代码即可
我已经看到了OP询问如何重写代码以使用流的许多问题。隐式假设是流优于循环,因此流应该总是优先于循环使用 事实并非如此 与循环相比,流是:
- 更严格的限制:不能使用流控制,如
,中断
;从周围环境中重新分配局部变量;抛出已检查的异常;从包含方法返回;在某些基本类型上循环继续
- 更重量级:在构建流时创建了许多对象
- 结构化程度较低:IMO称,使用平面映射的流比嵌套循环更难读取
- 不太容易理解:我的经验是,许多人看到代码中的流,并认为它们很难理解,而且有点神奇。这将随着时间的推移而改变,因为他们对仍然相对较新的API更加熟悉;但在某种程度上,它们是正确的:streams API是大型的、特定于Java的,并且提供了许多方法来攻击自己。另一方面,(基本)循环实际上与所有类似C语言中的语法相同:一旦在其中一种语言中学习了它,您就可以立即“了解”循环在Java中的作用。对循环的增强甚至与C++、Python等 基本相同。
- 更简洁:有时可以将“循环体”表示为lambda或方法引用,可以更短
- 简单地并行化:虽然有效的Java3rded有一条关于为什么要非常小心地使用这个特性的条款
您可以使用一个自定义的中间类来简化:
public List<MyObject> performSomeAction(){
List<String> myList = Arrays.asList("abc","xyz","def");
class ReductionHelper {
int startIndex;
final List<MyObject> resultList = new LinkedList<>();
}
return Stream.generate(xService::doSomething)
.limit(1000)
.reduce(new ReductionHelper(), (helper, o) -> {
int length = o.getLength();
if(myList.contains(o.getType()){
int[] myarray=getMyArray(helper.startIndex+20, helperstartIndex+length);
String id=o.getSomeId();
OtherObject obj= xService.performOperation(myarray,"abcd");
helper.resultList.add(new MyObject(obj,id));
}
helper.startIndex += length;
return helper;
}, (left, right) -> {
left.resultList.addAll(right.resultList);
return left;
})
.resultList; // return just the result list
}
public List performSomeAction(){
List myList=Arrays.asList(“abc”、“xyz”、“def”);
类简化助手{
国际标准指数;
最终列表结果列表=新建LinkedList();
}
返回Stream.generate(xService::doSomething)
.限额(1000)
.reduce(新ReductionHelper(),(helper,o)->{
int length=o.getLength();
if(myList.contains(o.getType()){
int[]myarray=getMyArray(helper.startIndex+20,helperstartIndex+length);
String id=o.getSomeId();
otherobjectobj=xService.performOperation(myarray,“abcd”);
add(新的MyObject(obj,id));
}
helper.startIndex+=长度;
返回助手;
},(左,右)->{
left.resultList.addAll(right.resultList);
左转;
})
.resultList;//仅返回结果列表
}
这只是使用类ReductionHelper
来保存resultList和startIndex,但它非常混乱
正如您所看到的,这绝不会比您的c更具可读性