How to compare objects by multiple fields

后端 未结 22 2573
暖寄归人
暖寄归人 2020-11-22 00:43

Assume you have some objects which have several fields they can be compared by:

public class Person {

    private String firstName;
    private String lastN         


        
相关标签:
22条回答
  • 2020-11-22 01:21

    @Patrick To sort more than one field consecutively try ComparatorChain

    A ComparatorChain is a Comparator that wraps one or more Comparators in sequence. The ComparatorChain calls each Comparator in sequence until either 1) any single Comparator returns a non-zero result (and that result is then returned), or 2) the ComparatorChain is exhausted (and zero is returned). This type of sorting is very similar to multi-column sorting in SQL, and this class allows Java classes to emulate that kind of behaviour when sorting a List.

    To further facilitate SQL-like sorting, the order of any single Comparator in the list can >be reversed.

    Calling a method that adds new Comparators or changes the ascend/descend sort after compare(Object, Object) has been called will result in an UnsupportedOperationException. However, take care to not alter the underlying List of Comparators or the BitSet that defines the sort order.

    Instances of ComparatorChain are not synchronized. The class is not thread-safe at construction time, but it is thread-safe to perform multiple comparisons after all the setup operations are complete.

    0 讨论(0)
  • 2020-11-22 01:21

    Usually I override my compareTo() method like this whenever I have to do multilevel sorting.

    public int compareTo(Song o) {
        // TODO Auto-generated method stub
        int comp1 = 10000000*(movie.compareTo(o.movie))+1000*(artist.compareTo(o.artist))+songLength;
        int comp2 = 10000000*(o.movie.compareTo(movie))+1000*(o.artist.compareTo(artist))+o.songLength;
        return comp1-comp2;
    } 
    

    Here first preference is given to movie name then to artist and lastly to songLength. You just have to make sure that those multipliers are distant enough to not cross each other's boundaries.

    0 讨论(0)
  • 2020-11-22 01:22

    Code implementation of the same is here if we have to sort the Person object based on multiple fields.

    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Comparator;
    
    public class Person {
    
    private String firstName;
    private String lastName;
    private int age;
    
    public String getFirstName() {
        return firstName;
    }
    
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    
    public String getLastName() {
        return lastName;
    }
    
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
    
    public int getAge() {
        return age;
    }
    
    public void setAge(int age) {
        this.age = age;
    }
    
    public Person(String firstName, String lastName, int age) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
    }
    
    
    static class PersonSortingComparator implements Comparator<Person> {
    
        @Override
        public int compare(Person person1, Person person2) {
    
            // for first name comparison
            int firstNameCompare = person1.getFirstName().compareTo(person2.getFirstName());
    
            // for last name comparison
            int lastNameCompare = person1.getLastName().compareTo(person2.getLastName());
    
            // for last name comparison
            int ageCompare = person1.getAge() - person2.getAge();
    
            // Now comparing
            if (firstNameCompare == 0) {
                if (lastNameCompare == 0) {
                    return ageCompare;
                }
                return lastNameCompare;
            }
            return firstNameCompare;
        }
    }
    
    public static void main(String[] args) {
        Person person1 = new Person("Ajay", "Kumar", 27);
        Person person2 = new Person("Ajay","Gupta", 23);
        Person person3 = new Person("Ajay","Kumar", 22);
    
    
        ArrayList<Person> persons = new ArrayList<>();
        persons.add(person1);
        persons.add(person2);
        persons.add(person3);
    
    
        System.out.println("Before Sorting:\n");
        for (Person person : persons) {
            System.out.println(person.firstName + " " + person.lastName + " " + person.age);
        }
    
        Collections.sort(persons, new PersonSortingComparator());
    
        System.out.println("After Sorting:\n");
        for (Person person : persons) {
            System.out.println(person.firstName + " " + person.lastName + " " + person.age);
        }
    }
    
    }
    
    0 讨论(0)
  • 2020-11-22 01:22

    Following blog given good chained Comparator example

    http://www.codejava.net/java-core/collections/sorting-a-list-by-multiple-attributes-example

    import java.util.Arrays;
    import java.util.Comparator;
    import java.util.List;
    
    /**
     * This is a chained comparator that is used to sort a list by multiple
     * attributes by chaining a sequence of comparators of individual fields
     * together.
     *
     */
    public class EmployeeChainedComparator implements Comparator<Employee> {
    
        private List<Comparator<Employee>> listComparators;
    
        @SafeVarargs
        public EmployeeChainedComparator(Comparator<Employee>... comparators) {
            this.listComparators = Arrays.asList(comparators);
        }
    
        @Override
        public int compare(Employee emp1, Employee emp2) {
            for (Comparator<Employee> comparator : listComparators) {
                int result = comparator.compare(emp1, emp2);
                if (result != 0) {
                    return result;
                }
            }
            return 0;
        }
    }
    

    Calling Comparator:

    Collections.sort(listEmployees, new EmployeeChainedComparator(
                    new EmployeeJobTitleComparator(),
                    new EmployeeAgeComparator(),
                    new EmployeeSalaryComparator())
            );
    
    0 讨论(0)
  • 2020-11-22 01:23

    You can implement a Comparator which compares two Person objects, and you can examine as many of the fields as you like. You can put in a variable in your comparator that tells it which field to compare to, although it would probably be simpler to just write multiple comparators.

    0 讨论(0)
  • 2020-11-22 01:23
    //here threshold,buyRange,targetPercentage are three keys on that i have sorted my arraylist 
    final Comparator<BasicDBObject> 
    
        sortOrder = new Comparator<BasicDBObject>() {
                        public int compare(BasicDBObject e1, BasicDBObject e2) {
                            int threshold = new Double(e1.getDouble("threshold"))
                            .compareTo(new Double(e2.getDouble("threshold")));
                            if (threshold != 0)
                                return threshold;
    
                            int buyRange = new Double(e1.getDouble("buyRange"))
                            .compareTo(new Double(e2.getDouble("buyRange")));
                            if (buyRange != 0)
                                return buyRange;
    
                            return (new Double(e1.getDouble("targetPercentage")) < new Double(
                                    e2.getDouble("targetPercentage")) ? -1 : (new Double(
                                            e1.getDouble("targetPercentage")) == new Double(
                                                    e2.getDouble("targetPercentage")) ? 0 : 1));
                        }
                    };
                    Collections.sort(objectList, sortOrder);
    
    0 讨论(0)
提交回复
热议问题