【问题标题】:Java 8 - Streams Nested ForEach with different CollectionJava 8 - 具有不同集合的嵌套 ForEach 流
【发布时间】:2014-10-10 23:55:27
【问题描述】:

我尝试了解新的 Java 8 Streams,并尝试了几天来将嵌套的 foreach 循环转移到 Java 8 Streams 中的集合上。

是否可以重构以下嵌套的 foreach 循环,包括 Java-8-Streams 中的 if 条件?

如果是的话会是什么样子。

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

非常感谢您的帮助。

BR

【问题讨论】:

  • 你确定这段代码是正确的吗?由于您在内循环中调用了tempInqAndQuot.add(simInq),因此您将多次添加相同的对象到相同的集合中。
  • 应该将tempQuotPos定义为ArrayList&lt;SalesQuotPosition&gt;吗?
  • 您好,arraylist 必须来自 SalesQuotPosition 类型

标签: java collections foreach java-8 java-stream


【解决方案1】:

首先,请尽量遵守 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());
                }
            }
        }
    }

虽然目前还不清楚它应该做什么以及它是否正确。除了在您的问题的 cmets 中提到的错误和怀疑之外,修改传入的值(尤其是来自外部循环的值)看起来不正确。

也不清楚您为什么使用….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 命名约定问题,然后我将尝试清理我的代码。
猜你喜欢
  • 2021-12-15
  • 1970-01-01
  • 2019-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多