【问题标题】:Create list of object from another using Java 8 Streams使用 Java 8 Streams 从另一个创建对象列表
【发布时间】:2016-02-26 11:50:56
【问题描述】:

我正在尝试理解 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;
    }
}

和:

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;
    }
}

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

我尝试从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( ????? );
}

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

我在伪代码中的看法:

.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

【问题讨论】:

  • 简单地说,不要使用forEachStream 支持的操作比这个多。

标签: java java-stream


【解决方案1】:

如果您想遍历一个列表并使用“转换”对象创建一个新列表,您应该使用流的map() 函数+collect()。在下面的示例中,我找到所有姓氏为“l1”的人,以及我“映射”到新员工实例的每个人。

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
}

【讨论】:

  • 完美运行!我使用类似的模式将数据库实体列表转换为 DTO
  • 如果 Employee 只有一个无参数的构造函数呢?
  • @csmith49 您可以实例化对象并在map 函数中调用set 方法。您可以在 tutorials.jenkov.com/java/lambda-expressions.htmlbaeldung.com/java-8-lambda-expressions-tips 上更好地了解 lambda 表达式
  • 是的,谢谢,我直到现在才看到您的消息,但昨天自己解决了,很高兴知道这是正确的方法: List employeeList = persons.stream() .filter(p -> p.getLastName().equals("l1")) .map(p -> { Employee e = new Employee(); e.setName(p.getName()); e.setSalary(p .getSalary()); return e; }) .collect(Collectors.toList());
  • 您好,感谢您的回答,但是如何返回多个对象,例如:.map(p -> { return p + new Employee(p.getName(), p.getLastName(), 1000) })。因为我需要用 p 返回新对象。
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    @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()));
    

    详细例子可以看here

    【讨论】:

      【解决方案4】:

      我更喜欢用经典的方式解决这个问题,创建一个我想要的数据类型的新数组:

      List<MyNewType> newArray = new ArrayList<>();
      myOldArray.forEach(info -> newArray.add(objectMapper.convertValue(info, MyNewType.class)));
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-14
        • 2019-06-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-11-14
        • 1970-01-01
        相关资源
        最近更新 更多