From 89d2f131263630c77fe30113702e65c9136ec411 Mon Sep 17 00:00:00 2001 From: Arsegg Date: Sun, 29 May 2022 13:48:31 +0400 Subject: [PATCH 01/11] prepare to HW0 patch --- .../javawebinar/topjava/model/UserMeal.java | 29 ++++++++++++++ .../topjava/model/UserMealWithExcess.java | 30 ++++++++++++++ .../ru/javawebinar/topjava/util/TimeUtil.java | 9 +++++ .../topjava/util/UserMealsUtil.java | 39 +++++++++++++++++++ 4 files changed, 107 insertions(+) create mode 100644 src/main/java/ru/javawebinar/topjava/model/UserMeal.java create mode 100644 src/main/java/ru/javawebinar/topjava/model/UserMealWithExcess.java create mode 100644 src/main/java/ru/javawebinar/topjava/util/TimeUtil.java create mode 100644 src/main/java/ru/javawebinar/topjava/util/UserMealsUtil.java diff --git a/src/main/java/ru/javawebinar/topjava/model/UserMeal.java b/src/main/java/ru/javawebinar/topjava/model/UserMeal.java new file mode 100644 index 000000000000..d8f91b127f6a --- /dev/null +++ b/src/main/java/ru/javawebinar/topjava/model/UserMeal.java @@ -0,0 +1,29 @@ +package ru.javawebinar.topjava.model; + +import java.time.LocalDateTime; + +public class UserMeal { + private final LocalDateTime dateTime; + + private final String description; + + private final int calories; + + public UserMeal(LocalDateTime dateTime, String description, int calories) { + this.dateTime = dateTime; + this.description = description; + this.calories = calories; + } + + public LocalDateTime getDateTime() { + return dateTime; + } + + public String getDescription() { + return description; + } + + public int getCalories() { + return calories; + } +} diff --git a/src/main/java/ru/javawebinar/topjava/model/UserMealWithExcess.java b/src/main/java/ru/javawebinar/topjava/model/UserMealWithExcess.java new file mode 100644 index 000000000000..d0aa431a35d9 --- /dev/null +++ b/src/main/java/ru/javawebinar/topjava/model/UserMealWithExcess.java @@ -0,0 +1,30 @@ +package ru.javawebinar.topjava.model; + +import java.time.LocalDateTime; + +public class UserMealWithExcess { + private final LocalDateTime dateTime; + + private final String description; + + private final int calories; + + private final boolean excess; + + public UserMealWithExcess(LocalDateTime dateTime, String description, int calories, boolean excess) { + this.dateTime = dateTime; + this.description = description; + this.calories = calories; + this.excess = excess; + } + + @Override + public String toString() { + return "UserMealWithExcess{" + + "dateTime=" + dateTime + + ", description='" + description + '\'' + + ", calories=" + calories + + ", excess=" + excess + + '}'; + } +} diff --git a/src/main/java/ru/javawebinar/topjava/util/TimeUtil.java b/src/main/java/ru/javawebinar/topjava/util/TimeUtil.java new file mode 100644 index 000000000000..0ebfdb5fcdcb --- /dev/null +++ b/src/main/java/ru/javawebinar/topjava/util/TimeUtil.java @@ -0,0 +1,9 @@ +package ru.javawebinar.topjava.util; + +import java.time.LocalTime; + +public class TimeUtil { + public static boolean isBetweenHalfOpen(LocalTime lt, LocalTime startTime, LocalTime endTime) { + return lt.compareTo(startTime) >= 0 && lt.compareTo(endTime) < 0; + } +} diff --git a/src/main/java/ru/javawebinar/topjava/util/UserMealsUtil.java b/src/main/java/ru/javawebinar/topjava/util/UserMealsUtil.java new file mode 100644 index 000000000000..3c171b4a5972 --- /dev/null +++ b/src/main/java/ru/javawebinar/topjava/util/UserMealsUtil.java @@ -0,0 +1,39 @@ +package ru.javawebinar.topjava.util; + +import ru.javawebinar.topjava.model.UserMeal; +import ru.javawebinar.topjava.model.UserMealWithExcess; + +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.Month; +import java.util.Arrays; +import java.util.List; + +public class UserMealsUtil { + public static void main(String[] args) { + List meals = Arrays.asList( + new UserMeal(LocalDateTime.of(2020, Month.JANUARY, 30, 10, 0), "Завтрак", 500), + new UserMeal(LocalDateTime.of(2020, Month.JANUARY, 30, 13, 0), "Обед", 1000), + new UserMeal(LocalDateTime.of(2020, Month.JANUARY, 30, 20, 0), "Ужин", 500), + new UserMeal(LocalDateTime.of(2020, Month.JANUARY, 31, 0, 0), "Еда на граничное значение", 100), + new UserMeal(LocalDateTime.of(2020, Month.JANUARY, 31, 10, 0), "Завтрак", 1000), + new UserMeal(LocalDateTime.of(2020, Month.JANUARY, 31, 13, 0), "Обед", 500), + new UserMeal(LocalDateTime.of(2020, Month.JANUARY, 31, 20, 0), "Ужин", 410) + ); + + List mealsTo = filteredByCycles(meals, LocalTime.of(7, 0), LocalTime.of(12, 0), 2000); + mealsTo.forEach(System.out::println); + +// System.out.println(filteredByStreams(meals, LocalTime.of(7, 0), LocalTime.of(12, 0), 2000)); + } + + public static List filteredByCycles(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { + // TODO return filtered list with excess. Implement by cycles + return null; + } + + public static List filteredByStreams(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { + // TODO Implement by streams + return null; + } +} From 003f4b98aba00f7477a16221a476a9704b7016c2 Mon Sep 17 00:00:00 2001 From: Arsegg Date: Sat, 4 Jun 2022 13:43:24 +0400 Subject: [PATCH 02/11] 1_0_rename --- .../model/{UserMeal.java => Meal.java} | 4 +- .../{UserMealWithExcess.java => MealTo.java} | 6 +-- .../javawebinar/topjava/util/MealsUtil.java | 39 +++++++++++++++++++ .../topjava/util/UserMealsUtil.java | 39 ------------------- 4 files changed, 44 insertions(+), 44 deletions(-) rename src/main/java/ru/javawebinar/topjava/model/{UserMeal.java => Meal.java} (83%) rename src/main/java/ru/javawebinar/topjava/model/{UserMealWithExcess.java => MealTo.java} (77%) create mode 100644 src/main/java/ru/javawebinar/topjava/util/MealsUtil.java delete mode 100644 src/main/java/ru/javawebinar/topjava/util/UserMealsUtil.java diff --git a/src/main/java/ru/javawebinar/topjava/model/UserMeal.java b/src/main/java/ru/javawebinar/topjava/model/Meal.java similarity index 83% rename from src/main/java/ru/javawebinar/topjava/model/UserMeal.java rename to src/main/java/ru/javawebinar/topjava/model/Meal.java index d8f91b127f6a..f546cef0f74a 100644 --- a/src/main/java/ru/javawebinar/topjava/model/UserMeal.java +++ b/src/main/java/ru/javawebinar/topjava/model/Meal.java @@ -2,14 +2,14 @@ import java.time.LocalDateTime; -public class UserMeal { +public class Meal { private final LocalDateTime dateTime; private final String description; private final int calories; - public UserMeal(LocalDateTime dateTime, String description, int calories) { + public Meal(LocalDateTime dateTime, String description, int calories) { this.dateTime = dateTime; this.description = description; this.calories = calories; diff --git a/src/main/java/ru/javawebinar/topjava/model/UserMealWithExcess.java b/src/main/java/ru/javawebinar/topjava/model/MealTo.java similarity index 77% rename from src/main/java/ru/javawebinar/topjava/model/UserMealWithExcess.java rename to src/main/java/ru/javawebinar/topjava/model/MealTo.java index d0aa431a35d9..07f04f8dbb9f 100644 --- a/src/main/java/ru/javawebinar/topjava/model/UserMealWithExcess.java +++ b/src/main/java/ru/javawebinar/topjava/model/MealTo.java @@ -2,7 +2,7 @@ import java.time.LocalDateTime; -public class UserMealWithExcess { +public class MealTo { private final LocalDateTime dateTime; private final String description; @@ -11,7 +11,7 @@ public class UserMealWithExcess { private final boolean excess; - public UserMealWithExcess(LocalDateTime dateTime, String description, int calories, boolean excess) { + public MealTo(LocalDateTime dateTime, String description, int calories, boolean excess) { this.dateTime = dateTime; this.description = description; this.calories = calories; @@ -20,7 +20,7 @@ public UserMealWithExcess(LocalDateTime dateTime, String description, int calori @Override public String toString() { - return "UserMealWithExcess{" + + return "MealTo{" + "dateTime=" + dateTime + ", description='" + description + '\'' + ", calories=" + calories + diff --git a/src/main/java/ru/javawebinar/topjava/util/MealsUtil.java b/src/main/java/ru/javawebinar/topjava/util/MealsUtil.java new file mode 100644 index 000000000000..bb5ddbf5ccc5 --- /dev/null +++ b/src/main/java/ru/javawebinar/topjava/util/MealsUtil.java @@ -0,0 +1,39 @@ +package ru.javawebinar.topjava.util; + +import ru.javawebinar.topjava.model.Meal; +import ru.javawebinar.topjava.model.MealTo; + +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.Month; +import java.util.Arrays; +import java.util.List; + +public class MealsUtil { + public static void main(String[] args) { + List meals = Arrays.asList( + new Meal(LocalDateTime.of(2020, Month.JANUARY, 30, 10, 0), "Завтрак", 500), + new Meal(LocalDateTime.of(2020, Month.JANUARY, 30, 13, 0), "Обед", 1000), + new Meal(LocalDateTime.of(2020, Month.JANUARY, 30, 20, 0), "Ужин", 500), + new Meal(LocalDateTime.of(2020, Month.JANUARY, 31, 0, 0), "Еда на граничное значение", 100), + new Meal(LocalDateTime.of(2020, Month.JANUARY, 31, 10, 0), "Завтрак", 1000), + new Meal(LocalDateTime.of(2020, Month.JANUARY, 31, 13, 0), "Обед", 500), + new Meal(LocalDateTime.of(2020, Month.JANUARY, 31, 20, 0), "Ужин", 410) + ); + + List mealsTo = filteredByCycles(meals, LocalTime.of(7, 0), LocalTime.of(12, 0), 2000); + mealsTo.forEach(System.out::println); + +// System.out.println(filteredByStreams(meals, LocalTime.of(7, 0), LocalTime.of(12, 0), 2000)); + } + + public static List filteredByCycles(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { + // TODO return filtered list with excess. Implement by cycles + return null; + } + + public static List filteredByStreams(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { + // TODO Implement by streams + return null; + } +} diff --git a/src/main/java/ru/javawebinar/topjava/util/UserMealsUtil.java b/src/main/java/ru/javawebinar/topjava/util/UserMealsUtil.java deleted file mode 100644 index 3c171b4a5972..000000000000 --- a/src/main/java/ru/javawebinar/topjava/util/UserMealsUtil.java +++ /dev/null @@ -1,39 +0,0 @@ -package ru.javawebinar.topjava.util; - -import ru.javawebinar.topjava.model.UserMeal; -import ru.javawebinar.topjava.model.UserMealWithExcess; - -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.Month; -import java.util.Arrays; -import java.util.List; - -public class UserMealsUtil { - public static void main(String[] args) { - List meals = Arrays.asList( - new UserMeal(LocalDateTime.of(2020, Month.JANUARY, 30, 10, 0), "Завтрак", 500), - new UserMeal(LocalDateTime.of(2020, Month.JANUARY, 30, 13, 0), "Обед", 1000), - new UserMeal(LocalDateTime.of(2020, Month.JANUARY, 30, 20, 0), "Ужин", 500), - new UserMeal(LocalDateTime.of(2020, Month.JANUARY, 31, 0, 0), "Еда на граничное значение", 100), - new UserMeal(LocalDateTime.of(2020, Month.JANUARY, 31, 10, 0), "Завтрак", 1000), - new UserMeal(LocalDateTime.of(2020, Month.JANUARY, 31, 13, 0), "Обед", 500), - new UserMeal(LocalDateTime.of(2020, Month.JANUARY, 31, 20, 0), "Ужин", 410) - ); - - List mealsTo = filteredByCycles(meals, LocalTime.of(7, 0), LocalTime.of(12, 0), 2000); - mealsTo.forEach(System.out::println); - -// System.out.println(filteredByStreams(meals, LocalTime.of(7, 0), LocalTime.of(12, 0), 2000)); - } - - public static List filteredByCycles(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { - // TODO return filtered list with excess. Implement by cycles - return null; - } - - public static List filteredByStreams(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { - // TODO Implement by streams - return null; - } -} From da08f2efac7ff630c7b3305d26ef430d04adb9a2 Mon Sep 17 00:00:00 2001 From: Arsegg Date: Sat, 4 Jun 2022 13:46:00 +0400 Subject: [PATCH 03/11] 1_1_HW0_streams --- .../ru/javawebinar/topjava/model/Meal.java | 10 +++++++ .../javawebinar/topjava/util/MealsUtil.java | 26 ++++++++++++------- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/main/java/ru/javawebinar/topjava/model/Meal.java b/src/main/java/ru/javawebinar/topjava/model/Meal.java index f546cef0f74a..943ff5cd59fa 100644 --- a/src/main/java/ru/javawebinar/topjava/model/Meal.java +++ b/src/main/java/ru/javawebinar/topjava/model/Meal.java @@ -1,6 +1,8 @@ package ru.javawebinar.topjava.model; +import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.LocalTime; public class Meal { private final LocalDateTime dateTime; @@ -26,4 +28,12 @@ public String getDescription() { public int getCalories() { return calories; } + + public LocalDate getDate() { + return dateTime.toLocalDate(); + } + + public LocalTime getTime() { + return dateTime.toLocalTime(); + } } diff --git a/src/main/java/ru/javawebinar/topjava/util/MealsUtil.java b/src/main/java/ru/javawebinar/topjava/util/MealsUtil.java index bb5ddbf5ccc5..c29e1fbbb077 100644 --- a/src/main/java/ru/javawebinar/topjava/util/MealsUtil.java +++ b/src/main/java/ru/javawebinar/topjava/util/MealsUtil.java @@ -3,11 +3,14 @@ import ru.javawebinar.topjava.model.Meal; import ru.javawebinar.topjava.model.MealTo; +import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.Month; import java.util.Arrays; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; public class MealsUtil { public static void main(String[] args) { @@ -21,19 +24,24 @@ public static void main(String[] args) { new Meal(LocalDateTime.of(2020, Month.JANUARY, 31, 20, 0), "Ужин", 410) ); - List mealsTo = filteredByCycles(meals, LocalTime.of(7, 0), LocalTime.of(12, 0), 2000); + List mealsTo = filteredByStreams(meals, LocalTime.of(7, 0), LocalTime.of(12, 0), 2000); mealsTo.forEach(System.out::println); - -// System.out.println(filteredByStreams(meals, LocalTime.of(7, 0), LocalTime.of(12, 0), 2000)); } - public static List filteredByCycles(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { - // TODO return filtered list with excess. Implement by cycles - return null; + public static List filteredByStreams(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { + Map caloriesSumByDate = meals.stream() + .collect( + Collectors.groupingBy(Meal::getDate, Collectors.summingInt(Meal::getCalories)) +// Collectors.toMap(Meal::getDate, Meal::getCalories, Integer::sum) + ); + + return meals.stream() + .filter(meal -> TimeUtil.isBetweenHalfOpen(meal.getTime(), startTime, endTime)) + .map(meal -> createTo(meal, caloriesSumByDate.get(meal.getDate()) > caloriesPerDay)) + .collect(Collectors.toList()); } - public static List filteredByStreams(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { - // TODO Implement by streams - return null; + private static MealTo createTo(Meal meal, boolean excess) { + return new MealTo(meal.getDateTime(), meal.getDescription(), meal.getCalories(), excess); } } From 7f24adcc543e7824ba7ad0d90b12fdcd0d7fb68d Mon Sep 17 00:00:00 2001 From: Arsegg Date: Sat, 4 Jun 2022 13:47:17 +0400 Subject: [PATCH 04/11] 1_opt_2_HW0_cycles --- .../javawebinar/topjava/util/MealsUtil.java | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/src/main/java/ru/javawebinar/topjava/util/MealsUtil.java b/src/main/java/ru/javawebinar/topjava/util/MealsUtil.java index c29e1fbbb077..48c2e96ef536 100644 --- a/src/main/java/ru/javawebinar/topjava/util/MealsUtil.java +++ b/src/main/java/ru/javawebinar/topjava/util/MealsUtil.java @@ -7,11 +7,11 @@ import java.time.LocalDateTime; import java.time.LocalTime; import java.time.Month; -import java.util.Arrays; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; +import static ru.javawebinar.topjava.util.TimeUtil.isBetweenHalfOpen; + public class MealsUtil { public static void main(String[] args) { List meals = Arrays.asList( @@ -24,8 +24,13 @@ public static void main(String[] args) { new Meal(LocalDateTime.of(2020, Month.JANUARY, 31, 20, 0), "Ужин", 410) ); - List mealsTo = filteredByStreams(meals, LocalTime.of(7, 0), LocalTime.of(12, 0), 2000); + final LocalTime startTime = LocalTime.of(7, 0); + final LocalTime endTime = LocalTime.of(12, 0); + + List mealsTo = filteredByStreams(meals, startTime, endTime, 2000); mealsTo.forEach(System.out::println); + + System.out.println(filteredByCycles(meals, startTime, endTime, 2000)); } public static List filteredByStreams(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { @@ -36,11 +41,25 @@ public static List filteredByStreams(List meals, LocalTime startTi ); return meals.stream() - .filter(meal -> TimeUtil.isBetweenHalfOpen(meal.getTime(), startTime, endTime)) + .filter(meal -> isBetweenHalfOpen(meal.getTime(), startTime, endTime)) .map(meal -> createTo(meal, caloriesSumByDate.get(meal.getDate()) > caloriesPerDay)) .collect(Collectors.toList()); } + public static List filteredByCycles(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { + + final Map caloriesSumByDate = new HashMap<>(); + meals.forEach(meal -> caloriesSumByDate.merge(meal.getDate(), meal.getCalories(), Integer::sum)); + + final List mealsTo = new ArrayList<>(); + meals.forEach(meal -> { + if (isBetweenHalfOpen(meal.getTime(), startTime, endTime)) { + mealsTo.add(createTo(meal, caloriesSumByDate.get(meal.getDate()) > caloriesPerDay)); + } + }); + return mealsTo; + } + private static MealTo createTo(Meal meal, boolean excess) { return new MealTo(meal.getDateTime(), meal.getDescription(), meal.getCalories(), excess); } From 3a2e81cb3c4b039dbc085028f2bd78ebc9037b33 Mon Sep 17 00:00:00 2001 From: Arsegg Date: Sat, 4 Jun 2022 13:48:09 +0400 Subject: [PATCH 05/11] 1_opt_3_HW0_opt2 --- .../ru/javawebinar/topjava/model/MealTo.java | 15 +- .../javawebinar/topjava/util/MealsUtil.java | 312 +++++++++++++++++- 2 files changed, 324 insertions(+), 3 deletions(-) diff --git a/src/main/java/ru/javawebinar/topjava/model/MealTo.java b/src/main/java/ru/javawebinar/topjava/model/MealTo.java index 07f04f8dbb9f..35551cda8020 100644 --- a/src/main/java/ru/javawebinar/topjava/model/MealTo.java +++ b/src/main/java/ru/javawebinar/topjava/model/MealTo.java @@ -9,7 +9,10 @@ public class MealTo { private final int calories; - private final boolean excess; +// private final AtomicBoolean excess; // filteredByAtomic (or any ref type, e.g. boolean[1]) +// private final Boolean excess; // filteredByReflection +// private final Supplier excess; // filteredByClosure + private boolean excess; public MealTo(LocalDateTime dateTime, String description, int calories, boolean excess) { this.dateTime = dateTime; @@ -18,6 +21,16 @@ public MealTo(LocalDateTime dateTime, String description, int calories, boolean this.excess = excess; } +// for filteredByClosure +// public Boolean getExcess() { +// return excess.get(); +// } + + // for filteredBySetterRecursion + public void setExcess(boolean excess) { + this.excess = excess; + } + @Override public String toString() { return "MealTo{" + diff --git a/src/main/java/ru/javawebinar/topjava/util/MealsUtil.java b/src/main/java/ru/javawebinar/topjava/util/MealsUtil.java index 48c2e96ef536..a7e7cca3222c 100644 --- a/src/main/java/ru/javawebinar/topjava/util/MealsUtil.java +++ b/src/main/java/ru/javawebinar/topjava/util/MealsUtil.java @@ -8,12 +8,20 @@ import java.time.LocalTime; import java.time.Month; import java.util.*; +import java.util.concurrent.*; +import java.util.concurrent.locks.ReentrantLock; +import java.util.function.Consumer; +import java.util.function.Predicate; +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; import static ru.javawebinar.topjava.util.TimeUtil.isBetweenHalfOpen; public class MealsUtil { - public static void main(String[] args) { + public static void main(String[] args) throws InterruptedException { List meals = Arrays.asList( new Meal(LocalDateTime.of(2020, Month.JANUARY, 30, 10, 0), "Завтрак", 500), new Meal(LocalDateTime.of(2020, Month.JANUARY, 30, 13, 0), "Обед", 1000), @@ -31,13 +39,34 @@ public static void main(String[] args) { mealsTo.forEach(System.out::println); System.out.println(filteredByCycles(meals, startTime, endTime, 2000)); + + // Optional2 recursion + System.out.println(filteredByRecursion(meals, startTime, endTime, 2000)); + System.out.println(filteredBySetterRecursion(meals, startTime, endTime, 2000)); + System.out.println(filteredByRecursionWithCycleAndRunnable(meals, startTime, endTime, 2000)); + + // Optional2 reference type + // System.out.println(filteredByAtomic(meals, startTime, endTime, 2000)); // or boolean[1] + // System.out.println(filteredByReflection(meals, startTime, endTime, 2000)); + + // Optional2 delayed execution + // System.out.println(filteredByClosure(meals, startTime, endTime, 2000)); + System.out.println(filteredByExecutor(meals, startTime, endTime, 2000)); + System.out.println(filteredByLock(meals, startTime, endTime, 2000)); + System.out.println(filteredByCountDownLatch(meals, startTime, endTime, 2000)); + System.out.println(filteredByPredicate(meals, startTime, endTime, 2000)); + System.out.println(filteredByConsumerChain(meals, startTime, endTime, 2000)); + + // Optional2 streams + System.out.println(filteredByFlatMap(meals, startTime, endTime, 2000)); + System.out.println(filteredByCollector(meals, startTime, endTime, 2000)); } public static List filteredByStreams(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { Map caloriesSumByDate = meals.stream() .collect( Collectors.groupingBy(Meal::getDate, Collectors.summingInt(Meal::getCalories)) -// Collectors.toMap(Meal::getDate, Meal::getCalories, Integer::sum) + // Collectors.toMap(Meal::getDate, Meal::getCalories, Integer::sum) ); return meals.stream() @@ -60,6 +89,285 @@ public static List filteredByCycles(List meals, LocalTime startTim return mealsTo; } + private static List filteredByRecursion(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { + ArrayList result = new ArrayList<>(); + filterWithRecursion(new LinkedList<>(meals), startTime, endTime, caloriesPerDay, new HashMap<>(), result); + return result; + } + + private static void filterWithRecursion(LinkedList meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay, + Map dailyCaloriesMap, List result) { + if (meals.isEmpty()) return; + + Meal meal = meals.pop(); + dailyCaloriesMap.merge(meal.getDate(), meal.getCalories(), Integer::sum); + filterWithRecursion(meals, startTime, endTime, caloriesPerDay, dailyCaloriesMap, result); + if (isBetweenHalfOpen(meal.getTime(), startTime, endTime)) { + result.add(createTo(meal, dailyCaloriesMap.get(meal.getDate()) > caloriesPerDay)); + } + } + + private static List filteredBySetterRecursion(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { + class MealNode { + private final MealNode prev; + private final MealTo mealTo; + + public MealNode(MealTo mealTo, MealNode prev) { + this.mealTo = mealTo; + this.prev = prev; + } + + public void setExcess() { + mealTo.setExcess(true); + if (prev != null) { + prev.setExcess(); + } + } + } + + Map caloriesSumByDate = new HashMap<>(); + Map mealNodeByDate = new HashMap<>(); + List mealsTo = new ArrayList<>(); + meals.forEach(meal -> { + LocalDate localDate = meal.getDate(); + boolean excess = caloriesSumByDate.merge(localDate, meal.getCalories(), Integer::sum) > caloriesPerDay; + if (TimeUtil.isBetweenHalfOpen(meal.getTime(), startTime, endTime)) { + MealTo mealTo = createTo(meal, excess); + mealsTo.add(mealTo); + if (!excess) { + MealNode prevNode = mealNodeByDate.get(localDate); + mealNodeByDate.put(localDate, new MealNode(mealTo, prevNode)); + } + } + if (excess) { + MealNode mealNode = mealNodeByDate.remove(localDate); + if (mealNode != null) { + // recursive set for all interval day meals + mealNode.setExcess(); + } + } + }); + return mealsTo; + } + + public static List filteredByRecursionWithCycleAndRunnable(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { + Map caloriesSumByDate = new HashMap<>(); + List mealsTo = new ArrayList<>(); + Iterator iterator = meals.iterator(); + + new Runnable() { + @Override + public void run() { + while (iterator.hasNext()) { + Meal meal = iterator.next(); + caloriesSumByDate.merge(meal.getDate(), meal.getCalories(), Integer::sum); + if (isBetweenHalfOpen(meal.getTime(), startTime, endTime)) { + run(); + mealsTo.add(createTo(meal, caloriesSumByDate.get(meal.getDate()) > caloriesPerDay)); + } + } + } + }.run(); + return mealsTo; + } + + /* + private static List filteredByAtomic(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { + Map caloriesSumByDate = new HashMap<>(); + Map exceededMap = new HashMap<>(); + + List mealsTo = new ArrayList<>(); + meals.forEach(meal -> { + AtomicBoolean wrapBoolean = exceededMap.computeIfAbsent(meal.getDate(), date -> new AtomicBoolean()); + Integer dailyCalories = caloriesSumByDate.merge(meal.getDate(), meal.getCalories(), Integer::sum); + if (dailyCalories > caloriesPerDay) { + wrapBoolean.set(true); + } + if (isBetween(meal.getTime(), startTime, endTime)) { + mealsTo.add(createTo(meal, wrapBoolean)); // also change createTo and MealTo.excess + } + }); + return mealsTo; + } + + private static List filteredByReflection(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) throws NoSuchFieldException, IllegalAccessException { + Map caloriesSumByDate = new HashMap<>(); + Map exceededMap = new HashMap<>(); + Field field = Boolean.class.getDeclaredField("value"); + field.setAccessible(true); + + List mealsTo = new ArrayList<>(); + for (Meal meal : meals) { + Boolean mutableBoolean = exceededMap.computeIfAbsent(meal.getDate(), date -> new Boolean(false)); + Integer dailyCalories = caloriesSumByDate.merge(meal.getDate(), meal.getCalories(), Integer::sum); + if (dailyCalories > caloriesPerDay) { + field.setBoolean(mutableBoolean, true); + } + if (isBetweenHalfOpen(meal.getTime(), startTime, endTime)) { + mealsTo.add(createTo(meal, mutableBoolean)); // also change createTo and MealTo.excess + } + } + return mealsTo; + } + + private static List filteredByClosure(List mealList, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { + final Map caloriesSumByDate = new HashMap<>(); + List mealsTo = new ArrayList<>(); + mealList.forEach(meal -> { + caloriesSumByDate.merge(meal.getDate(), meal.getCalories(), Integer::sum); + if (isBetween(meal.getTime(), startTime, endTime)) { + mealsTo.add(createTo(meal, () -> (caloriesSumByDate.get(meal.getDate()) > caloriesPerDay))); // also change createTo and MealTo.excess + } + } + ); + return mealsTo; + } + */ + + private static List filteredByExecutor(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) throws InterruptedException { + Map caloriesSumByDate = new HashMap<>(); + List> tasks = new ArrayList<>(); + final List mealsTo = Collections.synchronizedList(new ArrayList<>()); + + meals.forEach(meal -> { + caloriesSumByDate.merge(meal.getDate(), meal.getCalories(), Integer::sum); + if (isBetweenHalfOpen(meal.getTime(), startTime, endTime)) { + tasks.add(() -> { + mealsTo.add(createTo(meal, caloriesSumByDate.get(meal.getDate()) > caloriesPerDay)); + return null; + }); + } + }); + ExecutorService executorService = Executors.newCachedThreadPool(); + executorService.invokeAll(tasks); + executorService.shutdown(); + return mealsTo; + } + + public static List filteredByLock(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) throws InterruptedException { + Map caloriesSumByDate = new HashMap<>(); + List mealsTo = new ArrayList<>(); + ExecutorService executor = Executors.newCachedThreadPool(); + ReentrantLock lock = new ReentrantLock(); + lock.lock(); + for (Meal meal : meals) { + caloriesSumByDate.merge(meal.getDateTime().toLocalDate(), meal.getCalories(), Integer::sum); + if (isBetweenHalfOpen(meal.getDateTime().toLocalTime(), startTime, endTime)) + executor.submit(() -> { + lock.lock(); + mealsTo.add(createTo(meal, caloriesSumByDate.get(meal.getDateTime().toLocalDate()) > caloriesPerDay)); + lock.unlock(); + }); + } + lock.unlock(); + executor.shutdown(); + executor.awaitTermination(5, TimeUnit.SECONDS); + return mealsTo; + } + + private static List filteredByCountDownLatch(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) throws InterruptedException { + Map caloriesSumByDate = new HashMap<>(); + List mealsTo = Collections.synchronizedList(new ArrayList<>()); + CountDownLatch latchCycles = new CountDownLatch(meals.size()); + CountDownLatch latchTasks = new CountDownLatch(meals.size()); + for (Meal meal : meals) { + caloriesSumByDate.merge(meal.getDateTime().toLocalDate(), meal.getCalories(), Integer::sum); + if (isBetweenHalfOpen(meal.getDateTime().toLocalTime(), startTime, endTime)) { + new Thread(() -> { + try { + latchCycles.await(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + mealsTo.add(createTo(meal, caloriesSumByDate.get(meal.getDateTime().toLocalDate()) > caloriesPerDay)); + latchTasks.countDown(); + }).start(); + } else { + latchTasks.countDown(); + } + latchCycles.countDown(); + } + latchTasks.await(); + return mealsTo; + } + + public static List filteredByPredicate(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { + Map caloriesSumByDate = new HashMap<>(); + List mealsTo = new ArrayList<>(); + + Predicate predicate = b -> true; + for (Meal meal : meals) { + caloriesSumByDate.merge(meal.getDateTime().toLocalDate(), meal.getCalories(), Integer::sum); + if (TimeUtil.isBetweenHalfOpen(meal.getDateTime().toLocalTime(), startTime, endTime)) { + predicate = predicate.and(b -> mealsTo.add(createTo(meal, caloriesSumByDate.get(meal.getDateTime().toLocalDate()) > caloriesPerDay))); + } + } + predicate.test(true); + return mealsTo; + } + + public static List filteredByConsumerChain(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { + Map caloriesPerDays = new HashMap<>(); + List result = new ArrayList<>(); + Consumer consumer = dummy -> { + }; + + for (Meal meal : meals) { + caloriesPerDays.merge(meal.getDate(), meal.getCalories(), Integer::sum); + if (TimeUtil.isBetweenHalfOpen(meal.getTime(), startTime, endTime)) { + consumer = consumer.andThen(dummy -> result.add(createTo(meal, caloriesPerDays.get(meal.getDateTime().toLocalDate()) > caloriesPerDay))); + } + } + consumer.accept(null); + return result; + } + + private static List filteredByFlatMap(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { + Collection> list = meals.stream() + .collect(Collectors.groupingBy(Meal::getDate)).values(); + + return list.stream() + .flatMap(dayMeals -> { + boolean excess = dayMeals.stream().mapToInt(Meal::getCalories).sum() > caloriesPerDay; + return dayMeals.stream().filter(meal -> + isBetweenHalfOpen(meal.getTime(), startTime, endTime)) + .map(meal -> createTo(meal, excess)); + }).collect(toList()); + } + + private static List filteredByCollector(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { + final class Aggregate { + private final List dailyMeals = new ArrayList<>(); + private int dailySumOfCalories; + + private void accumulate(Meal meal) { + dailySumOfCalories += meal.getCalories(); + if (isBetweenHalfOpen(meal.getTime(), 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 finisher() { + final boolean excess = dailySumOfCalories > caloriesPerDay; + return dailyMeals.stream().map(meal -> createTo(meal, excess)); + } + } + + Collection> 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()); + } + private static MealTo createTo(Meal meal, boolean excess) { return new MealTo(meal.getDateTime(), meal.getDescription(), meal.getCalories(), excess); } From dca306348ecb2f5b7b9a84accd6d7a1cf9e888c2 Mon Sep 17 00:00:00 2001 From: Arsegg Date: Sat, 4 Jun 2022 13:52:41 +0400 Subject: [PATCH 06/11] 1_2_switch_to_war --- pom.xml | 2 +- src/main/webapp/WEB-INF/web.xml | 19 +++++++++++++++++++ src/main/webapp/index.html | 13 +++++++++++++ src/main/webapp/users.jsp | 11 +++++++++++ 4 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 src/main/webapp/WEB-INF/web.xml create mode 100644 src/main/webapp/index.html create mode 100644 src/main/webapp/users.jsp diff --git a/pom.xml b/pom.xml index 0b1c2896da5b..b4426c1aa2d6 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ ru.javawebinar topjava - jar + war 1.0-SNAPSHOT diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 000000000000..c63810c43593 --- /dev/null +++ b/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,19 @@ + + + Topjava + + + userServlet + ru.javawebinar.topjava.web.UserServlet + 0 + + + userServlet + /users + + + diff --git a/src/main/webapp/index.html b/src/main/webapp/index.html new file mode 100644 index 000000000000..58d8d5ab6aec --- /dev/null +++ b/src/main/webapp/index.html @@ -0,0 +1,13 @@ + + + + Java Enterprise (Topjava) + + +

Проект Java Enterprise (Topjava)

+
+ + + diff --git a/src/main/webapp/users.jsp b/src/main/webapp/users.jsp new file mode 100644 index 000000000000..650c8dda479c --- /dev/null +++ b/src/main/webapp/users.jsp @@ -0,0 +1,11 @@ +<%@ page contentType="text/html;charset=UTF-8" %> + + + Users + + +

Home

+
+

Users

+ + \ No newline at end of file From fc79d8dcf8fc3fda67df0a51dd743d474d6de83c Mon Sep 17 00:00:00 2001 From: Arsegg Date: Sat, 4 Jun 2022 13:53:21 +0400 Subject: [PATCH 07/11] 1_opt_3_HW0_opt2 --- pom.xml | 7 +++++++ .../ru/javawebinar/topjava/web/UserServlet.java | 15 +++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 src/main/java/ru/javawebinar/topjava/web/UserServlet.java diff --git a/pom.xml b/pom.xml index b4426c1aa2d6..3cd703f93681 100644 --- a/pom.xml +++ b/pom.xml @@ -34,6 +34,13 @@ + + + javax.servlet + javax.servlet-api + 4.0.1 + provided + diff --git a/src/main/java/ru/javawebinar/topjava/web/UserServlet.java b/src/main/java/ru/javawebinar/topjava/web/UserServlet.java new file mode 100644 index 000000000000..76056e06c019 --- /dev/null +++ b/src/main/java/ru/javawebinar/topjava/web/UserServlet.java @@ -0,0 +1,15 @@ +package ru.javawebinar.topjava.web; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +public class UserServlet extends HttpServlet { + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + request.getRequestDispatcher("/users.jsp").forward(request, response); + } +} From 78dcbef0b2cb19a453c54e678c30b874d9a35f82 Mon Sep 17 00:00:00 2001 From: Arsegg Date: Sat, 4 Jun 2022 13:53:57 +0400 Subject: [PATCH 08/11] 1_4_forward_to_redirect --- pom.xml | 2 +- src/main/java/ru/javawebinar/topjava/web/UserServlet.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 3cd703f93681..f7abfea2b739 100644 --- a/pom.xml +++ b/pom.xml @@ -19,7 +19,7 @@ topjava - install + package org.apache.maven.plugins diff --git a/src/main/java/ru/javawebinar/topjava/web/UserServlet.java b/src/main/java/ru/javawebinar/topjava/web/UserServlet.java index 76056e06c019..11f282bac482 100644 --- a/src/main/java/ru/javawebinar/topjava/web/UserServlet.java +++ b/src/main/java/ru/javawebinar/topjava/web/UserServlet.java @@ -10,6 +10,7 @@ public class UserServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - request.getRequestDispatcher("/users.jsp").forward(request, response); +// request.getRequestDispatcher("/users.jsp").forward(request, response); + response.sendRedirect("users.jsp"); } } From 8a20076550b9de5ceec377f71a7a82fc68011590 Mon Sep 17 00:00:00 2001 From: Arsegg Date: Sat, 4 Jun 2022 13:54:34 +0400 Subject: [PATCH 09/11] 1_5_logging --- pom.xml | 19 ++++++++++++ .../javawebinar/topjava/web/UserServlet.java | 7 +++++ src/main/resources/logback.xml | 29 +++++++++++++++++++ 3 files changed, 55 insertions(+) create mode 100644 src/main/resources/logback.xml diff --git a/pom.xml b/pom.xml index f7abfea2b739..e8dc01d332cf 100644 --- a/pom.xml +++ b/pom.xml @@ -15,6 +15,10 @@ 1.8 UTF-8 UTF-8 + + + 1.2.11 + 1.7.36 @@ -34,6 +38,21 @@ + + + org.slf4j + slf4j-api + ${slf4j.version} + compile + + + + ch.qos.logback + logback-classic + ${logback.version} + runtime + + javax.servlet diff --git a/src/main/java/ru/javawebinar/topjava/web/UserServlet.java b/src/main/java/ru/javawebinar/topjava/web/UserServlet.java index 11f282bac482..ef52d67576c0 100644 --- a/src/main/java/ru/javawebinar/topjava/web/UserServlet.java +++ b/src/main/java/ru/javawebinar/topjava/web/UserServlet.java @@ -1,15 +1,22 @@ package ru.javawebinar.topjava.web; +import org.slf4j.Logger; + import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; +import static org.slf4j.LoggerFactory.getLogger; + public class UserServlet extends HttpServlet { + private static final Logger log = getLogger(UserServlet.class); @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + log.debug("redirect to users"); + // request.getRequestDispatcher("/users.jsp").forward(request, response); response.sendRedirect("users.jsp"); } diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml new file mode 100644 index 000000000000..e9b900b26669 --- /dev/null +++ b/src/main/resources/logback.xml @@ -0,0 +1,29 @@ + + + + + + + + ${TOPJAVA_ROOT}/log/topjava.log + + + UTF-8 + %date %-5level %logger{0} [%file:%line] %msg%n + + + + + + UTF-8 + %-5level %logger{0} [%file:%line] %msg%n + + + + + + + + + + From 1909b6b7ae9b64aaa19ccb9af8c6513d70c3b3d1 Mon Sep 17 00:00:00 2001 From: Arsegg Date: Wed, 8 Jun 2022 19:57:38 +0400 Subject: [PATCH 10/11] Revert "1_opt_3_HW0_opt2" This reverts commit 3a2e81cb3c4b039dbc085028f2bd78ebc9037b33. --- .../ru/javawebinar/topjava/model/MealTo.java | 15 +- .../javawebinar/topjava/util/MealsUtil.java | 312 +----------------- 2 files changed, 3 insertions(+), 324 deletions(-) diff --git a/src/main/java/ru/javawebinar/topjava/model/MealTo.java b/src/main/java/ru/javawebinar/topjava/model/MealTo.java index 35551cda8020..07f04f8dbb9f 100644 --- a/src/main/java/ru/javawebinar/topjava/model/MealTo.java +++ b/src/main/java/ru/javawebinar/topjava/model/MealTo.java @@ -9,10 +9,7 @@ public class MealTo { private final int calories; -// private final AtomicBoolean excess; // filteredByAtomic (or any ref type, e.g. boolean[1]) -// private final Boolean excess; // filteredByReflection -// private final Supplier excess; // filteredByClosure - private boolean excess; + private final boolean excess; public MealTo(LocalDateTime dateTime, String description, int calories, boolean excess) { this.dateTime = dateTime; @@ -21,16 +18,6 @@ public MealTo(LocalDateTime dateTime, String description, int calories, boolean this.excess = excess; } -// for filteredByClosure -// public Boolean getExcess() { -// return excess.get(); -// } - - // for filteredBySetterRecursion - public void setExcess(boolean excess) { - this.excess = excess; - } - @Override public String toString() { return "MealTo{" + diff --git a/src/main/java/ru/javawebinar/topjava/util/MealsUtil.java b/src/main/java/ru/javawebinar/topjava/util/MealsUtil.java index a7e7cca3222c..48c2e96ef536 100644 --- a/src/main/java/ru/javawebinar/topjava/util/MealsUtil.java +++ b/src/main/java/ru/javawebinar/topjava/util/MealsUtil.java @@ -8,20 +8,12 @@ import java.time.LocalTime; import java.time.Month; import java.util.*; -import java.util.concurrent.*; -import java.util.concurrent.locks.ReentrantLock; -import java.util.function.Consumer; -import java.util.function.Predicate; -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; import static ru.javawebinar.topjava.util.TimeUtil.isBetweenHalfOpen; public class MealsUtil { - public static void main(String[] args) throws InterruptedException { + public static void main(String[] args) { List meals = Arrays.asList( new Meal(LocalDateTime.of(2020, Month.JANUARY, 30, 10, 0), "Завтрак", 500), new Meal(LocalDateTime.of(2020, Month.JANUARY, 30, 13, 0), "Обед", 1000), @@ -39,34 +31,13 @@ public static void main(String[] args) throws InterruptedException { mealsTo.forEach(System.out::println); System.out.println(filteredByCycles(meals, startTime, endTime, 2000)); - - // Optional2 recursion - System.out.println(filteredByRecursion(meals, startTime, endTime, 2000)); - System.out.println(filteredBySetterRecursion(meals, startTime, endTime, 2000)); - System.out.println(filteredByRecursionWithCycleAndRunnable(meals, startTime, endTime, 2000)); - - // Optional2 reference type - // System.out.println(filteredByAtomic(meals, startTime, endTime, 2000)); // or boolean[1] - // System.out.println(filteredByReflection(meals, startTime, endTime, 2000)); - - // Optional2 delayed execution - // System.out.println(filteredByClosure(meals, startTime, endTime, 2000)); - System.out.println(filteredByExecutor(meals, startTime, endTime, 2000)); - System.out.println(filteredByLock(meals, startTime, endTime, 2000)); - System.out.println(filteredByCountDownLatch(meals, startTime, endTime, 2000)); - System.out.println(filteredByPredicate(meals, startTime, endTime, 2000)); - System.out.println(filteredByConsumerChain(meals, startTime, endTime, 2000)); - - // Optional2 streams - System.out.println(filteredByFlatMap(meals, startTime, endTime, 2000)); - System.out.println(filteredByCollector(meals, startTime, endTime, 2000)); } public static List filteredByStreams(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { Map caloriesSumByDate = meals.stream() .collect( Collectors.groupingBy(Meal::getDate, Collectors.summingInt(Meal::getCalories)) - // Collectors.toMap(Meal::getDate, Meal::getCalories, Integer::sum) +// Collectors.toMap(Meal::getDate, Meal::getCalories, Integer::sum) ); return meals.stream() @@ -89,285 +60,6 @@ public static List filteredByCycles(List meals, LocalTime startTim return mealsTo; } - private static List filteredByRecursion(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { - ArrayList result = new ArrayList<>(); - filterWithRecursion(new LinkedList<>(meals), startTime, endTime, caloriesPerDay, new HashMap<>(), result); - return result; - } - - private static void filterWithRecursion(LinkedList meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay, - Map dailyCaloriesMap, List result) { - if (meals.isEmpty()) return; - - Meal meal = meals.pop(); - dailyCaloriesMap.merge(meal.getDate(), meal.getCalories(), Integer::sum); - filterWithRecursion(meals, startTime, endTime, caloriesPerDay, dailyCaloriesMap, result); - if (isBetweenHalfOpen(meal.getTime(), startTime, endTime)) { - result.add(createTo(meal, dailyCaloriesMap.get(meal.getDate()) > caloriesPerDay)); - } - } - - private static List filteredBySetterRecursion(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { - class MealNode { - private final MealNode prev; - private final MealTo mealTo; - - public MealNode(MealTo mealTo, MealNode prev) { - this.mealTo = mealTo; - this.prev = prev; - } - - public void setExcess() { - mealTo.setExcess(true); - if (prev != null) { - prev.setExcess(); - } - } - } - - Map caloriesSumByDate = new HashMap<>(); - Map mealNodeByDate = new HashMap<>(); - List mealsTo = new ArrayList<>(); - meals.forEach(meal -> { - LocalDate localDate = meal.getDate(); - boolean excess = caloriesSumByDate.merge(localDate, meal.getCalories(), Integer::sum) > caloriesPerDay; - if (TimeUtil.isBetweenHalfOpen(meal.getTime(), startTime, endTime)) { - MealTo mealTo = createTo(meal, excess); - mealsTo.add(mealTo); - if (!excess) { - MealNode prevNode = mealNodeByDate.get(localDate); - mealNodeByDate.put(localDate, new MealNode(mealTo, prevNode)); - } - } - if (excess) { - MealNode mealNode = mealNodeByDate.remove(localDate); - if (mealNode != null) { - // recursive set for all interval day meals - mealNode.setExcess(); - } - } - }); - return mealsTo; - } - - public static List filteredByRecursionWithCycleAndRunnable(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { - Map caloriesSumByDate = new HashMap<>(); - List mealsTo = new ArrayList<>(); - Iterator iterator = meals.iterator(); - - new Runnable() { - @Override - public void run() { - while (iterator.hasNext()) { - Meal meal = iterator.next(); - caloriesSumByDate.merge(meal.getDate(), meal.getCalories(), Integer::sum); - if (isBetweenHalfOpen(meal.getTime(), startTime, endTime)) { - run(); - mealsTo.add(createTo(meal, caloriesSumByDate.get(meal.getDate()) > caloriesPerDay)); - } - } - } - }.run(); - return mealsTo; - } - - /* - private static List filteredByAtomic(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { - Map caloriesSumByDate = new HashMap<>(); - Map exceededMap = new HashMap<>(); - - List mealsTo = new ArrayList<>(); - meals.forEach(meal -> { - AtomicBoolean wrapBoolean = exceededMap.computeIfAbsent(meal.getDate(), date -> new AtomicBoolean()); - Integer dailyCalories = caloriesSumByDate.merge(meal.getDate(), meal.getCalories(), Integer::sum); - if (dailyCalories > caloriesPerDay) { - wrapBoolean.set(true); - } - if (isBetween(meal.getTime(), startTime, endTime)) { - mealsTo.add(createTo(meal, wrapBoolean)); // also change createTo and MealTo.excess - } - }); - return mealsTo; - } - - private static List filteredByReflection(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) throws NoSuchFieldException, IllegalAccessException { - Map caloriesSumByDate = new HashMap<>(); - Map exceededMap = new HashMap<>(); - Field field = Boolean.class.getDeclaredField("value"); - field.setAccessible(true); - - List mealsTo = new ArrayList<>(); - for (Meal meal : meals) { - Boolean mutableBoolean = exceededMap.computeIfAbsent(meal.getDate(), date -> new Boolean(false)); - Integer dailyCalories = caloriesSumByDate.merge(meal.getDate(), meal.getCalories(), Integer::sum); - if (dailyCalories > caloriesPerDay) { - field.setBoolean(mutableBoolean, true); - } - if (isBetweenHalfOpen(meal.getTime(), startTime, endTime)) { - mealsTo.add(createTo(meal, mutableBoolean)); // also change createTo and MealTo.excess - } - } - return mealsTo; - } - - private static List filteredByClosure(List mealList, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { - final Map caloriesSumByDate = new HashMap<>(); - List mealsTo = new ArrayList<>(); - mealList.forEach(meal -> { - caloriesSumByDate.merge(meal.getDate(), meal.getCalories(), Integer::sum); - if (isBetween(meal.getTime(), startTime, endTime)) { - mealsTo.add(createTo(meal, () -> (caloriesSumByDate.get(meal.getDate()) > caloriesPerDay))); // also change createTo and MealTo.excess - } - } - ); - return mealsTo; - } - */ - - private static List filteredByExecutor(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) throws InterruptedException { - Map caloriesSumByDate = new HashMap<>(); - List> tasks = new ArrayList<>(); - final List mealsTo = Collections.synchronizedList(new ArrayList<>()); - - meals.forEach(meal -> { - caloriesSumByDate.merge(meal.getDate(), meal.getCalories(), Integer::sum); - if (isBetweenHalfOpen(meal.getTime(), startTime, endTime)) { - tasks.add(() -> { - mealsTo.add(createTo(meal, caloriesSumByDate.get(meal.getDate()) > caloriesPerDay)); - return null; - }); - } - }); - ExecutorService executorService = Executors.newCachedThreadPool(); - executorService.invokeAll(tasks); - executorService.shutdown(); - return mealsTo; - } - - public static List filteredByLock(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) throws InterruptedException { - Map caloriesSumByDate = new HashMap<>(); - List mealsTo = new ArrayList<>(); - ExecutorService executor = Executors.newCachedThreadPool(); - ReentrantLock lock = new ReentrantLock(); - lock.lock(); - for (Meal meal : meals) { - caloriesSumByDate.merge(meal.getDateTime().toLocalDate(), meal.getCalories(), Integer::sum); - if (isBetweenHalfOpen(meal.getDateTime().toLocalTime(), startTime, endTime)) - executor.submit(() -> { - lock.lock(); - mealsTo.add(createTo(meal, caloriesSumByDate.get(meal.getDateTime().toLocalDate()) > caloriesPerDay)); - lock.unlock(); - }); - } - lock.unlock(); - executor.shutdown(); - executor.awaitTermination(5, TimeUnit.SECONDS); - return mealsTo; - } - - private static List filteredByCountDownLatch(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) throws InterruptedException { - Map caloriesSumByDate = new HashMap<>(); - List mealsTo = Collections.synchronizedList(new ArrayList<>()); - CountDownLatch latchCycles = new CountDownLatch(meals.size()); - CountDownLatch latchTasks = new CountDownLatch(meals.size()); - for (Meal meal : meals) { - caloriesSumByDate.merge(meal.getDateTime().toLocalDate(), meal.getCalories(), Integer::sum); - if (isBetweenHalfOpen(meal.getDateTime().toLocalTime(), startTime, endTime)) { - new Thread(() -> { - try { - latchCycles.await(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - mealsTo.add(createTo(meal, caloriesSumByDate.get(meal.getDateTime().toLocalDate()) > caloriesPerDay)); - latchTasks.countDown(); - }).start(); - } else { - latchTasks.countDown(); - } - latchCycles.countDown(); - } - latchTasks.await(); - return mealsTo; - } - - public static List filteredByPredicate(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { - Map caloriesSumByDate = new HashMap<>(); - List mealsTo = new ArrayList<>(); - - Predicate predicate = b -> true; - for (Meal meal : meals) { - caloriesSumByDate.merge(meal.getDateTime().toLocalDate(), meal.getCalories(), Integer::sum); - if (TimeUtil.isBetweenHalfOpen(meal.getDateTime().toLocalTime(), startTime, endTime)) { - predicate = predicate.and(b -> mealsTo.add(createTo(meal, caloriesSumByDate.get(meal.getDateTime().toLocalDate()) > caloriesPerDay))); - } - } - predicate.test(true); - return mealsTo; - } - - public static List filteredByConsumerChain(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { - Map caloriesPerDays = new HashMap<>(); - List result = new ArrayList<>(); - Consumer consumer = dummy -> { - }; - - for (Meal meal : meals) { - caloriesPerDays.merge(meal.getDate(), meal.getCalories(), Integer::sum); - if (TimeUtil.isBetweenHalfOpen(meal.getTime(), startTime, endTime)) { - consumer = consumer.andThen(dummy -> result.add(createTo(meal, caloriesPerDays.get(meal.getDateTime().toLocalDate()) > caloriesPerDay))); - } - } - consumer.accept(null); - return result; - } - - private static List filteredByFlatMap(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { - Collection> list = meals.stream() - .collect(Collectors.groupingBy(Meal::getDate)).values(); - - return list.stream() - .flatMap(dayMeals -> { - boolean excess = dayMeals.stream().mapToInt(Meal::getCalories).sum() > caloriesPerDay; - return dayMeals.stream().filter(meal -> - isBetweenHalfOpen(meal.getTime(), startTime, endTime)) - .map(meal -> createTo(meal, excess)); - }).collect(toList()); - } - - private static List filteredByCollector(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { - final class Aggregate { - private final List dailyMeals = new ArrayList<>(); - private int dailySumOfCalories; - - private void accumulate(Meal meal) { - dailySumOfCalories += meal.getCalories(); - if (isBetweenHalfOpen(meal.getTime(), 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 finisher() { - final boolean excess = dailySumOfCalories > caloriesPerDay; - return dailyMeals.stream().map(meal -> createTo(meal, excess)); - } - } - - Collection> 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()); - } - private static MealTo createTo(Meal meal, boolean excess) { return new MealTo(meal.getDateTime(), meal.getDescription(), meal.getCalories(), excess); } From 27ada5bfbb87397e29a845d37c591030bab213d4 Mon Sep 17 00:00:00 2001 From: Arsegg Date: Wed, 8 Jun 2022 19:57:40 +0400 Subject: [PATCH 11/11] Revert "1_opt_2_HW0_cycles" This reverts commit 7f24adcc543e7824ba7ad0d90b12fdcd0d7fb68d. --- .../javawebinar/topjava/util/MealsUtil.java | 29 ++++--------------- 1 file changed, 5 insertions(+), 24 deletions(-) diff --git a/src/main/java/ru/javawebinar/topjava/util/MealsUtil.java b/src/main/java/ru/javawebinar/topjava/util/MealsUtil.java index 48c2e96ef536..c29e1fbbb077 100644 --- a/src/main/java/ru/javawebinar/topjava/util/MealsUtil.java +++ b/src/main/java/ru/javawebinar/topjava/util/MealsUtil.java @@ -7,11 +7,11 @@ import java.time.LocalDateTime; import java.time.LocalTime; import java.time.Month; -import java.util.*; +import java.util.Arrays; +import java.util.List; +import java.util.Map; import java.util.stream.Collectors; -import static ru.javawebinar.topjava.util.TimeUtil.isBetweenHalfOpen; - public class MealsUtil { public static void main(String[] args) { List meals = Arrays.asList( @@ -24,13 +24,8 @@ public static void main(String[] args) { new Meal(LocalDateTime.of(2020, Month.JANUARY, 31, 20, 0), "Ужин", 410) ); - final LocalTime startTime = LocalTime.of(7, 0); - final LocalTime endTime = LocalTime.of(12, 0); - - List mealsTo = filteredByStreams(meals, startTime, endTime, 2000); + List mealsTo = filteredByStreams(meals, LocalTime.of(7, 0), LocalTime.of(12, 0), 2000); mealsTo.forEach(System.out::println); - - System.out.println(filteredByCycles(meals, startTime, endTime, 2000)); } public static List filteredByStreams(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { @@ -41,25 +36,11 @@ public static List filteredByStreams(List meals, LocalTime startTi ); return meals.stream() - .filter(meal -> isBetweenHalfOpen(meal.getTime(), startTime, endTime)) + .filter(meal -> TimeUtil.isBetweenHalfOpen(meal.getTime(), startTime, endTime)) .map(meal -> createTo(meal, caloriesSumByDate.get(meal.getDate()) > caloriesPerDay)) .collect(Collectors.toList()); } - public static List filteredByCycles(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { - - final Map caloriesSumByDate = new HashMap<>(); - meals.forEach(meal -> caloriesSumByDate.merge(meal.getDate(), meal.getCalories(), Integer::sum)); - - final List mealsTo = new ArrayList<>(); - meals.forEach(meal -> { - if (isBetweenHalfOpen(meal.getTime(), startTime, endTime)) { - mealsTo.add(createTo(meal, caloriesSumByDate.get(meal.getDate()) > caloriesPerDay)); - } - }); - return mealsTo; - } - private static MealTo createTo(Meal meal, boolean excess) { return new MealTo(meal.getDateTime(), meal.getDescription(), meal.getCalories(), excess); }