2017-10-17 10 views
1

我想修改我的for循环到流:重构环路到数据流中的Android

for (TrackingGroup item : trackingGroups) { 
    List<IItem> items = new ArrayList<>(); 
    items.add(new ItemText(getActivity().getString(R.string.track_title) + " " + trackingGroup.getTitle())); 
    for (ProfileAnswerItem answerItem : listofAnswers) { 
     for (TrackingItem trackingItem : item.getItems()) { 
      if (trackingItem.getId() == answerItem.getId()) { 
       ItemQuestionResult itemView = new ItemQuestionResult(new ItemAnswer(item.getId(), answerItem.getId(), answerItem.getText(), false, true), 
         items.size() > 1); 
       items.add(itemView); 
       // adapter.add(itemView); 
      } else { 
       if (item.getId() == answerItem.getTrackId() && answerItem.isCustom()) { 
        ItemQuestionResult itemView = new ItemQuestionResult(new ItemAnswer(item.getId(), answerItem.getId(), answerItem.getText(), false, true), 
          items.size() > 1); 
        if (answerItem.getId() != lastID) { 
         items.add(itemView); 
         //adapter.add(itemView); 
         lastID = answerItem.getId(); 
        } 
       } 
      } 
     } 
    } 
    adapter.add(items); 
} 

,这就是我对这个时刻:

Stream.of(trackingGroups) 
       .forEach(trackingGroup1 -> { 
        List<IItem> items = new ArrayList<>(); 
        items.add(new ItemText(getActivity().getString(R.string.track_title) + " " + trackingGroup.getTitle())); 
        Stream.of(listofAnswers) 
          .forEach(profileAnswerItem -> { 
           Stream.of(trackingGroup1.getItems()) 
             .forEach(trackingItem -> { 
              if (trackingItem.getId() == profileAnswerItem.getId()) { 
               ItemQuestionResult itemView = new ItemQuestionResult(new ItemAnswer(trackingGroup1.getId(), 
                 profileAnswerItem.getId(), profileAnswerItem.getText(), false, true), 
                 items.size() > 1); 
               items.add(itemView); 
              } else { 
               if (trackingGroup1.getId() == profileAnswerItem.getTrackId() && profileAnswerItem.isCustom()) { 
                ItemQuestionResult itemView = new ItemQuestionResult(new ItemAnswer(trackingGroup1.getId(), 
                  profileAnswerItem.getId(), profileAnswerItem.getText(), false, true), 
                  items.size() > 1); 
                if (profileAnswerItem.getId() != lastID) { 
                 items.add(itemView); 
                 lastID = profileAnswerItem.getId(); 
                } 
               } 
              } 
             }); 
          }); 
       }); 

现在我有一个问题变量lastID。对于lambdas这个变量应该是final的。我如何添加缺少的部分,然后在适配器中添加结果?

+4

没有要求使用流而不是循环。有时(如这里),代码对于流更糟糕。你为什么认为你想在这里使用流? –

+0

我同意@AndyTurner,你*可能*可能*可能重构这个利用流的使用map/flatMap从你的数据对象到视图,但正如书面,没有什么可以通过使用流获得。 –

回答

0

你可以让你的lastID变成一个班级字段。可以在lambda块内访问类成员,而不使它们成为final

+1

或者你可以使用像AtomicInteger这样的可变包装。 – shmosel

1

在这里没有理由使用流。 Streams are useful when defining sophisticated data processing queries.它们提供了一种紧凑而表达的方式来定义在流中的元素顺序的操作,如由Oracle提供的示例:编写.stream().forEach(...)(或Stream.of(...).forEach(...))是一个代码气味

List<Integer> transactionsIds = 
    transactions.stream() 
       .filter(t -> t.getType() == Transaction.GROCERY) 
       .sorted(comparing(Transaction::getValue).reversed()) 
       .map(Transaction::getId) 
       .collect(toList()); 

。您正在构建一个流,并立即将其解构为对元素的常规迭代。经常的forfor each构造看起来既简单又清晰,除非您重构循环体的内容。

0

您的代码遗漏了很多细节,但想了解你所要完成的是什么,我凸轮了这一点:

for (TrackingGroup item : trackingGroups) 
{ 
    List<IItem> items = new ArrayList<>(); 

    items.add(new ItemText(getActivity().getString(R.string.track_title) + " " + trackingGroup.getTitle())); 

    for (ProfileAnswerItem answerItem : listofAnswers) 
    { 
     // first, find out how many items to create 
     long itemsToCreate = item.getItems() 
           .stream() 
           .filter(trackingItem -> trackingItem.getId() == answerItem.getId()) 
           .count(); 

     if (itemsToCreate < item.getItems().size() // not all trackingItems matched the answerItem 
      && item.getId() == answerItem.getTrackId() && answerItem.isCustom() // answer matches your original condition 
     ) 
     { 
      itemsToCreate++; // create 1 extra item 
     } 

     // second, create and add items 
     Stream.generate(() -> new ItemQuestionResult(new ItemAnswer(item.getId(), 
                    answerItem.getId(), 
                    answerItem.getText(), 
                    false, 
                    true), 
                items.size() > 1)) 
       .limit(itemsToCreate) 
       .forEach(items::add); 
    } 

    adapter.add(items); 
} 

如果我理解正确的代码,并且尽我所能看到不知道lastIDlistofAnswerstrackingGrouptrackingGroups来自哪里,或者之后用什么,你根本不需要lastID

您尝试添加一个额外的项目,如果一个ProfileAnswerItem不匹配所有TrackingItem秒。并且lastID用于确保只添加一个那些每ProfileAnswerItem

起初这很难读,我认为你可以通过分离测试和项目创建来简化这个过程,如图所示。这也使得更明显的是,为追踪项目创建的项目与额外项目相同。这部分也可以从使用流中受益。其余的,试图将它转换成流完全使它更难以阅读。

如果我误解了你的代码,请告诉我。也许你可以让你的示例代码更简单一些,让我们更容易理解。所有这些缺失的类使得很难在没有首先创建大量模拟类的情况下工作。