3

Let's say I have such object:

public class Customer {

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

and I have a List<Customer>. I would like to split such list with Java streams so that I would get a list of ids List<Integer>, countries List<String>, customerIds List<Integer> etc.

I know that I could do it as simple as making 6 streams such as:

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

but doing it that many times that I have fields seems pretty dull. I was thinking about custom Collector but I could not come up with anything useful that would be both neat and efficient.

2
  • What about initializing 3 lists and using customerList.foreach and add each member to relevant one Commented Feb 17, 2020 at 16:06
  • Probably simple forEach adding to respective lists would be better choice Commented Feb 17, 2020 at 16:09

2 Answers 2

6

For a type safe solution, you’d need to define a class holding the desired results. This type may also provide the necessary methods for adding another Customer or partial result:

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

Then, you can collect all results like

CustomerProperties all = customers.stream()
    .collect(CustomerProperties::new, CustomerProperties::add, CustomerProperties::add);
Sign up to request clarification or add additional context in comments.

Comments

3

You can create a method like so:

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

Then just call your method with the field you want:

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.