简体   繁体   中英

Best way to double sort in java using Collections.sort

In java I have a custom class, and I sort it like this:

public static void sortList(List<FishCategory> categories) {
    Collections.sort(categories, new Comparator<FishCategory>(){
        public int compare(FishCategory s1, FishCategory s2) {
            return s1.getName().compareTo(s2.getName());
        }
    });
}

But like sql where you can do this:

select * from mytable
order by id, name

I want to double sort in java. I want to sort by this (Note: im using getParentId ) as the first sort, then I want to sort like above.

public static void sortList(List<FishCategory> categories) {
    Collections.sort(categories, new Comparator<FishCategory>(){
        public int compare(FishCategory s1, FishCategory s2) {
            return s1.getParentId().compareTo(s2.getParentId());
        }
    });
}

I can't just run both functions one right after the next cause that would cancel out the first sorting. I need to sort the way sql does it (ie sort the sorted groups).

So I want to sort by .getParentId() first, then .getName() .

Does anyone know a good way to do this easily?

Thanks

Write a single Comparator that tests both fields, consulting the second only if the first is equal. Plug that into the sort. Done.

Note that you can also write a Comparator that wraps around two Comparators (or a list of Comparators), if you want a more general solution for multi-level sorts.

Simple modification for the Comparator :

final int diff = s1.getParentId() - s2.getParentId();
return diff != 0 ? diff : s1.getName().compareTo(s2.getName());

If getParentId() has a difference, sort it by the manner. Else sort by getName() .

As pointed out by this comment by Pshemo , you can use the following in place for diff initialization:

= Integer.compare(s1.getParentId(), s2.getParentId());

Since Java 8 Comparator has thenComparing default method in which you can add next comparator which should be used if "original" comparator would decide that values are equal.

So your code can look like

public static void sortList(List<FishCategory> categories) {
    Collections.sort(categories, new Comparator<FishCategory>(){
        public int compare(FishCategory s1, FishCategory s2) {
            return s1.getParentId().compareTo(s2.getParentId());
        }
    }.thenComparing(new Comparator<FishCategory>(){
        public int compare(FishCategory s1, FishCategory s2) {
            return s1.getName().compareTo(s2.getName());
        }
    }));

    Comparator.comparing(FishCategory::getParentId);
}

or you can simplify it more with Comparator.comparing method which accept Function which returns Comparable field, so in your case you could even use lambdas and write something like

public static void sortList(List<FishCategory> categories) {
    Collections.sort(categories, Comparator
            .comparing(FishCategory::getParentId)
            .thenComparing(Comparator.comparing(FishCategory::getName)));
}

First check it using the parentId, if it is equal then compare for the name

See the code below:

public static void sortList(List<FishCategory> categories) {
    Collections.sort(categories, new Comparator<FishCategory>(){
        public int compare(FishCategory s1, FishCategory s2) {
            int diff = s1.getParentId() - s2.getParentId();
            if (diff != 0)
                return diff;
            return s1.getName().compareTo(s2.getName());
        }
    });
}

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