Home > Back-end >  Trying to sort an ArrayList using Comparator
Trying to sort an ArrayList using Comparator

Time:01-05

In the code below the object someObj has two properties, a float x and an int pnt. An ArrayList<someObj> is created and is then sorted using a Comparator interface according to x. The property pnt is intended to keep track of the elements after the sorting.

I've copied the code from https://www.geeksforgeeks.org/collections-sort-java-examples/ and modified it a little to suit my needs. I wonder what might be wrong, it just does not do its sorting job.

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Random;

public class ArrayListSorting {

   public static void main(String[] args) {
       
       // 20 random numbers will be used for the test
       final int sz=20;
       Random rand = new Random();
       
       ArrayList<someObj> oList=new ArrayList<someObj>();
      
      // Build the list
      for(int i=0;i<sz;i  ) {
          oList.add(new someObj(i,rand.nextFloat()));
      }
    
      // Print the list before sorting
      for(int i=0;i<sz;i  ) {
          System.out.println(i "\t" oList.get(i).getX());
      }

      Collections.sort(oList, new sorter());

      // ...and after sorting
      for(int i=0;i<sz;i  ) {
          int j=oList.get(i).getPnt();
          System.out.println(j "\t" oList.get(i).getX());
      }

   }
}

class someObj {

    private float x;
    private int pnt;
    
    public someObj(int pnt,float x) {
        this.pnt=pnt;
        this.x=x;
    }
    
    public int getPnt() {
        return pnt;
    }
    
    public float getX() {
        return x;
    }
}

class sorter implements Comparator<someObj> {
    
    public int compare(someObj a, someObj b) {
        return (int)(a.getX() - b.getX());
    }
}

CodePudding user response:

nextFloat() will generate a float in the range [0,1), and by subtracting any two such values in the comparator, you'll get a value in the range (-1, 1). When you cast this to an int you'll get a 0, meaning that according to this comparator they are all equivalent, and the list will retain its order.

You can solve this by not implementing the comparator with -, but by reusing Float's compare method:

class sorter implements Comparator<someObj> {
    
    public int compare(someObj a, someObj b) {
        return Float.compare(a.getX(), b.getX());
    }
}

Or better yet, use Comparator.comparing to create this comparator on the fly:

Collections.sort(oList, Comparator.comparing(someObj::getX));

EDIT:
As Andy Turner noted in the comments, Collections.sort is a bit outdated. Since JDK 8, lists have their own sort method you can invoke directly:

oList.sort(Comparator.comparing(someObj::getX));
  • Related