Search code examples
javaandroidlistsortingcomparable

Sort ArrayList<> Alphabetically in two parts depends if flag is marked


I have List of objects which has several several members the most important are fullName and isSubscribed. I want sort it alphabetically in the following order:

  1. First show alphabetically ordered objects that isSubscribed flag true.
  2. After that show also alphabetically sorted objects that isSubscribed flag is false.

example of expected Contacts order:

  1. Barry (isSubscribed:true)

  2. Ericsson (isSubscribed:true)

  3. Andy (isSubscribed:false)

  4. Cook (isSubscribed:false)

I call sort method of my list which has overridden method compareTo(). my code is alphabetically ordering properly for flag marked false, however flag marked true is just putting on top of that list without alphabetically order. example of Contacts order that I have:

  1. Ericsson (isSubscribed:true)

  2. Barry (isSubscribed:true)

  3. Andy (isSubscribed:false)

  4. Cook (isSubscribed:false)

My overridden code of my Comparable Object (I cant use java 8 due to some circumstances(min sdk level), so please dont offer java8 solution):

   @Override
    public int compareTo(PersonalContact contact) {
        String fullName = getFullName() != null ? getFullName() : "";
        String contactFullName = contact.getFullName() != null ? contact.getFullName() : "";

         int c;
        PersonalContact c1 = this;
        PersonalContact c2 = contact;
        String fullNameContact1 = c1.getFullName();
        String fullNameContact2 = c2.getFullName();
        Boolean subscribedForPresenceContact1 = c1.isSubscribeForPresenceEnabled();
        Boolean subscribedForPresenceContact2 = c2.isSubscribeForPresenceEnabled();

        c = subscribedForPresenceContact1.compareTo(subscribedForPresenceContact2);

        if (subscribedForPresenceContact1) {
            return  -1;
        } else if (subscribedForPresenceContact2) {
            return 1;
        } else  if (fullName.equals(contactFullName)) {
            String id = getAndroidId() != null ? getAndroidId() : "";
            String contactId = contact.getAndroidId() != null ? contact.getAndroidId() : "";

            if (id.equals(contactId)) {
                List<ContactNumberOrAddress> noas1 = getNumbersOrAddresses();
                List<ContactNumberOrAddress> noas2 = contact.getNumbersOrAddresses();
                if (noas1.size() == noas2.size() && noas1.size() > 0) {
                    if (!noas1.containsAll(noas2) || !noas2.containsAll(noas1)) {
                        for (int i = 0; i < noas1.size(); i++) {
                            int compare = noas1.get(i).compareTo(noas2.get(i));
                            if (compare != 0) return compare;
                        }
                    }
                } else {
                    return Integer.compare(noas1.size(), noas2.size());
                }

                String org = getOrganization() != null ? getOrganization() : "";
                String contactOrg =
                        contact.getOrganization() != null ? contact.getOrganization() : "";
                return org.compareTo(contactOrg);
            }
            return id.compareTo(contactId);
        }
        return fullName.compareTo(contactFullName);
    }

Solution

  • I would suggest just to use custom comparator for Collections.sort

    Like

        class PersonalContactComparator implements Comparator<PersonalContact>
        {
    
            @Override
            public int compare(final PersonalContact o1, final PersonalContact o2)
            {
                if (o1.isSubscribeForPresenceEnabled() == o2.isSubscribeForPresenceEnabled()) {
                    return o1.getFullName().compareTo(o2.getFullName());
                }
    
                if (o1.isSubscribeForPresenceEnabled()) {
                    return 1;
                }
    
                return -1;
            }
        }
    

    And use it as Collections.sort(list, new PersonalContactComparator());

    PS: This approach is similar to another asnwers, but more general one