简体   繁体   中英

Descending sort of object using comparable or comparator

So I have a Hill object that contains information about hills that is obtained from a CSV file. The file looks like this:

import java.io.IOException;
import java.net.URL;
import java.util.*;



public class Hill implements Comparable<Hill>{
    public static final String CSV_FILE_URL = "HIDDEN";
    public static final String DELIMITER = ",";
    public int number;
    public String name,county;
    public double height,lat,lon;


    public Hill(int number,String name,String county,double height,double lat,double lon){
        this.number = number;
        this.name = name;
        this.county = county;
        this.height = height;
        this.lat = lat;
        this.lon = lon;

    }

    public String toString(){
        return(number + ", " + name + ", " + county + ", " + height + ", " + lat + ", " + lon);
    }

    public static List<Hill> readHills() throws IOException{
        String[] fields = new String[0];
        URL url = new URL(CSV_FILE_URL);
        Scanner input = new Scanner(url.openConnection().getInputStream());
        List<Hill> hillList = new ArrayList<>();
        input.nextLine();
        while(input.hasNextLine()){
            fields = input.nextLine().split(DELIMITER);
            Hill hill = new Hill(Integer.parseInt(fields[0]),fields[1],fields[2],Double.parseDouble(fields[3]),Double.parseDouble(fields[4]),Double.parseDouble(fields[5]));
            hillList.add(hill);

        }

        return hillList;
    }


    @Override
    public int compareTo(Hill o) {
        return this.name.compareTo(o.name);
    }


}

Inside my exercise class I am currently able to sort the hills alphabetically using the Comparable interface. I then get it to print the first 20 hills.

Now I wish to sort the hills list by height but descending so that I can print out the 20 tallest hills.

import java.io.IOException;
import java.util.*;

public class Exercise5 {

    public static void exercise5d() throws IOException {
        System.out.println("### Exercise 5D ###");
        List listOfHills = Hill.readHills();
        Collections.sort(listOfHills);
        for(int x=0;x<20;x++){
            System.out.println(listOfHills.get(x));
        }
        System.out.println("");

        //Attempt at reversing
        Comparator<Hill> HillComparator = Collections.reverseOrder();
        Collections.sort(listOfHills,HillComparator);
        for(int x=0;x<20;x++){
            System.out.println(listOfHills.get(x));
        }



    }

    public static void main(String[] args) throws IOException {
        exercise5d();
    }
}

Here is an example that shows how you can use Comparable or a Comparator :

/*
**  Use the Collections API to sort a List for you.
**
**  When your class has a "natural" sort order you can implement
**  the Comparable interface.
**
**  You can use an alternate sort order when you implement
**  a Comparator for your class.
*/
import java.util.*;

public class Person implements Comparable<Person>
{
    String name;
    int age;

    public Person(String name, int age)
    {
        this.name = name;
        this.age = age;
    }

    public String getName()
    {
        return name;
    }

    public int getAge()
    {
        return age;
    }

    public String toString()
    {
        return name + " : " + age;
    }

    /*
    **  Implement the natural order for this class
    */
    public int compareTo(Person p)
    {
        return getName().compareTo(p.getName());
    }

    static class AgeComparator implements Comparator<Person>
    {
        public int compare(Person p1, Person p2)
        {
            return p1.getAge() - p2.getAge();
        }
    }

    public static void main(String[] args)
    {
        List<Person> people = new ArrayList<Person>();
        people.add( new Person("Homer", 38) );
        people.add( new Person("Marge", 35) );
        people.add( new Person("Bart", 15) );
        people.add( new Person("Lisa", 13) );

        // Sort by natural order

        Collections.sort(people);
        System.out.println("Sort by Natural order");
        System.out.println("\t" + people);

        // Sort by reverse natural order

        Collections.sort(people, Collections.reverseOrder());
        System.out.println("Sort by reverse natural order");
        System.out.println("\t" + people);

        //  Use a Comparator to sort by age

        Collections.sort(people, new Person.AgeComparator());
        System.out.println("Sort using Age Comparator");
        System.out.println("\t" + people);

        //  Use a Comparator to sort by descending age

        Collections.sort(people, Collections.reverseOrder(new Person.AgeComparator()));
        System.out.println("Sort using Reverse Age Comparator");
        System.out.println("\t" + people);

        //  Use a Comparator with lambda expression to sort by age

//      Collections.sort(people, (o1, o2) -> o1.getAge() - o2.getAge());
//      Collections.sort(people, Comparator.comparingInt(p -> p.getAge()));
        Collections.sort(people, Comparator.comparingInt(Person::getAge));
        System.out.println("Sort using Lambda Age Comparator");
        System.out.println("\t" + people);
    }
}

So you just need to implement the Comparator for your Hill class on whatever property(s) you want.

Your basic implementation of Comparable compares the names of the hills, it has nothing to do with the height

How can I adjust Comparable so that it allows me to sort by name and then by height after?

Create a new Comparator which implements the logic you need to compare the heights and use that with Collections.sort

Collections.sort(listOfHills, new Comparator<Hill>() {
    @Override
    public int compare(Hill o1, Hill o2) {
        return o2.height > o1.height ? (o2.height == o1.height ? 0 : 1) : -1;
    }
});

This is one of the reasons I don't normally implement Comparator on objects, unless their is a good business rule associated with how the object should be compared, it's easily to provide a number of custom Comparator s (or allow other developers to devise their own) which implement "common" algorithms - but that's me

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM