I need to use lambdas to generate some lists of new objects. These new objects inherit some of the traits from the existing ones. Since it's hard to describe it without going into too much delicate details, I'll use an example of a parent and their children.
I want to generate a list of kids based on a list of people (one person = one kid). Kids should inherit only some traits of their parents (in this case, let's say it's a skin colour).
Since I'm somewhat forced to use lambdas (but also want to learn how it works), I've tried the following solution but I can't get over the problem with correct mapping (haven't seen anything like that yet and I'm doing a trial&error method). Probably I have a badly made constructor as well.
public class Kid {
private Colour colour;
private Person person;
public Kid(Person person) {
this.colour = person.getColour();
}
public List<Kid> listOfKids() {
return people.stream()
.map(e -> new Kid(e));
}
}
After map
you have a Stream<Kid>
rather what you need is a List<Kid>
thus you'll need to collect to a list via toList()
.
return people.stream()
.map(e -> new Kid(e))
.collect(Collectors.toList());
or if you need a mutable list then use toCollection
:
return people.stream()
.map(e -> new Kid(e))
.collect(Collectors.toCollection(ArrayList::new));
On another note, you'll need to rethink your design.
Person
to the Kid
constructor just pass a Colour
(assuming it's an enum) otherwise pass String
to represent the colour.Person
attribute inside a Kid
model doesn't make much sense to be honest, it's like saying "a kid has a person"... maybe what you're looking for is a Kid
to inherit from Person
to indicate that "a kid is a person"etc...
Alternatively, you can use method reference in map
as:
public List<Kid> listOfKids(List<Person> people) {
return people.stream()
.map(Kid::new) // your existing constructor resolves this
.collect(Collectors.toList());
}
Do, note that though the constructor implementation though compiles fine, if you want to keep Person
and Colour
as attributes of class Kid
it would make more sense with something like:
// assign both attributes of the class within your constructor
public Kid(Person person, Colour colour) {
this.person = person;
this.colour = colour;
}
and then updating the mapping function as:
public List<Kid> listOfKids(List<Person> people) {
return people.stream()
.map(p -> new Kid(p, p.getColour())) // map to the updated contructor
.collect(Collectors.toList());
}
Kids should inherit only some traits of their parents (in this case, let's say it's a skin colour).
In which case you can use inheritance in java by extending your class Kid from Person class, for which all you would need is
public class Kid extends Person {
public Kid(Colour colour) {
super(colour);
}
}
where class Person definition could be something like:
public class Person {
Colour colour;
public Person(Colour colour) {
this.colour = colour;
}
}
then with this change, your method would look like
public List<Kid> listOfKids(List<Person> people) {
return people.stream()
.map(p -> new Kid(p.getColour()))
.collect(Collectors.toList());
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With