diff --git a/README.md b/README.md
index 228b708b7094..6b840eac3b03 100644
--- a/README.md
+++ b/README.md
@@ -69,6 +69,9 @@ Java Enterprise Online Project
- Выполнить задание и залить на GitHub (commit + push)
- Переключиться в основную ветку проекта master.
+##  4. [Тех.задание: библия или допускаются изменения. Полуоткрытый интервал.](https://drive.google.com/file/d/123XyBYVeKLC3ZcRr_dUkwyvO9NC6WLkY/view?usp=sharing)
+- [Типы промежутков](https://ru.wikipedia.org/wiki/Промежуток_(математика))
+
##  Домашнее задание HW0
```
Реализовать метод `UserMealsUtil.filteredByCycles` через циклы (`forEach`):
@@ -172,7 +175,7 @@ Java Enterprise Online Project
#### Java (базовые вещи)
- Интуит. Программирование на Java
- 1й урок MasterJava: Многопоточность
-- Основы Java garbage collection
+- [Основы Java garbage collection](http://web.archive.org/web/20180831013112/https://ggenikus.github.io/blog/2014/05/04/gc)
- Размер Java объектов
- Введение в Java Reflection API
- Структуры данных в картинках
diff --git a/src/main/java/ru/javawebinar/topjava/Main.java b/src/main/java/ru/javawebinar/topjava/Main.java
index c2f9cc618f7c..ff53b0ef5e4f 100644
--- a/src/main/java/ru/javawebinar/topjava/Main.java
+++ b/src/main/java/ru/javawebinar/topjava/Main.java
@@ -1,5 +1,10 @@
package ru.javawebinar.topjava;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.stream.Stream;
+
/**
* @see Demo application
* @see Initial project
@@ -7,5 +12,21 @@
public class Main {
public static void main(String[] args) {
System.out.format("Hello TopJava Enterprise!");
+
+ HashMap l = new HashMap<>();
+ l.put(123, 4);
+ l.put(321, 5);
+
+ System.out.println(l.size());
+
+ /* Stream.of("dd2", "aa2", "bb1", "bb3", "cc4")
+ .map(s -> {
+ System.out.println("map: " + s);
+ return s.toUpperCase();
+ })
+ .anyMatch(s -> {
+ System.out.println("anyMatch: " + s);
+ return s.startsWith("A");
+ });*/
}
}
diff --git a/src/main/java/ru/javawebinar/topjava/model/Meal.java b/src/main/java/ru/javawebinar/topjava/model/Meal.java
new file mode 100644
index 000000000000..f546cef0f74a
--- /dev/null
+++ b/src/main/java/ru/javawebinar/topjava/model/Meal.java
@@ -0,0 +1,29 @@
+package ru.javawebinar.topjava.model;
+
+import java.time.LocalDateTime;
+
+public class Meal {
+ private final LocalDateTime dateTime;
+
+ private final String description;
+
+ private final int calories;
+
+ public Meal(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/MealTo.java b/src/main/java/ru/javawebinar/topjava/model/MealTo.java
new file mode 100644
index 000000000000..4ad8718c50e7
--- /dev/null
+++ b/src/main/java/ru/javawebinar/topjava/model/MealTo.java
@@ -0,0 +1,30 @@
+package ru.javawebinar.topjava.model;
+
+import java.time.LocalDateTime;
+
+public class MealTo {
+ private final LocalDateTime dateTime;
+
+ private final String description;
+
+ private final int calories;
+
+ private boolean excess;
+
+ public MealTo(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..3d536a5c5ef2
--- /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 isBetweenInclusive(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..bc9f21d235c3
--- /dev/null
+++ b/src/main/java/ru/javawebinar/topjava/util/UserMealsUtil.java
@@ -0,0 +1,84 @@
+package ru.javawebinar.topjava.util;
+
+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.*;
+import java.util.stream.Collectors;
+
+public class UserMealsUtil {
+ 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)
+ );
+
+ LocalTime dateStart = LocalTime.of(7, 0);
+ LocalTime dateEnd = LocalTime.of(12, 0);
+ Integer caloriesPerDay = 2000;
+
+ filteredByCycles(meals, dateStart, dateEnd, caloriesPerDay).forEach(System.out::println);
+
+ System.out.println("=============");
+
+ filteredByStreams(meals, dateStart, dateEnd, caloriesPerDay).forEach(System.out::println);
+
+ System.out.println("=============");
+
+ filteredByCycles2(meals, dateStart, dateEnd, caloriesPerDay).forEach(System.out::println);
+ }
+
+ public static List filteredByCycles(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) {
+ Map excessList = new HashMap<>();
+ meals.forEach(mealItem -> {
+ excessList.merge(mealItem.getDateTime().toLocalDate(), mealItem.getCalories(), Integer::sum);
+ });
+
+ List resultMeals = new ArrayList<>();
+ meals.forEach(mealItem -> {
+ if(TimeUtil.isBetweenInclusive(mealItem.getDateTime().toLocalTime(), startTime, endTime)){
+ resultMeals.add(new MealTo(mealItem.getDateTime(), mealItem.getDescription(), mealItem.getCalories(), excessList.get(mealItem.getDateTime().toLocalDate()) > caloriesPerDay));
+ }
+ });
+
+ return resultMeals;
+ }
+
+ public static List filteredByStreams(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) {
+ Map caloriesSumByDate = meals.stream()
+ .collect(Collectors.groupingBy(um -> um.getDateTime().toLocalDate(), Collectors.summingInt(Meal::getCalories)));
+
+ return meals.stream()
+ .filter(mealItem -> TimeUtil.isBetweenInclusive(mealItem.getDateTime().toLocalTime(), startTime, endTime))
+ .map(mealItem -> new MealTo(mealItem.getDateTime(), mealItem.getDescription(), mealItem.getCalories(),
+ caloriesSumByDate.get(mealItem.getDateTime().toLocalDate()) > caloriesPerDay
+ ))
+ .collect(Collectors.toList());
+ }
+
+ public static List filteredByCycles2(List meals, LocalTime startTime, LocalTime endTime, int caloriesPerDay) {
+ Map excessList = new HashMap<>();
+ for (Meal meal : meals){
+ LocalDate lDate= meal.getDateTime().toLocalDate();
+ excessList.put(lDate, excessList.getOrDefault(lDate, 0) + meal.getCalories());
+ }
+
+ List resultMeals = new ArrayList<>();
+ for (Meal mealItem : meals){
+ if(TimeUtil.isBetweenInclusive(mealItem.getDateTime().toLocalTime(), startTime, endTime)) {
+ resultMeals.add(new MealTo(mealItem.getDateTime(), mealItem.getDescription(), mealItem.getCalories(), excessList.getOrDefault(mealItem.getDateTime().toLocalDate(), 0) > caloriesPerDay));
+ }
+ }
+
+ return resultMeals;
+ }
+}