【问题标题】:Split list of objects into multiple lists of fields values using Java streams使用 Java 流将对象列表拆分为多个字段值列表
【发布时间】:2020-02-17 16:02:40
【问题描述】:

假设我有这样的对象:

public class Customer {

    private Integer id;
    private String country;
    private Integer customerId;
    private String name;
    private String surname;
    private Date dateOfBirth;
}

我有一个List<Customer>。我想用 Java 流拆分这样的列表,以便获得 ids List<Integer>、国家 List<String>、customerIds List<Integer> 等列表。

我知道我可以像制作 6 个流一样简单,例如:

List<Integer> idsList = customerList.stream()
        .map(Customer::getId)
        .collect(Collectors.toList());

但是在我拥有字段的情况下多次这样做似乎很乏味。我在考虑自定义收集器,但我想不出任何既整洁又高效的有用的东西。

【问题讨论】:

  • 如何初始化 3 个列表并使用 customerList.foreach 并将每个成员添加到相关的列表中
  • 可能很简单的forEach 添加到各自的列表会是更好的选择

标签: java java-8 java-stream


【解决方案1】:

对于类型安全的解决方案,您需要定义一个包含所需结果的类。这种类型还可能提供添加另一个Customer 或部分结果的必要方法:

public class CustomerProperties {
    private List<Integer> id = new ArrayList<>();
    private List<String> country = new ArrayList<>();
    private List<Integer> customerId = new ArrayList<>();
    private List<String> name = new ArrayList<>();
    private List<String> surname = new ArrayList<>();
    private List<Date> dateOfBirth = new ArrayList<>();

    public void add(Customer c) {
        id.add(c.getId());
        country.add(c.getCountry());
        customerId.add(c.getCustomerId());
        name.add(c.getName());
        surname.add(c.getSurname());
        dateOfBirth.add(c.getDateOfBirth());
    }
    public void add(CustomerProperties c) {
        id.addAll(c.id);
        country.addAll(c.country);
        customerId.addAll(c.customerId);
        name.addAll(c.name);
        surname.addAll(c.surname);
        dateOfBirth.addAll(c.dateOfBirth);
    }
}

然后,您可以收集所有结果,例如

CustomerProperties all = customers.stream()
    .collect(CustomerProperties::new, CustomerProperties::add, CustomerProperties::add);

【讨论】:

    【解决方案2】:

    你可以像这样创建一个方法:

    public <T> List<T> getByFieldName(List<Customer> customerList, Function<Customer, T> field){
        return customerList.stream()
                .map(field)
                .collect(Collectors.toList());
    }
    

    然后只需使用您想要的字段调用您的方法:

    List<Integer> ids = getByFieldName(customerList, Customer::getId);
    List<String> countries = getByFieldName(customerList, Customer::getCountry);
    List<Integer> customerIds = getByFieldName(customerList, Customer::getCustomerId);
    //...
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-04
      • 2020-09-04
      • 2018-11-25
      • 2016-02-14
      • 1970-01-01
      • 2019-06-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多