Reputation: 2399
I have a few classes A, B, and C that extend from class Z. Class Z has an attribute private Date dateCreated = new Date();
I am collecting data in Lists using the following:
List<A> aList = repo.listA();
List<B> aList = repo.listB();
List<C> aList = repo.listC();
and then combining the Lists using
List<Object> combinedList = new ArrayList<Object>
combinedList.addAll(aList);
combinedList.addAll(bList);
combinedList.addAll(cList);
Now, I want to sort the list of objects by the attribute dateCreated
that comes from Class Z. I have tried to use a comparator like so:
Collections.sort(combinedList, new Comparator<Object>() {
@Override
public int compare(Object o1, Object o2) {
return o1.getDateModified().compareTo(o2.getDateModified());
}
});
but this won't work because getDateModified() is undefined for the Objects. I also tried adding a method to Class Z like so:
@Override
public int compareTo(Z o) {
return getDateModified().compareTo(o.getDateModified());
}
but when I try to call sort using
Collections.sort(combinedList)
I get the following error:
The method sort(List<T>) in the type Collections is not applicable for the arguments (List<Object>)
How should I go about sorting the combinedList?
Upvotes: 1
Views: 392
Reputation: 6808
I am not sure if you are forced to use a list of lists, but i don't like to use something like this (whenever it is not necessary). Instead of having a list of lists you could have only one List<Z>
and let Z class implement Comparable
interface in order to sort objects of classes extending Z easier. Then in order to get a sorted list of all objects from class A (A extends Z
) simply:
List<A> sortedA = zList.stream().filter(A.class::isInstance).map(A.class::cast).sorted().collect(Collectors.toList());
If you even let parent class implement Comparable
you can get a sorted version of Z objects sorted by a common property.
A full example:
public class Lists {
private static class Employee implements Comparable<Employee> {
protected int salary;
// All employees sortable by salary
@Override
public int compareTo(Employee o) {
return salary - o.salary;
}
}
private static class HourlyEmployee extends Employee {
private int hoursWorked;
public HourlyEmployee(int hoursWorked) {
this.hoursWorked = hoursWorked;
this.salary = hoursWorked * 12; // use setter instead or parent constructor
}
// Sort hourly employees by hours worked.
@Override
public int compareTo(Employee o) {
if (o instanceof HourlyEmployee) {
HourlyEmployee hourlyEmployee = (HourlyEmployee) o;
// Getter should be used here
return hoursWorked - hourlyEmployee.hoursWorked;
}
return super.compareTo(o);
}
@Override
public String toString() {
return "HourlyEmployee [hoursWorked=" + hoursWorked + ", salary=" + salary + "]";
}
}
private static class MonthlyEmployee extends Employee {
private int monthsWorked;
public MonthlyEmployee(int monthsWorked) {
this.monthsWorked = monthsWorked;
this.salary = monthsWorked * 100; // again use setter instead
}
// Sort montly employees by months worked.
@Override
public int compareTo(Employee o) {
if (o instanceof MonthlyEmployee) {
MonthlyEmployee monthlyEmployee = (MonthlyEmployee) o;
// Getter should be used here
return monthsWorked - monthlyEmployee.monthsWorked;
}
return super.compareTo(o);
}
@Override
public String toString() {
return "MonthlyEmployee [monthsWorked=" + monthsWorked + ", salary=" + salary + "]";
}
}
public static void main(String[] args) {
List<Employee> employees = new ArrayList<>();
employees.add(new HourlyEmployee(5));
employees.add(new HourlyEmployee(55));
employees.add(new HourlyEmployee(12));
employees.add(new HourlyEmployee(15));
employees.add(new HourlyEmployee(4));
employees.add(new MonthlyEmployee(51));
employees.add(new MonthlyEmployee(44));
employees.add(new MonthlyEmployee(72));
employees.add(new MonthlyEmployee(12));
employees.add(new MonthlyEmployee(4));
System.out.println("Sorted hourly employess:");
List<HourlyEmployee> sortedHourlyEmployees = employees.stream().filter(HourlyEmployee.class::isInstance).map(HourlyEmployee.class::cast).sorted()
.collect(Collectors.toList());
sortedHourlyEmployees.forEach(System.out::println);
System.out.println();
System.out.println("Sorted monthly employess:");
List<MonthlyEmployee> sortedMonthlyEmployees = employees.stream().filter(MonthlyEmployee.class::isInstance).map(MonthlyEmployee.class::cast).sorted()
.collect(Collectors.toList());
sortedMonthlyEmployees.forEach(System.out::println);
System.out.println();
System.out.println("Sorted employess:");
List<Employee> sortedEmployeesBySalary = employees.stream().sorted().collect(Collectors.toList());
sortedEmployeesBySalary.forEach(System.out::println);
}
}
Which outputs:
Sorted hourly employess:
HourlyEmployee [hoursWorked=4, salary=48]
HourlyEmployee [hoursWorked=5, salary=60]
HourlyEmployee [hoursWorked=12, salary=144]
HourlyEmployee [hoursWorked=15, salary=180]
HourlyEmployee [hoursWorked=55, salary=660]
Sorted monthly employess:
MonthlyEmployee [monthsWorked=4, salary=400]
MonthlyEmployee [monthsWorked=12, salary=1200]
MonthlyEmployee [monthsWorked=44, salary=4400]
MonthlyEmployee [monthsWorked=51, salary=5100]
MonthlyEmployee [monthsWorked=72, salary=7200]
Sorted employess:
HourlyEmployee [hoursWorked=4, salary=48]
HourlyEmployee [hoursWorked=5, salary=60]
HourlyEmployee [hoursWorked=12, salary=144]
HourlyEmployee [hoursWorked=15, salary=180]
MonthlyEmployee [monthsWorked=4, salary=400]
HourlyEmployee [hoursWorked=55, salary=660]
MonthlyEmployee [monthsWorked=12, salary=1200]
MonthlyEmployee [monthsWorked=44, salary=4400]
MonthlyEmployee [monthsWorked=51, salary=5100]
MonthlyEmployee [monthsWorked=72, salary=7200]
Where MonthlyEmployee
and HourlyEmployee
represents A
and B
. Employee represents the parent class Z
.
Also do not ignore the comments about getters and setters. I did not use them for the sake of the example :)
Upvotes: 0
Reputation: 12953
You need to define your list to be of type Z and not Object
, and than you'll be able to use Comparator<Z>
List<Z> combinedList = new ArrayList<>();
combinedList.addAll(aList);
combinedList.addAll(bList);
combinedList.addAll(cList);
Upvotes: 2