MBZ
MBZ

Reputation: 27612

sort a List based on a parameter available in another class

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;  
    ...
}

IDs 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 Prioritys it should implements Comparator<int>. But the List only contains IDs and the Prioritys 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

Answers (2)

ReyCharles
ReyCharles

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

Rohit Jain
Rohit Jain

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

Related Questions