RahulArackal
RahulArackal

Reputation: 954

Sorting objects in a TreeSet based on a particular predefined order

I have an object class, Project with attributes label & value. I am storing the objects inside a Set. The problem is I need to retrieve the object attributes based on the order of the labels which is predefined. I am unable to understand, how to provide a comparator to TreeSet to implement the same.

public class Project {

    String label;

    String value;

   //Setters & getters
}

    project1.setLabel("Project Name");
    project1.setValue("Solar Project");

    project2.setLabel("Project Type");
    project2.setValue("Government");

The output i am expecting is

Project Name=Solar Project, Project Type=Government

But since it is a Set, the order is not always the same.

I am able to do the same via HashMap & TreeMap combo.

Map<Integer, String> detailsHashMap = new HashMap<Integer, String>();
switch (person.getLabel()) {
    case "Project Name":
            detailsHashMap.put(1, person.getValue());
            break;
    case "Project Type":
            detailsHashMap.put(2, person.getValue());
            break;
    default:
            break;
}

Map<Integer, String> treeMap = new TreeMap<Integer, String>(detailsHashMap);

I always want the objects to be listed in the order

"Project Name" : "Solar Project", "Project Type" : "Government"

Note :

i ) Adding an additional integer field in Project class and sorting based on that is a workaround, but i can't use it because these values will be used in a json.

ii) changing from Set to Map is not possible since large scale changes would be required

Is there any way I can achieve with TreeSet or any implmentation of Set?

Thanks in advance

Upvotes: 0

Views: 2824

Answers (2)

baao
baao

Reputation: 73241

When creating the TreeSet, pass a Comparator to the constructor - like

Set<Project> projects = new TreeSet<>(new Comparator<Project>() {
    @Override
    public int compare(Project o1, Project o2) {
        if (o1.getLabel().equals("foo")) return -2;
        if (o1.getLabel().equals("Solar")) return -1;
        if (o1.getLabel().equals("Gov")) return 1;
        return 0;
    }
});

Or using lambda with java8

Set<Project> projects = new TreeSet<>((o1, o2) -> {
    if (o1.getLabel().equals("foo")) return -2;
    if (o1.getLabel().equals("Solar")) return -1;
    if (o1.getLabel().equals("Gov")) return 1;
    return 0;
});

Now your values will always be sorted like set in the Comparator:

public class FooTestApplication {

    public static void main(String[] args) {
        Project p = new Project();
        p.setLabel("Solar");
        p.setValue("foo");
        Project p2 = new Project();
        p2.setLabel("Gov");
        p2.setValue("foo2");
        Project p3 = new Project();
        p3.setLabel("foo");
        p3.setValue("foo3");
        Set<Project> projects = new TreeSet<>((o1, o2) -> {
            if (o1.getLabel().equals("foo")) return -2;
            if (o1.getLabel().equals("Solar")) return -1;
            if (o1.getLabel().equals("Gov")) return 1;
            return 0;
        });
        projects.add(p);
        projects.add(p2);
        projects.add(p3);

        projects.iterator().forEachRemaining(pp -> {
            System.out.println(pp.getLabel());
        });
    }
}

Outputs:

foo
Solar
Gov

Upvotes: 2

Alex S
Alex S

Reputation: 582

In your project class you need to add a method that overrides the compareTo method, like below:

@Override
public int compareTo(String s1, String s2) {
    // ordering logic
}

Now when you add items to a TreeMap it will keep the order that you want.

Upvotes: 0

Related Questions