使用 Java 8 Streams 从另一个创建对象列表

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35650974/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 16:57:58  来源:igfitidea点击:

Create list of object from another using Java 8 Streams

javajava-stream

提问by Lex Valyaev

I'm trying to understand Java 8 streams. I have two classes:

我正在尝试了解 Java 8 流。我有两个班级:

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 exceedfield should indicate whether the sum of calories for the entire day. This field is the same for all entries for that day.

exceed字段应指示是否为全天的卡路里总和。该字段对于当天的所有条目都是相同的。

I try to get object from List<UserMeal> mealList, group by the day, calculate calories for a period of time, and create List<UserMealWithExceed>:

我尝试从 中获取对象List<UserMeal> mealList,按天分组,计算一段时间内的卡路里,然后创建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 forEachand return collection.

但我不明白如何在其中创建新对象forEach并返回集合。

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

回答by Rafael Teles

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.

如果你想遍历一个列表并创建一个带有“转换”对象的新列表,你应该使用map()stream +的功能collect()。在下面的示例中,我找到所有姓氏为“l1”的人,并将每个人“映射”到一个新的 Employee 实例。

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
}

回答by Robert Br?utigam

What you are possibly looking for is map(). You can "convert" the objects in a stream to another by mapping this way:

您可能正在寻找的是map(). 您可以通过以下方式将流中的对象“转换”为另一个对象:

...
 .map(userMeal -> new UserMealExceed(...))
...

回答by Jónás Balázs

An addition to the solution by @Rafael Teles. The syntactic sugar Collectors.mappingdoes the same in one step:

@Rafael Teles 对解决方案的补充。语法糖Collectors.mapping在一个步骤中完成相同的操作:

//...
List<Employee> employees = persons.stream()
  .filter(p -> p.getLastName().equals("l1"))
  .collect(
    Collectors.mapping(
      p -> new Employee(p.getName(), p.getLastName(), 1000),
      Collectors.toList()));

Detailed example can be found here

可以在此处找到详细示例