重构循环进入android中的流

时间:2017-10-17 06:50:10

标签: java android java-stream

我想将for循环重构为流:

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,这个变量应该是最终的。如何添加缺失部分,然后在适配器中添加结果?

3 个答案:

答案 0 :(得分:1)

没有理由在这里使用流。 Streams are useful when defining sophisticated data processing queries.它们提供了一种紧凑但富有表现力的方式来定义流的元素的顺序操作,如Oracle提供的示例:

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

.stream().forEach(...)(或Stream.of(...).forEach(...))是代码气味。您正在构建流并立即将其解构为对元素的常规迭代。除非您重构循环体的内容,否则常规的forfor each结构似乎更容易,更清晰。

答案 1 :(得分:0)

您可以将lastID变量作为类字段。可以在lambda块中访问类成员,而无需使用final

答案 2 :(得分: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添加一个

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

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