Reputation: 27612
I have some design problems with Java Comparator
Interface.
I have a class which contains a Set
of a simple custom data structure:
class data {
Long ID;
int Priority;
...
}
ID
s are unique, so it is possible to get the whole data using ID
.
and the container class:
class Container {
Set<data> mySet = ...;
List<Long> myList = ...;
...
}
for some inevitable reasons, I need to keep a sorted List
of data
IDs in parallel. I need the List
to be sorted by Priority
.
Since, the Comparator
should compare Priority
s it should implements Comparator<int>
. But the List
only contains ID
s and the Priority
s are not available directly.
This is the problem. There is only ID
in the List
. Therefore, the Comparator class has no access to Priority
.
How can I design such concept?
Upvotes: 1
Views: 998
Reputation: 1792
You could use something that smells like higher order functions. That is, make a static function that takes a map of sorts from Long to int (which is the priority) or data and returns a new Comparator.
The class Foo has a static method getComparator
which takes an Orange. An Orange is a class that has a method getPriority
which takes an ID an return the corresponding priority. The getComparator
method constructs a new Comparator
object. The new Comparator
object's compare
method takes two IDs. It looks up the corresponding priorities of the two IDs and compares them.
public interface Orange {
// Looks up id and returns the corresponding Priority.
public int getPriority(Long id);
}
public class Foo {
public static Comparator<Long> getComparator(final Orange orange) {
return new Comparator<Long>() {
public int compare(Long id1, Long id2) {
// Get priority through orange, or
// Make orange juice from our orange.
// You may want to compare them in a different way.
return orange.getPriority(id1) - orange.getPriority(id2);
};
}
}
My java is a bit rusty so the code may be flawed. The general idea should work, though.
Usage:
// This is defined somewhere. It could be a local variable or an instance
// field or whatever. There's no exception (except is has to be in scope).
Collection c = ...;
...
Orange orange = new Orange() {
public int getPriority(Long id) {
// Insert code that searches c.mySet for an instance of data
// with the desired ID and return its Priority
}
};
Collections.sort(c.myList, Foo.getComparator(orange));
I have not given an example on how an Orange could look.
Upvotes: 1
Reputation: 213321
I assume that you have a List<Data>
stored somewhere.. In Comparator, you need to invoke a getDataById
method from your data class, and sort through Priority..
Check the below code.. I have used a single class for many purpose..
Ideally you would want to break it into more classes.. But this is just a Demo, how to achieve what you want..
class Container {
// List of Data instances created..
// This list has to be static, as it is for a class,
// and not `instance specific`
public static List<Data> dataList = new ArrayList<Data>();
// List of Ids, that you want to sort.
private List<Long> idList = new ArrayList<Long>();
// Populate both the list..
// Have a method that will iterate through static list to
// find Data instance for a particular id
public static Data getDataById(long id) {
// Find Data with id from the list
// Return Data
}
public void sortList() {
Collections.sort(idList, new MyComparator());
}
}
public MyComparator implements Comparator<Long> {
public int compare(Long int1, Long int2) {
Data data1 = Container.getDataById(int1);
Data data2 = Container.getDataById(int2);
return data1.getPriority() - data2.getPriority();
}
}
Upvotes: 0