androidsortingsecondary-sort

Secondary sort on ArrayAdapter


i am trying to sort my Arrayadapter with it's sort-Method

@Override
public void sort(@NonNull Comparator<? super Task> comparator) {
    super.sort(comparator);
}

two times.

I'm using the two Comparators

private static final Comparator TASKCOMPARATOR_TITLE = new Comparator<Task>() {
    @Override
    public int compare(Task a, Task b) {
        return a.getTitle().compareToIgnoreCase(b.getTitle());
    }
};

private static final Comparator TASKHOLDERCOMPARATOR_DUEDATE = new Comparator<ViewHolder>() {
    @Override
    public int compare(ViewHolder a, ViewHolder b) {
        return a.getTask().getDueTime().compareTo(b.getTask().getDueTime());
    }
};

like this

taskAdapter.sort(Util.getTASKCOMPARATOR_TITLE());
taskAdapter.sort(Util.getTASKCOMPARATOR_DUEDATE());

hoping to secondary sort the ArrayAdapter by the title and then by the Date. The sort-Method of the ArrayAdapter is internally using

public void sort(Comparator<? super T> comparator) {
    synchronized (mLock) {
        if (mOriginalValues != null) {
            Collections.sort(mOriginalValues, comparator);
        } else {
            Collections.sort(mObjects, comparator);
        }
    }
    if (mNotifyOnChange) notifyDataSetChanged();
}

I've read, that Collections.sort() is using a stable algorithm and therefore i'm wondering why the List of my ArrayAdapter is just being sorted by the last comparator i call.

Can anyone tell me where i made a mistake and why the first sort()-call is being ignored by the second one?

EDIT

private static final Comparator TASKCOMPARATOR = new Comparator<Task>() {
    @Override
    public int compare(Task a, Task b) {
        int timeCompareResult = a.getDueTime().compareTo(b.getDueTime());
        if (timeCompareResult == 0) {
            return a.getTitle().compareToIgnoreCase(b.getTitle());
        } else {
            return timeCompareResult;
        }
    }
};

This works. I don't know if it's the only/best way.


Solution

  • As Шах stated, use one comparator. Comparator returns 0 on equals. First compare on Title, if they are equal you go for the comparison on Time. I haven't ran the code, but it should be something like this:

    private static final Comparator TASKHOLDERCOMPARATOR_DUEDATE = new Comparator<ViewHolder>() {
        @Override
        public int compare(ViewHolder a, ViewHolder b) {
            int comparison = a.getTask().getTitle().compareToIgnoreCase(b.getTask().getTitle());
    
            if(comparison == 0){
                comparison = a.getTask().getDueTime().compareTo(b.getTask().getDueTime());
            }
            return comparison;
        }
    };