简体   繁体   中英

How to combine two Collections.sort functions

I have a program where i am have a list of Names, and how many people have that name. I want to put the names in alphabetical order while also putting the counts from greatest to least. If the name has the same count it puts the name in alphabetical order. I figured out how to put the names in abc order and figured out how to put the counts in greatest to least but i cant figure out how to combine the two to get list of names greatest to least and if they have the same count in alphabetical order.

 Collections.sort(oneName, new OneNameCompare());
    for(OneName a: oneName)
    {
     System.out.println(a.toString());

    }
 Collections.sort(oneName, new OneNameCountCompare());
     for(OneName a: oneName)
    {

     System.out.println(a.toString());
     }

You can make another Comparator that combines the effects of the two other Comparator s. If one comparator compares equal, then you can call the second comparator and use its value.

public class CountNameComparator implements Comparator<Name>
{
    private OneNameCompare c1 = new OneNameCompare();
    private OneNameCountCompare c2 = new OneNameCountCompare();
    @Override
    public int compare(Name n1, Name n2)
    {
        int comp = c1.compare(n1, n2);
        if (comp != 0) return comp;
        return c2.compare(n1, n2);
    }
}

Then you can call Collections.sort just once.

Collections.sort(oneName, new CountNameComparator());

This can be generalized for any number of comparators.

You can combine comparators like this

public static <T> Comparator<T> combine(final Comparator<T> c1, final Comparator<T> c2) {
    return new Comparator<T>() {
       public int compare(T t1, T t2) {
          int cmp = c1.compare(t1, t2);
          if (cmp == 0)
              cmp = c2.compare(t1, t2);
          return cmp;
       }
    };
}

BTW Comparators are a good example of when to use a stateless singleton. All comparators or a type are the same so you only ever need one of them.

public enum OneNameCompare implements Comparator<OneName> {
    INSTANCE;
    public int compare(OneName o1, OneName o2) {
        int cmp = // compare the two objects
        return cmp;
    }
}

This avoid creating new instances or cache copies. You only ever need one of each type.

假设您正在使用Apache Commons Collections API,您可能需要查看ComparatorUtils.chainedComparator

Collections.sort(oneName, ComparatorUtils.chainedComparator(new OneNameCompare(), new OneNameCountCompare());

Using lambdas from Java 8:

Collections.sort(Arrays.asList(""),
        (e1, e2) -> e1.getName().compareTo(e2.getName()) != 0 ?
                e1.getName().compareTo(e2.getName()) :
                e1.getCount().compareTo(e2.getCount()));

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