Java 8 - Streams嵌套ForEach与不同的Collection

时间:2014-08-18 05:50:12

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

我尝试了解新的Java 8 Streams,并且我尝试了几天将嵌套的foreach循环传输到Java 8 Streams中的集合。

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

如果是,它会是什么样子。

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

1 个答案:

答案 0 :(得分: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。流形式将从更精确的定义中获益。