javasortingjava-8groupingby

Java 8 Map group by orderid and sort by itemLeastDate


I want the DB records list to be groupby orderId and sort by itemDate.

I am getting records from db like this in any order. Same OrderId's record will come in different order.

OrderId Item Number Item Date
1       12345       3/10/21
2       67890       4/10/21
1       12345       3/11/21  -> duplicate. so take least date of Item 12345
1       23456       3/11/21  -> don't remove this one as itemnumb is unique
3       33441       5/10/21
2       67890       4/11/21  -> duplicate. so take least date 4/10/21 record
2       12333       4/11/21
3       33441       5/11/21  -> duplicate. so take least date 5/10/21 record
3       45321       5/11/21

I need to return only the top record sorted by least Item Date first. The second record for same order id is not needed.

POJO

public class ItemDetail {

    private String orderId;
    private String itemNumber;
    private Date itemDate;

    //setter/getters
}

DAO layer will return itemDetails list i.e., List itemDetails;

From itemDetails List I have to set the key, value in map like below code,

I need to store key as OrderId-ItemNumber combination in String, value as ItemDetail object

public List<ItemDetail> getItemDetails(List<ItemDetail> itemDetails) {
 Map<String, ItemDetail> itemMap = itemDetails.stream()
        .collect(Collectors.groupingBy(itemDetail -> itemDetail.getOrderId()))
        .values()
        .stream()
        .collect(Collectors.toMap(itemDetail -> itemDetail.getOrderId() +"-"+ itemDetail.getItemNumber(), 
                 itemDetail -> itemDetail));
return mapValueAsItemDetailList;
}

Finally the map should return records like this only

OrderId Item Number Item Date
1       12345       3/10/21
1       23456       3/11/21
2       67890       4/10/21
2       12333       4/11/21
3       33441       5/10/21
3       45321       5/11/21

In simple terms, I need to group by orderId-itemNumber and sort by item date and return only least date records. Don't remove the unique item number records of same order id. How to do this in Java 8?

Take one record. 12345 is not unique. so remove the 2nd record of highest date. Need to keep the unique records and remove the duplicate by itemdate.

1       12345       3/10/21
1       12345       3/11/21
1       23456       3/11/21

So only I want to keep the key as orderId-itemNumber


Solution

  • First, consider using LocalDate. Date is very outdated.

    private LocalDate itemDate;
    

    To remove all but the oldest item details with the same order IDs, you can use the toMap collector to make a map first: 1. use the order ID + item number as key and 2. the item details themselves as value. 3. Specify that when there is a duplicate key, choose the item detail with the older date as the value.

    After that, get the values of the map, and create a list out of it. Then sort the list by date.

    public List<ItemDetail> getItemDetails(List<ItemDetail> itemDetails) {
        ArrayList<ItemDetail> list = new ArrayList<>(itemDetails.stream().collect(
            Collectors.toMap(
                x -> x.getOrderId() + x.getItemNumber(), // 1
                Function.identity(), // 2
                BinaryOperator.minBy( // 3
                    Comparator.comparing(ItemDetail::getItemDate)
                )
            )
        ).values());
        list.sort(Comparator.comparing(ItemDetail::getItemDate));
        return list;
    }