1

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?

7
  • 1
    you want orange juice but you dont supply orange, huh? Commented Oct 10, 2012 at 10:53
  • lol, yeah. but the orange is available somewhere else! :D I just don't know how to access it! Commented Oct 10, 2012 at 10:54
  • Do you have list of instances what you created, somewhere?? Commented Oct 10, 2012 at 10:54
  • yes, they are available in the mySet. Commented Oct 10, 2012 at 10:55
  • Then you need to find the object from that Set for each Id and check its Priority.. have a getDataById() method in your class. Commented Oct 10, 2012 at 10:56

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

10 Comments

I really didn't get your answer :( Can you please add more details?
Yes. Can you give some hints on what's missing?
I added some naming to my question. It would be very nice if you rewrite your code in my naming :)
@MBZ, how about now? Is it better? Or am I still missing something?
not working :( it seems that it is not possible to cast Comparator<Int> to Comparator<Long>.
|
0

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

5 Comments

Thanks for your solution. But I am not able to redefine the Container class as Static. The List must vary in different instances.
@MBZ.. That is meaningless.. How can you have a different list of instance created for every instance.. No of instances created has to be same for all the instances.. Actually it is class-specific..
@MBZ.. And you are not making your Container class Static.. But the List that holds your instances Static.. Without that, you cannot achieve what you want.. Unless you use a Database..
Re our discussion here. You suggest he makes mySet static. That's fine, although one could suspect it's not an option for him to change the Container class since it would be easier to just have a List<data> instead of List<Long>. He then says it's not possible for him to do that and you just say that's "meaningless". You also say it's not possible without making it static. That's clearly not true as my answer shows. Hope to see some good answers and comments from you in the future :-)
It's mostly that you insist he changes his Container class and say it's not possible otherwise. Often one works with code one does not control and hence cannot change. You have to accept his terms and try to work out a solution from there.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.