3

Problem: I have a list of interface type which i need to convert to list of database DTO before storing in database. I am new to Java 8 streams and map functions so any help would be great.

Research: I tried to use instanceOf in map but i always get compile errors.

Below are the different classes and their hierarchy.

public interface Animal {}

Public Class Cat implements Animal{
    private String name;
    public void getName() {
        return name;
    }
}

Public Class Dog implements Animal{
    private String name;
    public void getName() {
        return name;
    }
}

Public Class DBAnimalDTO{
    private String dbName;
    public void setDbName(String name) {
        this.dbName = name;
    }
}

To map the Dog and Cat classes i had created separate Functions.

Function<Dog, DBAnimalDTO> dogFunction = dog -> {
    DBAnimalDTO dbAnimalDTO = new DBAnimalDTO();
    dbAnimalDTO.setDbName(dog.getName());
    return dbAnimalDTO;
}
Function<Cat, DBAnimalDTO> catFunction = cat -> {
    DBAnimalDTO dbAnimalDTO = new DBAnimalDTO();
    dbAnimalDTO.setDbName(cat.getName());
    return dbAnimalDTO;
}

Using streams i tried to use different map functions based on Object type.

List<Animal> animals = new ArrayList();

List<DBAnimalDTO> dbAnimals = animals.stream().map(animal -> {
    if(animal instanceOf Dog) {
        return dogFunction;
    } else {
        return catFunction;
    }
}).collect(Collectors.<DBAnimalDTO> toList());

I always get compile issue in Collectors.toList(). How do i fix this issue?

Also, any advise on if this is a good design pattern to transform list in this scenario would also be great.

2
  • The Java way of doing this would be to add a method like DBAnimalDTO toDTO() to the interface and to implement it in the two classes. Then you can simply do animal.toDTO() Commented Feb 12, 2019 at 6:04
  • If getName was declared in the Animal interface, you wouldn't have this problem. Polymorphism! Commented Feb 12, 2019 at 7:48

1 Answer 1

5

You need to apply the function that you've created as:

List<DBAnimalDTO> dbAnimals = animals.stream().map(animal -> {
    if (animal instanceof Dog) {
        return dogFunction.apply((Dog) animal);
    } else {
        return catFunction.apply((Cat) animal);
    }
}).collect(Collectors.toList());

On the other hand, using a constructor in the DBAnimalDTO class as:

public DBAnimalDTO(String dbName) {
    this.dbName = dbName;
}

you can update your functions to be more cleaner as:

Function<Dog, DBAnimalDTO> dogFunction = dog -> new DBAnimalDTO(dog.getName());
Function<Cat, DBAnimalDTO> catFunction = cat -> new DBAnimalDTO(cat.getName());
Sign up to request clarification or add additional context in comments.

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.