My apologies for my limited knowledge of generics beforehand.
I have the following situation:
Class 1:
public class PostProcess implements Serializable {
public int order;
// Several other variables.
// Constructor setting vars
public PostProcess(){
}
/* Getters and setters for variables */
}
Class 2:
public class Application extends PostProcess{
public int subOrder;
// Several other variables.
// Constructor setting vars
public Application(){
}
/* Getters and setters for variables */
}
Class 3:
public class FileOperation extends PostProcess{
public int subOrder;
// Several other variables (different from class 'Application').
// Constructor setting vars
public FileOperation(){
}
/* Getters and setters for variables */
}
What I am trying to achieve in a different class is to sort a list containing a mix of 'FileOperation' and 'Application' objects defined as:
private ArrayList<? extends PostProcess> processList = new ArrayList<PostProcess>();
This sort will have to be on two fields of both of these objects, namely: 'order' and 'subOrder'. 'order' is inherited from PostProcess and 'subOrder' is defined in both the 'Application' and 'FileOperation' classes.
Throughout my journey of reading up on Generics, Comparable, Comparators and Interfaces I think I got things mixed up.
I am trying to apply a sort using:
Collections.sort(processList, new PostProcessComparator());
The PostProcessComparator is defined as:
public class PostProcessComparator implements Comparator<? extends PostProcess> {
@Override
public int compare(Object p1, Object p2) {
int mainOrderCompare = p1.getOrder().compareTo(p2.getOrder());
if (mainOrderCompare != 0) {
return mainOrderCompare;
} else {
return p1.getSubOrder().compareTo(p2.getSubOrder());
}
}
}
Questions:
I know my Comparator (and possibly more) is wrong, but I dont know where specifically. Im here to learn ;)
- I noticed that defining the 'processList' List isnt the right way to do it. When I try to add an 'FileOperation' or 'Application' object to the List the compiler slaps me in the face with "no suitable method found for add(Application)" (the same for FileOperation). Did I incorrectly assume that I could use generics to declare my processList types? should be correct as both classes have PostProcess as their superclass right?
- Defining the PostProcessComparator with class bounds should work in my eyes as I only want to be able to compare objects that have PostProcess as a superclass (and thus have access to the same methods).
How do I access the argumented objects in the Comparator class for p1 and p2 (because I still need to declare their types for the arguments:
@Override public int compare(<What to put here?> p1, <And here?> p2) { }
I really hope you guys can help! If I was unclear in something, do let me know and ill elaborate.
Thanks!
EDIT
Thanks to NickJ and Winzu I have made the necessary changes to the comparator and the ArrayList definition.
- I have moved subOrder from Application and FileOperation to the parent class (and made them protected)
Redefined parameterization of the comparator to:
public class PostProcessComparator<T extends PostProcess> implements Comparator<T>
Made use of the Integer.compare(p1.getOrder(), p2.getOrder()) for initial comparator comparisons.
Now the final challenge (compiler warnings) Upon calling:
Collections.sort(processList, new PostProcessComparator());
I get the warning: - [unchecked] unchecked method invocation: method sort in class Collections is applied to given types
required: List<T>,Comparator<? super T>
found: ArrayList<PostProcess>,PostProcessComparator
The parameterization is correct for this comparator in my eyes, aside from the fact that i havent checked the object types.
Where does this go wrong?