简体   繁体   中英

Java sort a list of different type objects

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?

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);

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 :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM