简体   繁体   中英

Sort the Objects with comparator logic in java

I am trying to sort the list of objects with following parameters

a.group the two list objects whose partId is same as id of other object

b. Push any object whose partId is null to the end of the list.

c. sort the grouped objects based on the count in ascending order, preference is to

I. both the objects in the group should have less count

II. then any object in group having less count than other groups.

Below is the code I have so far,

public class ListTTest {
    public static void main(String[] args) {
        LstObj lstObj1 = new LstObj("0:0:1", "1:0:1", 49);
        LstObj lstObj2 = new LstObj("0:0:2", "1:0:2", 2);
        LstObj lstObj3 = new LstObj("0:2:1", "1:2:1", 0);
        LstObj lstObj4 = new LstObj("0:2:2", null , 0);
        LstObj lstObj5 = new LstObj("0:2:3", "1:2:3" , 2);
        LstObj lstObj6 = new LstObj("0:2:4", "1:2:4" , 49);
        LstObj lstObj7 = new LstObj("1:0:1", "0:0:1" , 49);
        LstObj lstObj8 = new LstObj("1:0:2", "0:0:2" , 49);
        LstObj lstObj9 = new LstObj("1:2:1", "0:2:1" , 0);
        LstObj lstObj10 = new LstObj("1:2:2", null , 0);
        LstObj lstObj11 = new LstObj("1:2:3", "0:2:3" , 49);
        LstObj lstObj12 = new LstObj("1:2:4", "0:2:4" , 49);


        LstObj lst[] = new LstObj[]{lstObj1,lstObj2,lstObj3,lstObj4,lstObj5,lstObj6,lstObj7,lstObj8,lstObj9,lstObj10,lstObj11,lstObj12};
        List<LstObj> lstArr = Arrays.asList(lst);

        lstArr.sort(new Comparator<LstObj>() {
            @Override
            public int compare(LstObj o1, LstObj o2) {
                    if(o1.partId==null){
                        return 1;
                    }else if(o2.partId==null){
                         return -1;
                    }else{
                        return -1*(o1.partId.compareTo(o2.id)-(o1.count-o2.count));
                    }

            }
        });

        System.out.println(lstArr);
    }


}

class LstObj {
    String partId;
    String id;
    int count;

    public LstObj(  String id,
    String partId,
    int count
    ) {
        this.count = count;
        this.partId = partId;
        this.id = id;       
    }

    public String getPartId() {
        return partId;
    }
    public String getId() {
        return id;
    }
    public int getCount() {
        return count;
    }
    public void setPartId(String partId) {
        this.partId = partId;
    }
    public void setId(String id) {
        this.id = id;
    }
    public void setCount(int count) {
        this.count = count;
    }

    @Override
    public String toString() {
        return "LstObj [partId=" + partId + ", id=" + id + ", count=" + count
                + "]\n";
    }


}

Output for above code is :

[LstObj [partId=1:2:1, id=0:2:1, count=0]
    , LstObj [partId=1:2:3, id=0:2:3, count=2]
    , LstObj [partId=0:2:1, id=1:2:1, count=0]
    , LstObj [partId=1:0:2, id=0:0:2, count=2]
    , LstObj [partId=1:2:4, id=0:2:4, count=49]
    , LstObj [partId=0:2:3, id=1:2:3, count=49]
    , LstObj [partId=1:0:1, id=0:0:1, count=49]
    , LstObj [partId=0:0:1, id=1:0:1, count=49]
    , LstObj [partId=0:0:2, id=1:0:2, count=49]
    , LstObj [partId=0:2:4, id=1:2:4, count=49]
    , LstObj [partId=null, id=0:2:2, count=0]
    , LstObj [partId=null, id=1:2:2, count=0]

But I am looking for output as:

 [LstObj [partId=0:2:1, id=1:2:1, count=0]
    , LstObj [partId=1:2:1, id=0:2:1, count=0]
    , LstObj [partId=0:0:2, id=1:0:2, count=2]
    , LstObj [partId=1:0:2, id=0:0:2, count=49]
    , LstObj [partId=0:2:3, id=1:2:3, count=2]
    , LstObj [partId=1:2:3, id=0:2:3, count=49]
    , LstObj [partId=0:0:1, id=1:0:1, count=49]
    , LstObj [partId=1:0:1, id=0:0:1, count=49]
    , LstObj [partId=0:2:4, id=1:2:4, count=49]
    , LstObj [partId=1:2:4, id=0:2:4, count=49]
    , LstObj [partId=null, id=0:2:2, count=0]
    , LstObj [partId=null, id=1:2:2, count=0]

Anybody have any idea where exactly I'm doing wrong?

It is impossible to implement a comparator applying your intended grouping logic by just looking at two elements of the list.

You may perform a dedicated grouping operation and sort the groups, followed by creating a result list afterwards. The builtin grouping collector requires a function that is capable of assigning each element to a group without seeing the counterpart, but if you use a stable selector, eg using the minimum of partId and id , the correct elements will end up in one group, as long as your input data has the right shape.

List<LstObj> lstArr = Arrays.asList(
    new LstObj("0:0:1", "1:0:1", 49),
    new LstObj("0:0:2", "1:0:2", 2),
    new LstObj("0:2:1", "1:2:1", 0),
    new LstObj("0:2:2", null , 0),
    new LstObj("0:2:3", "1:2:3" , 2),
    new LstObj("0:2:4", "1:2:4" , 49),
    new LstObj("1:0:1", "0:0:1" , 49),
    new LstObj("1:0:2", "0:0:2" , 49),
    new LstObj("1:2:1", "0:2:1" , 0),
    new LstObj("1:2:2", null , 0),
    new LstObj("1:2:3", "0:2:3" , 49),
    new LstObj("1:2:4", "0:2:4" , 49)
);

Function<LstObj,Object> groupFunc = o -> {
    String id = o.getId(), partId = o.getPartId();
    return partId == null? Void.TYPE: partId.compareTo(id)<0? partId: id;
};
List<LstObj> result = lstArr.stream()
        .sorted(Comparator.comparing(LstObj::getPartId, Comparator.nullsLast(null))
                          .thenComparingInt(LstObj::getCount))
        .collect(Collectors.groupingBy(groupFunc, LinkedHashMap::new, Collectors.toList()))
        .values().stream()
        .flatMap(List::stream)
        .collect(Collectors.toList());
System.out.println(result);

This sorts all elements, moving all objects whose partId is null to the end of the list and sorting by count as secondary order. The subsequent grouping operation uses a LinkedHashMap which retains the encounter order, effectively sorting the groups according to their first encountered element, which is the one with the minimum count. The groups are then flattened to a result list.

The result fulfills the specified criteria of your question but does not exactly produce the list you have posted as desired result, as the order of the elements within the groups is underspecified. The code above sorts them by count, as a side effect of initial sorting, and keeps the original list order for elements with the same count.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM