vanste25
vanste25

Reputation: 1774

Best way to combine multiple sorts in API 21

My goal is to apply 2 sorts on a list of objects made of string and boolean.

I have accounts and active/inactive states, so I want to show active first (sort boolean values) and then to sort rest of elements in alphabetical order.

For instance:

[John,inactive], [Craig,active], [Mike,inactive], [Dennis,innactive]

I want to have:

[Craig,active], [Dennis,innactive], [John,inactive], [Mike,inactive]

What I plan to do is to use Comparable<> but I wonder if there is another way to do that.

I don't want to use Guava or any additional libraries. This should be used for Android API 21 as well, so list.sort() cannot be used.

Thanks in advance!

Upvotes: 1

Views: 600

Answers (2)

Glains
Glains

Reputation: 2863

Simply create a new Comparator like this:

public class AccountComparator implements Comparator<Account> {

    @Override
    public int compare(Account o1, Account o2) {
        if (o1.isActive() && !o2.isActive()) {
             return -1;
        }
        if (!o1.isActive() && o2.isActive()) {
            return 1;
        }
        return o1.getName().compareTo(o2.getName());
    }
}

Minimal tested example:

public static void main(String[] args) {
    Account account2 = new Account("B", true);
    Account account4 = new Account("D", false);
    Account account3 = new Account("C", true);
    Account account1 = new Account("A", false);

    List<Account> list = new ArrayList<>();
    list.add(account1);
    list.add(account2);
    list.add(account3);
    list.add(account4);

    Collections.sort(list, new AccountComparator());

    list.forEach(System.out::println);
}

with the expected output of

Account{name='B', active=true}
Account{name='C', active=true}
Account{name='A', active=false}
Account{name='D', active=false}

Or with a lambda expression: (Thanks to @Wow for using Comparator.comparing)

Collections.sort(list, Comparator.comparing(Account::isActive).reversed()
        .thenComparing(Account::getName));

Upvotes: 2

Ben P.
Ben P.

Reputation: 54214

There's no magic/easy way to do it without Java 8 or some third-party library. You'll have to implement Comparable and do the heavy lifting yourself:

public class Person implements Comparable<Person> {

    private final boolean isActive;
    private final String name;

    @Override
    public int compareTo(Person other) {
        if (isActive && !other.isActive) {
            return -1;
        } else if (!isActive && other.isActive) {
            return 1;
        } else {
            return name.compareTo(other.name);
        }
    }
}

Upvotes: 2

Related Questions