I'm trying to understand Java 8 streams. I have two classes:
public class UserMeal { protected final LocalDateTime dateTime; protected final String description; protected 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; } }
and:
public class UserMealWithExceed { protected final LocalDateTime dateTime; protected final String description; protected final int calories; protected final boolean exceed; public UserMealWithExceed(LocalDateTime dateTime, String description, int calories, boolean exceed) { this.dateTime = dateTime; this.description = description; this.calories = calories; this.exceed = exceed; } }
The exceed
field should indicate whether the sum of calories for the entire day. This field is the same for all entries for that day.
I try to get object from List<UserMeal> mealList
, group by the day, calculate calories for a period of time, and create List<UserMealWithExceed>
:
public static List<UserMealWithExceed> getFilteredMealsWithExceeded(List<UserMeal> mealList, LocalTime startTime, LocalTime endTime, int caloriesPerDay) { return mealList.stream() .filter(userMeal -> userMeal.getDateTime().toLocalTime().isAfter(startTime)&&userMeal.getDateTime().toLocalTime().isBefore(endTime)) .collect(Collectors.groupingBy(userMeal -> userMeal.getDateTime().getDayOfMonth(), Collectors.summingInt(userMeal -> userMeal.getCalories()))) .forEach( ????? ); }
but I don't understand how to create new object in forEach
and return collection.
How I see in pseudocode:
.foreach( if (sumCalories>caloriesPerDay) {return new UserMealWithExceed(userMeal.getdateTime, usermeal.getDescription, usermeal.getCalories, true);} else {return new UserMealWithExceed(userMeal.getdateTime, usermeal.getDescription, usermeal.getCalories, false) } )//foreach
In Java 8, we have the ability to convert an object to another type using a map() method of Stream object with a lambda expression. The map() method is an intermediate operation in a stream object, so we need a terminal method to complete the stream.
Create a class. Create a list of the class objects from an array using the asList method. Convert list of objects to a stream of objects using the stream() method. Use the collect(Collectors.
Stream class has toArray() method to convert Stream to Array, but there is no similar method to convert Stream to List or Set. Java has a design philosophy of providing conversion methods between new and old API classes e.g. when they introduced Path class in JDK 7, which is similar to java.
Convert Stream into List using List. stream() method.
If you want to iterate over a list and create a new list with "transformed" objects, you should use the map()
function of stream + collect()
. In the following example I find all people with the last name "l1" and each person I'm "mapping" to a new Employee instance.
public class Test { public static void main(String[] args) { List<Person> persons = Arrays.asList( new Person("e1", "l1"), new Person("e2", "l1"), new Person("e3", "l2"), new Person("e4", "l2") ); List<Employee> employees = persons.stream() .filter(p -> p.getLastName().equals("l1")) .map(p -> new Employee(p.getName(), p.getLastName(), 1000)) .collect(Collectors.toList()); System.out.println(employees); } } class Person { private String name; private String lastName; public Person(String name, String lastName) { this.name = name; this.lastName = lastName; } // Getter & Setter } class Employee extends Person { private double salary; public Employee(String name, String lastName, double salary) { super(name, lastName); this.salary = salary; } // Getter & Setter }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With