[Problem] Using Collections.sort() to sort list collections

Background:
Recently, we identified a problem of out-of-order sorting of list collections , which is considered a relatively typical problem. I would like to share it here.

Problem description:
When using the collection Collections.sort()method to collect lists 排序, an issue appears in the sorted results 乱序问题. The problem code is as follows:

CarRecord .java:

package com.sk.bean;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class CarRecord implements Comparable<CarRecord> {
    
    

    private Integer id;
    private String plateCode;
    private Long passTime;

    @Override
    public int compareTo(CarRecord o) {
    
    
        return (int) (o.passTime - this.passTime);
    }
}

Test.java

package com.sk.test;

import com.sk.bean.CarRecord;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

public class Test01 {
    
    

    public static void main(String[] args) {
    
    
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        List<CarRecord> list = new ArrayList<>();
        list.add(new CarRecord(1, "鲁A 12345", 1688634366000L));
        list.add(new CarRecord(2, "鲁A 12346", 1688568125000L));
        list.add(new CarRecord(3, "鲁A 12347", 1688504221000L));
        list.add(new CarRecord(4, "鲁A 12348", 1686144663000L));
        list.add(new CarRecord(5, "鲁A 12349", 1686094000000L));
        list.add(new CarRecord(5, "鲁A 12349", 1686043339000L));
        list.add(new CarRecord(5, "鲁A 12349", 1685992410000L));
        Collections.sort(list);
        list.stream().forEach(x -> {
    
    
            System.out.println(x.toString() + "  时间:" + sdf.format(new Date(x.getPassTime())));
        });
    }
}

Results of the:

CarRecord(id=4, plateCode=A 12348, passTime=1686144663000)  时间:2023-06-07 21:31:03
CarRecord(id=5, plateCode=A 12349, passTime=1686094000000)  时间:2023-06-07 07:26:40
CarRecord(id=5, plateCode=A 12349, passTime=1686043339000)  时间:2023-06-06 17:22:19
CarRecord(id=5, plateCode=A 12349, passTime=1685992410000)  时间:2023-06-06 03:13:30
CarRecord(id=1, plateCode=A 12345, passTime=1688634366000)  时间:2023-07-06 17:06:06
CarRecord(id=2, plateCode=A 12346, passTime=1688568125000)  时间:2023-07-05 22:42:05
CarRecord(id=3, plateCode=A 12347, passTime=1688504221000)  时间:2023-07-05 04:57:01

We passTimesort by fields, and by observing the execution results, we can clearly find that passTimethe fields of the data are out of order.

Cause of the problem:
By analyzing the code, we found that the problem occurred in the code (int) (o.passTime - this.passTime). We know that the numerical length returned by long and int types in Java is different. When the range of the difference between time o.passTime - this.passTime exceeds the range of int value, forced conversion The int type will cause data loss;
Note:
**int**The value range of is ( -2147483648~2147483647), occupying 4 bytes (-2 to the 31st power to 2 to the 31st power -1);
**long**the value range is ( -9223372036854774808~9223372036854774807), occupying 8 bytes Bytes (-2 to the power of 63 to 2 to the power of 63 -1);
passtime of id3 - passtime value of id4: 1688504221000-1686144663000=2359558000 > 2147483647
As can be seen from the above, the difference between passtimes in the same year and month is within the int value time range, so Data of the same year and month are ordered.

problem solved:

Code modification: (int) (o.passTime - this.passTime)Modify it compare(o.passTime, this.passTime)to:

Collections.sort(list, new Comparator<Long>() {
    
    
    @Override
    public int compare(Long l1, Long l2) {
    
    
        return Long.compare(l1,l2);
    }
});

View compare()the source code of the method as follows:

public static int compare(long x, long y) {
    
    
        return (x < y) ? -1 : ((x == y) ? 0 : 1);
}

Modified execution results:

CarRecord(id=1, plateCode=A 12345, passTime=1688634366000)  时间:2023-07-06 17:06:06
CarRecord(id=2, plateCode=A 12346, passTime=1688568125000)  时间:2023-07-05 22:42:05
CarRecord(id=3, plateCode=A 12347, passTime=1688504221000)  时间:2023-07-05 04:57:01
CarRecord(id=4, plateCode=A 12348, passTime=1686144663000)  时间:2023-06-07 21:31:03
CarRecord(id=5, plateCode=A 12349, passTime=1686094000000)  时间:2023-06-07 07:26:40
CarRecord(id=5, plateCode=A 12349, passTime=1686043339000)  时间:2023-06-06 17:22:19
CarRecord(id=5, plateCode=A 12349, passTime=1685992410000)  时间:2023-06-06 03:13:30

The specification requirements for Collections.sort() in Alibaba's "Java Development Manual":
Insert image description here

Guess you like

Origin blog.csdn.net/weixin_37598243/article/details/131612230