Search code examples
javaclassjava-streamhierarchy

How to get data only from desired classes (stream)?


Employee class:

public abstract class Employee extends Person {
    private final Manager manager;
    private final BigDecimal salary;
    
    protected Employee(String firstName, String surname, LocalDate birth_date, Manager _manager, BigDecimal _salary) {
        super(firstName, surname, birth_date);
        manager = _manager;
        salary = _salary;
        if (manager != null) {
            manager.getSubordinates().add(this);
        }
    }

    ...
}

Worker class:

public class Worker extends Employee {
    private final LocalDate employment_date;
    private BigDecimal bonus;
    
    public Worker(String firstName, String surname, LocalDate birth_date, Manager manager, BigDecimal salary,
                  LocalDate _employment_date, BigDecimal _bonus) {
        super(firstName, surname, birth_date, manager, salary);
        employment_date = _employment_date;
        bonus = _bonus;
    }

    ...
}

Manager class:

public final class Manager extends Worker {
    List<Employee> subordinates = new ArrayList<Employee>();
    
    public Manager(String firstName, String surname, LocalDate birth_date, Manager manager, BigDecimal salary,
                   LocalDate employment_date, BigDecimal bonus) {
        super(firstName, surname, birth_date, manager, salary, employment_date, bonus);
    }

    ...
}

Trainee class:

public class Trainee extends Employee {

    private final LocalDate start_date;
    private final short apprenticeship_length;
    
    public Trainee(String firstName, String surname, LocalDate birth_date, Manager manager, BigDecimal salary,
                   LocalDate _start_date, short _apprenticeship_length) {
        super(firstName, surname, birth_date, manager, salary);
        manager.getSubordinates().add(this);
        start_date = _start_date;
        apprenticeship_length = _apprenticeship_length;
    }
}

payrol class:

public final class PayrollEntry {

    private final Employee _employee;
    private final BigDecimal _salaryPlusBonus;
    
    public PayrollEntry(Employee employee, BigDecimal salary, BigDecimal bonus) {
        _employee = employee;
        _salaryPlusBonus = salary.add(bonus);
    }
}

I have to write the function List<PayrollEntry> payroll(List<Employee> employees) {}. As you can see above, only Worker and Manager can have a bonus, Trainee on the other hand don't, but all of them derive from class Employee (BTW I can't change anything in classes hierarchy because it's my assignment and the hierarchy was written by teacher). I'm supposed to use functional programming techniques to write the function, this is my attempt:

public static List<PayrollEntry> payroll(List<Employee> employees) {
    return employees
            .stream()
            .map(employee -> new PayrollEntry(employee, employee.getSalary(), ((Worker) employee).getBonus()))
            .collect(Collectors.toList());
}

I understand why it gives me a ClassCastException, but I don't know of any other way of doing this using stream. I think I can do it with a for-each loop checking each time if it's a Trainee or not, but I would like to know if there's a way of doing it using stream.


Solution

  • I'm not sure if it fits the task definition your teacher gave you, but you could expand your map stream operation as follows:

    public static List<PayrollEntry> payroll(List<Employee> employees) {
            return employees
                    .stream()
                    .map(employee -> {
                        // if statements to check type of employee
                        // set some variables for the various fields
                        return new PayroleEntry(...);
                    })
                    .collect(Collectors.toList());
    }