Java 8 - 使用不同集合的嵌套 ForEach 流

3
我尝试了解新的Java 8 Streams,并尝试了数天将Java 8 Streams中的嵌套foreach循环转换为集合。
是否可以在Java 8 Streams中重构以下包含if条件的嵌套foreach循环?
如果可以,它会是什么样子。
ArrayList<ClassInq> Inq = new ArrayList<>();
TreeMap<String, SalesQuot> Quotations = new TreeMap<>();

ArrayList<ClassInq> tempInqAndQuot = new ArrayList<>();
ArrayList<SalesQuot> tempQuotPos = new ArrayList<>();   

for(ClassInq simInq : this.Inq) {
    if(!simInq.isClosed() && !simInq.isDenied()) {
        for(Map.Entry<String, SalesQuot> Quot: Quotations.entrySet()) {

            SalesQuot sapQuot = Quot.getValue();

            if(sapQuot.getInquiryDocumentNumber().compareTo(simInq.getSapInquiryNumber()) == 0) {

                simInq.setSAPQuotationNumber(sapQuot.getQuotationDocumentNumber());
                tempInqAndQuot.add(simInq);

                for(Map.Entry<String, SalesQuotPosition> quotp : sapQuot.getPosition().entrySet()) {
                    tempQuotPos.add(quotp.getValue());
                }
            }
        }
    }
}

非常感谢您的帮助。
敬礼

你确定这段代码是正确的吗?由于在内部循环中调用了 tempInqAndQuot.add(simInq),所以你正在将同一对象多次添加到同一集合中。 - Eran
tempQuotPos 应该定义为 ArrayList<SalesQuotPosition> 吗? - Sean Van Gorder
嗨,没错,ArrayList 必须是 SalesQuotPosition 类型的。 - user1796346
1个回答

13

首先,尝试遵循Java命名约定,因为您的大写变量名使得代码阅读起来非常困难。其次,您想学习Stream API是一件好事,但不应忽略Java 8之前的Collection API基础知识。

当您只关心键或值时,迭代entrySet()是没有用处的。在一小段代码中,您这样做了两次。

在第一次出现时,您可以将其替换为

for (Map.Entry<String, SalesQuot> Quot: Quotations.entrySet()){
    SalesQuot sapQuot = Quot.getValue();

更加简单易懂地

for (SalesQuot sapQuot: Quotations.values()){

目前,整个

for(Map.Entry<String,SalesQuotPosition> quotp: sapQuot.getPosition().entrySet()){
    tempQuotPos.add(quotp.getValue());
}

可以被替换为

tempQuotPos.addAll(sapQuot.getPosition().values());
因此,即使没有流,您的代码也可以简化为:
for (ClassInq simInq : this.Inq){
        if (!simInq.isClosed() && !simInq.isDenied()){      
            for (SalesQuot sapQuot: Quotations.values()){
                if (sapQuot.getInquiryDocumentNumber().compareTo(simInq.getSapInquiryNumber()) == 0){
                    simInq.setSAPQuotationNumber(sapQuot.getQuotationDocumentNumber());
                    tempInqAndQuot.add(simInq);
                    tempQuotPos.addAll(sapQuot.getPosition().values());
                }
            }
        }
    }

虽然目的和正确性仍不清楚。除了评论中提到的错误和疑虑,修改传入的值(特别是来自外部循环的值)似乎不正确。

也不清楚为什么要使用....compareTo(...)==0而不是equals

但是,可以直接重写为使用流,而不改变任何代码逻辑:

this.Inq.stream().filter(simInq -> !simInq.isClosed() && !simInq.isDenied())
  .forEach(simInq -> Quotations.values().stream().filter(sapQuot ->
   sapQuot.getInquiryDocumentNumber().compareTo(simInq.getSapInquiryNumber())==0)
   .forEach(sapQuot -> {
      simInq.setSAPQuotationNumber(sapQuot.getQuotationDocumentNumber());
      tempInqAndQuot.add(simInq);
      tempQuotPos.addAll(sapQuot.getPosition().values());
    })
  );

不过,在重写代码以使用其他API之前,我建议先清理原始逻辑。对于流式表单来说,更精确地定义要实现的目标将大大有益。


谢谢你的帮助。我是一个Java初学者,我首先尝试让程序正常工作,然后在下一步中改进/重构它。感谢您所有的提示。所以我会先清理Java命名规则问题,然后尝试清理我的代码。 - user1796346

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接