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