Cant get java stream to work with arraylist

Ask Sejsbo :

So, I have been playing around with java streams a bit, and found something very frustrating.

I want to make a list of this type of object (Customer), and after that use a stream to filter out all those objects where glad == false.

package com.company;

public class Customer {

    public String name;
    public int points;
    public boolean glad;

    public Customer(String name, int points, boolean glad) {
        this.name = name;
        this.points = points;
        this.glad = glad;
    }

    public boolean isGlad() {
        return this.glad;
    }
}

Whenever I try doing it with a regular array, everything seems to work just fine:

Customer kunde1 = new Customer("jens", 20, true);
Customer kunde2 = new Customer("marie", 20, false);
Customer kunde3 = new Customer("niels", 20, false);
Customer kunde4 = new Customer("jens", 20, true);
Customer kunde5 = new Customer("jens", 20, true);

Customer[] kunderne = {kunde1,kunde2,kunde3,kunde4,kunde5};

Customer[] filtered = Stream.of(kunderne)
    .filter(Customer::isGlad)
    .toArray(Customer[]::new);

But whenever I try to create the stream from something other than an array, like an ArrayList, I am not able to access the object attributes within my lambda statement

ArrayList<Customer> customers = new ArrayList<>();

Customer kunde1 = new Customer("jens", 20, true);
Customer kunde2 = new Customer("marie", 20, false);
Customer kunde3 = new Customer("niels", 20, false);
Customer kunde4 = new Customer("jens", 20, true);
Customer kunde5 = new Customer("jens", 20, true);

customers.add(kunde1);
customers.add(kunde2);
customers.add(kunde3);
customers.add(kunde4);
customers.add(kunde5);


Customer[] filtered = Stream.of(kunderne)
    .filter(Customer::isGlad)
    .toArray(Customer[]::new);

But this code won't even run. Why does this happen, and why does it only seem to work with arrays?

WJS :

Here is what you wanted to do.

      Customer[] filtered = Stream.of(kunderne).filter(Customer::isGlad).map(
            cust -> new Customer(cust.name, cust.points, cust.glad)).toArray(
                  Customer[]::new);

      for (Customer c : filtered) {
         System.out.println(c.name + " " + c.points + " " + c.glad);
      }

You needed to map the filtered customer to a new customer and then put those in an array. Another option would be to add a constructor that takes an existing customer and uses that as input. Here is how that would work.

      Customer[] filtered = Stream.of(kunderne).filter(Customer::isGlad).map(
            Customer::new).toArray(Customer[]::new);

      for (Customer c : filtered) {
         System.out.println(c.name + " " + c.points + " " + c.glad);
      }

     // modified customer class with additional constructor

    class Customer {
       public String  name;
       public int     points;
       public boolean glad;

       public Customer(String name, int points, boolean glad) {
          this.name = name;
          this.points = points;
          this.glad = glad;
       }

       public Customer(Customer cust) {
          this(cust.name, cust.points, cust.glad);
       }

       public boolean isGlad() {
          return this.glad;
       }
    } 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325800&siteId=1