5

How can i create a comparator to be able to sort an arraylist by a float parameter?

Imagine i have an arraylist of objects that has something like this:

ID=7 TFIDF=0.12654299 PR=25238.0
ID=4 TFIDF=0.12654299 PR=3638.0
ID=4 TFIDF=0.12654299 PR=3638.0
ID=4 TFIDF=0.12654299 PR=3638.0
ID=3 TFIDF=0.56442446 PR=14558.0
ID=1 TFIDF=0.0083091585 PR=3953.0 

I want to sort the array by TFIDF values.. As far as i know i can only sort them by integer.. Thus, im comparing zeros.

So far i have this:

Collections.sort(Contents_To_Show, new Comparator<ContentToShow>() {
            public int compare(ContentToShow o1, ContentToShow o2) {
                return (int) (o1.GetPR() - o2.GetPR());
            }
        });

But. Again, it compares me only the integer part. How can i compare the entire value?

Please help.

Thanks

Pedro Neves
  • 364
  • 1
  • 8
  • 26
  • `As far as i know i can only sort them by integer.. Thus, im comparing zeros. ` Who says that? You compare them by whatever attribute you want, the only thing that matters is the `compare` method return value. – SJuan76 Sep 01 '13 at 21:39
  • Well. At least it haven't the expected results. The code i posted do not sort the values i want. I used in another sorting PR values and it works, thats why i think this has something to do with float values or, at least 0.X – Pedro Neves Sep 01 '13 at 21:45

4 Answers4

11

Followup to Pedro's followup. If you want to sort by TFIDF, then by PR,

int result = Float.compare(o1.getTFIDF(), o2.getTFIDF());
if (result == 0)
  result = Float.compare(o1.getPR(), o2.getPR());
return result;
Pedro Neves
  • 364
  • 1
  • 8
  • 26
user949300
  • 15,364
  • 7
  • 35
  • 66
  • Ah men u just finished to save my life. Call me a noob but i developed a hell of an algorithm to organize this this way (kind of). U did it in a few line.. omg i feel terrible :D. Thanks a lot – Pedro Neves Sep 02 '13 at 01:04
  • 1
    Glad to help. I've written a lot of Comparators and eventually you figure out this idiom. Float.compare() is fairly recent, at least to my knowledge. When dealing with primitives, always look in their "wrapper" class for possible utility methods. – user949300 Sep 02 '13 at 04:03
4

Ok, from your comment the issue that you have is that you are using the substraction code to your comparator, but as the float values difference is less than 1 (absolute value), casting to int always rounds to 0.

Use a more generic form, with if

        public int compare(ContentToShow o1, ContentToShow o2) {
            if (o1.getTFIDF() > o2.getTFIDF()) {
              return -1;
            }
            if (o1.getTFIDF() < o2.getTFIDF()) {
              return 1;
            }
            return 0
        }

As I said, how do you get the compare result value (as long as it is coherent) is not related to the sorting.

SJuan76
  • 24,532
  • 6
  • 47
  • 87
  • The code you posted works only for ints/longs because if the difference between two ints is less than 1, it is because they are both the same. – SJuan76 Sep 01 '13 at 21:51
  • 1
    However, instead of writing you own code, use Float.compare() or Double.compare(). – user949300 Sep 02 '13 at 00:41
1

I want to sort the array by TFIDF values..

Then why are you comparing PR values with o1.GetPR()

public int compare(ContentToShow o1, ContentToShow o2) {
      return (int) (o1.GetPR() - o2.GetPR());
}

Try comparing the TFIDF values in your compare method (but as mentioned casting to int will always round to int value i.e. 0)

return (int) (o1.GetTFIDF() - o2.GetTFIDF());

So you could use

return Float.valueOf(o1.GetTFIDF()).compareTo(Float.valueOf(o2.GetTFIDF()))
Java Devil
  • 10,629
  • 7
  • 33
  • 48
1

In Java 8 with lambda functions is now very simple to compare two float in a object list. I use in this example both lambda functions and functional operations (new features in Java 8). In your main you can try this example. This example arrange people by floats that represent the height :

List<Person> people = Person.createStandardList(); // create a list with 2 standard users
Collections.sort(people, (Person p1, Person p2) -> Float.compare(p1.height_in_meter, p2.height_in_meter));

    people.stream().forEach((p) -> { // functional operation
        p.printName();
    });

This is my class Person

public class Person {

 public static List<Person> createStandardList() {
   List<Person> people = new ArrayList<>();
   Person p = new Person();
   p.name = "Administrator";
   p.surname = "admin";
   p.address = "Via standard 1";
   p.age = 26;
   p.sex = 'M';
   p.height_in_meter = 1.70f;
   p.weight_in_kg = 68.50f;
   people.add(p);
   p = new Person();
   p.name = "First";
   p.surname = "Creator";
   p.address = "Via standard 2";
   p.age = 30;
   p.sex = 'F';
   p.height_in_meter = 1.80f;
   p.weight_in_kg = 58.50f;      
   people.add(p);
   p = new Person();
   p.name = "Second";
   p.surname = "Creator";
   p.address = "Via standard 3";
   p.age = 20;
   p.sex = 'F';
   p.height_in_meter = 1.30f;
   p.weight_in_kg = 48.50f;      
   people.add(p);
   return people;

 }

 public String name;
 public String surname;
 public String address;
 public int age;
 public char sex;
 public float height_in_meter;
 public float weight_in_kg;

 public String getName() {
     return name;
 }

 public String getSurname() {
     return surname;
 }

 public float getHeight_in_meter() {
    return high_in_meter;
 }

 public float getWeight_in_kg() {
    return weight_in_kg;
 }

 public void printName() {
  System.out.println(this.name);
 }  
}

The output is :

Second

Administrator

First

So I think this example it's easier to understand JAVA 8 features. In Documentation you try a similar example but with strings that use another method. (Oracle official documentation to lambda functions with Collection example)