如何在Java 8流中编写以下方法?

时间:2016-05-30 18:33:03

标签: java-8 java-stream

如何在Java 8流中编写以下方法?我找不到办法做到这一点。这是我的代码:

public static List<ObjectB>  getFilteredList(List<ObjectA> list, LocalTime startTime, LocalTime endTime, int quantity) {

List<ObjectA> objectAList = new LinkedList<>();
List<ObjectB> objectBList = new LinkedList<>();
for (ObjectA object : list) {
    if (object.getDateTime().toLocalTime().isAfter(startTime) && object.getDateTime().toLocalTime().isBefore(endTime)) {
        objectAList.add(object);
    }
}
for (ObjectA objectA : objectAList) {
    int total = 0;
    for (ObjectA object : list) {
        if (object.getDateTime().toLocalDate().equals(objectA.getDateTime().toLocalDate())) {
            total += object.getQuantity();
        }
    }
    if (total > quantity) {
        objectBList.add(new ObjectB(objectA.getDateTime(), objectA.getDescription(), objectA.getQuantity(), true));
    } else {
        objectBList.add(new ObjectB(objectA.getDateTime(), objectA.getDescription(), objectA.getQuantity(), false));
    }

}
return objectBList;}

我有一个包含两个字段的对象列表:日期和数量。我需要为每个日期返回一个包含一个对象的列表,但是还有一个feild - boolean,如果每天所有数量的总和大于16,则为true,如果不是则为false。

1 个答案:

答案 0 :(得分:1)

让我们一步一步来做。

  • for (ObjectA object : list) {:for循环通常替换为stream(),因此请从list.stream()开始。
  • if (...) {:条件通常替换为filter(),因此请继续.filter(object -> object.getDateTime()...)
  • objectAList.add(object);:将结果添加到容器通常会替换为collect()。您使用的是LinkedList(),但此处的任何其他列表都没问题,因此我们只需使用collect(Collectors.toList())

所以这是第一个循环:

List<ObjectA> objectAList = list.stream()
    .filter(object -> object.getDateTime().toLocalTime().isAfter(startTime) &&
                      object.getDateTime().toLocalTime().isBefore(endTime))
    .collect(Collectors.toList());

现在让我们看看计算total

的内部循环
int total = 0;
for (ObjectA object : list) {
    if (object.getDateTime().toLocalDate().equals(objectA.getDateTime().toLocalDate())) {
        total += object.getQuantity();
    }
}

它也是流过滤器收集序列,但在这里你要收集总和。因此,您可以在IntStream处使用sum()方法:

int total = list.stream()
                .filter(object -> object.getDateTime().toLocalDate().equals(
                                         objectA.getDateTime().toLocalDate())
                .mapToInt(ObjectA::getQuantity).sum();

为了让您的代码不那么拥挤,我会将其提取到单独的方法中:

private static int getQuantityByDate(List<ObjectA> list, LocalDate date) {
    return list.stream().filter(object -> object.getDateTime().toLocalDate().equals(date))
               .mapToInt(ObjectA::getQuantity).sum();
}

现在是下一个if语句。它只是改变了最后一个布尔参数,所以我会重写它(即使没有Stream API):

objectBList.add(new ObjectB(objectA.getDateTime(), objectA.getDescription(), 
         objectA.getQuantity(), total > quantity));

所以现在我们看到外部循环变成了stream-map-collect链,可以这样重写:

List<ObjectB> objectBList = objectAList.stream()
    .map(objectA -> 
         new ObjectB(objectA.getDateTime(), objectA.getDescription(), objectA.getQuantity(), 
             getQuantityByDate(list, objectA.getDateTime().toLocalDate()) > quantity))
    .collect(Collectors.toList());

现在你可以注意到收集到objectAList是不必要的,因为我们只是用它来创建另一个流。因此,我们可以将两个循环合并到单个管道中,从而生成以下最终代码:

private static int getQuantityByDate(List<ObjectA> list, LocalDate date) {
    return list.stream().filter(object -> object.getDateTime().toLocalDate().equals(date))
               .mapToInt(ObjectA::getQuantity).sum();
}

public static List<ObjectB> getFilteredList(
                 List<ObjectA> list, LocalTime startTime, LocalTime endTime, int quantity) {
    return list.stream()
        .filter(object -> object.getDateTime().toLocalTime().isAfter(startTime) &&
                          object.getDateTime().toLocalTime().isBefore(endTime))
        .map(objectA -> new ObjectB(
                objectA.getDateTime(), objectA.getDescription(), objectA.getQuantity(), 
                getQuantityByDate(list, objectA.getDateTime().toLocalDate()) > quantity))
        .collect(Collectors.toList());
}