forked from JavaOPs/topjava
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path1_3_HW0_optional2.patch
More file actions
90 lines (85 loc) · 4.15 KB
/
1_3_HW0_optional2.patch
File metadata and controls
90 lines (85 loc) · 4.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
Index: src/main/java/ru/javawebinar/topjava/util/MealsUtil.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/main/java/ru/javawebinar/topjava/util/MealsUtil.java (date 1509555460000)
+++ src/main/java/ru/javawebinar/topjava/util/MealsUtil.java (revision )
@@ -8,7 +8,12 @@
import java.time.LocalTime;
import java.time.Month;
import java.util.*;
+import java.util.stream.Collector;
import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static java.util.function.Function.identity;
+import static java.util.stream.Collectors.toList;
public class MealsUtil {
public static void main(String[] args) {
@@ -24,6 +29,8 @@
mealsWithExceeded.forEach(System.out::println);
System.out.println(getFilteredWithExceededByCycle(meals, LocalTime.of(7, 0), LocalTime.of(12, 0), 2000));
+ System.out.println(getFilteredWithExceededInOnePass(meals, LocalTime.of(7, 0), LocalTime.of(12, 0), 2000));
+ System.out.println(getFilteredWithExceededInOnePass2(meals, LocalTime.of(7, 0), LocalTime.of(12, 0), 2000));
}
public static List<MealWithExceed> getFilteredWithExceeded(List<Meal> meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) {
@@ -36,7 +43,7 @@
return meals.stream()
.filter(meal -> TimeUtil.isBetween(meal.getTime(), startTime, endTime))
.map(meal -> createWithExceed(meal, caloriesSumByDate.get(meal.getDate()) > caloriesPerDay))
- .collect(Collectors.toList());
+ .collect(toList());
}
public static List<MealWithExceed> getFilteredWithExceededByCycle(List<Meal> meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) {
@@ -53,6 +60,51 @@
return mealsWithExceeded;
}
+ public static List<MealWithExceed> getFilteredWithExceededInOnePass(List<Meal> meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) {
+ Collection<List<Meal>> list = meals.stream()
+ .collect(Collectors.groupingBy(Meal::getDate)).values();
+
+ return list.stream().flatMap(dayMeals -> {
+ boolean exceed = dayMeals.stream().mapToInt(Meal::getCalories).sum() > caloriesPerDay;
+ return dayMeals.stream().filter(meal ->
+ TimeUtil.isBetween(meal.getTime(), startTime, endTime))
+ .map(meal -> createWithExceed(meal, exceed));
+ }).collect(toList());
+ }
+
+ public static List<MealWithExceed> getFilteredWithExceededInOnePass2(List<Meal> meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) {
+ final class Aggregate {
+ private final List<Meal> dailyMeals = new ArrayList<>();
+ private int dailySumOfCalories;
+
+ private void accumulate(Meal meal) {
+ dailySumOfCalories += meal.getCalories();
+ if (TimeUtil.isBetween(meal.getDateTime().toLocalTime(), startTime, endTime)) {
+ dailyMeals.add(meal);
+ }
+ }
+
+ // never invoked if the upstream is sequential
+ private Aggregate combine(Aggregate that) {
+ this.dailySumOfCalories += that.dailySumOfCalories;
+ this.dailyMeals.addAll(that.dailyMeals);
+ return this;
+ }
+
+ private Stream<MealWithExceed> finisher() {
+ final boolean exceed = dailySumOfCalories > caloriesPerDay;
+ return dailyMeals.stream().map(meal -> createWithExceed(meal, exceed));
+ }
+ }
+
+ Collection<Stream<MealWithExceed>> values = meals.stream()
+ .collect(Collectors.groupingBy(Meal::getDate,
+ Collector.of(Aggregate::new, Aggregate::accumulate, Aggregate::combine, Aggregate::finisher))
+ ).values();
+
+ return values.stream().flatMap(identity()).collect(toList());
+ }
+
public static MealWithExceed createWithExceed(Meal meal, boolean exceeded) {
return new MealWithExceed(meal.getDateTime(), meal.getDescription(), meal.getCalories(), exceeded);
}