Search code examples
javaandroidsortinglambda

Sorting multiple fields from an object in natural order


Currently I'm using a lamda sort to sort listID first, then Item Name second

Comparator < Item > itemComparator = Comparator.comparing(Item::getListId)
                                               .thenComparing(Item::getItemName);
Collections.sort(itemList, itemComparator);

Which technically works, but ItemName is alphanumeric and sorts by ASCII instead of natural order So instead of Item 0, Item 101, Item 28. I want Item 0, Item 28, Item 101. Is there a simple way to do this?

Edit: Item is taking info from a JSON File

    [{"id": 684, "listId": 1, "name": "Item 684"},
    {"id": 276, "listId": 1, "name": "Item 276"},
    {"id": 808, "listId": 4, "name": "Item 808"},
    {"id": 680, "listId": 3, "name": "Item 680"},
    {"id": 534, "listId": 4, "name": "Item 534"},
    {"id": 906, "listId": 2, "name": "Item 906"},
    {"id": 735, "listId": 1, "name": "Item 735"},

Solution

  • "... So instead of Item 0, Item 101, Item 28. I want Item 0, Item 28, Item 101. Is there a simple way to do this? ..."

    You could parse the numeric value within name, from the closure.

    Comparator<Item> comparator
        = Comparator.comparing(Item::getListId)
                    .thenComparing(value -> {
                        int indexOf = value.name.indexOf(' ');
                        return Integer.parseInt(value.name.substring(indexOf + 1));
                    });
    list.sort(comparator);
    

    Output

    [{id=276, listId=1, name='Item 276'},
     {id=684, listId=1, name='Item 684'},
     {id=735, listId=1, name='Item 735'},
     {id=906, listId=2, name='Item 906'},
     {id=680, listId=3, name='Item 680'},
     {id=534, listId=4, name='Item 534'},
     {id=808, listId=4, name='Item 808'}]