Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Custom ordering using Java Comparator – Retain the position for objects with certain value

I am trying to implement a custom comparator that sorts a list of objects in descending order, but while doing so, it ignores when the object has a specific value (-1 in my case). Thus, the objects with that value retain their original position, but all the objects around them will be sorted in descending order. For example, if the list is :

Candidate candidate1 = new Candidate("id1",  0.4);
Candidate candidate2 = new Candidate("id2", -1.0);
Candidate candidate3 = new Candidate("id3", 0.8);
List<Candidate> inputCandidates = ImmutableList.of(candidate1, candidate2, candidate3)

The resulting order should be

[
    Candidate(super=Candidate(id=id3), value=0.8), 
    Candidate(super=Candidate(id=id2), value=-1.0), 
    Candidate(super=Candidate(id=id1), value=0.4)
]

Currently, I am trying something like this:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

public final Comparator<Candidate> customComparator() {
    return (Candidate one, Candidate two) -> {
        double scoreOne =  one.getValue() != null ? one.getValue() : 0d;
        double scoreTwo =  two.getValue() != null ? two.getValue() : 0d;
        if (scoreOne == scoreTwo) return 0;
        if (scoreOne == -1.0d) return 1;
        if (scoreTwo == -1.0d) return -1;
        return Double.compare(scoreTwo, scoreOne);
    };
}

However, this instead gives me:

[
    Candidate(super=Candidate(id=id3), value=0.8), 
    Candidate(super=Candidate(id=id1), value=0.4), 
    Candidate(super=Candidate(id=id2), value=-1.0)
]

Could someone please help me figure out where I am going wrong?

>Solution :

There is no solution using a single Comparator (or at least I failed to find it so). Here is a working solution requiring two steps:

  1. Sort all the values in the descending (reversed()) order without the specific value and collect it as a mutable list:

    List<Candidate> sorted = inputCandidates.stream()
         .filter(candidate -> candidate.getValue() != -1.0)
         .sorted(Comparator.comparing(Candidate::getValue).reversed())
         .collect(Collectors.toCollection(ArrayList::new));
    
  2. Iterate through the former collection and add the candidates with the specific value (-1.0) to its original index position in the newly sorted list:

    for (int i=0; i<inputCandidates.size(); i++) {
         Candidate candidate = inputCandidates.get(i);
         if (candidate.getValue() == -1.0) {
             sorted.add(i, candidate);
         }
     }
    

Example input:

Candidate candidate1 = new Candidate("id1",  0.4);
Candidate candidate2 = new Candidate("id2", -1.0); // fixed position
Candidate candidate3 = new Candidate("id3", -1.0); // fixed position
Candidate candidate4 = new Candidate("id4",  0.8); 
Candidate candidate5 = new Candidate("id5", -1.0); // fixed position
Candidate candidate6 = new Candidate("id6",  0.5);

Example output:

sorted.forEach(c -> System.out.println(c.getId() + " : " + c.getValue()));
id4 : 0.8
id2 : -1.0  // fixed position    
id3 : -1.0  // fixed position
id6 : 0.5 
id5 : -1.0  // fixed position
id1 : 0.4

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading