[질문] 목록 컬렉션을 정렬하려면 Collections.sort()를 사용하세요.

배경: 최근 대표적인 문제인 목록 수집 정렬 장애
문제가 발견되어 여기에 공유하겠습니다.

문제 설명 컬렉션의 메소드를
사용하여 목록 컬렉션을 정렬하면 정렬 결과에 나타나는데 문제 코드는 다음과 같습니다.Collections.sort()排序乱序问题

자동차 기록 .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())));
        });
    }
}

결과:

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

필드별로 정렬 하고 실행 결과를 관찰하면 데이터 필드의 순서가 잘못되었음을 passTime명확하게 알 수 있습니다 .passTime

문제 원인 :
코드를 분석한 결과 코드에서 문제가 발생하는 것으로 확인되었으며 (int) (o.passTime - this.passTime), Java에서 long 및 int 유형의 값의 길이를 반환하는 방식이 동일하지 않음을 알 수 있습니다. 유형은 데이터 손실을 유발합니다.
참고:
**int**값 범위는 ( -2147483648~2147483647)이며 4바이트(-2의 2-1의 31승)를 차지합니다.
**long**값 범위는 ( -9223372036854774808~9223372036854774807), 8바이트를 차지합니다. 바이트(-2의 63승) 2의 2의 63승 -1),
id3-id4의 passtime 값: 1688504221000-1686144663000=2359558000 > 2147483647
위에서 알 수 있듯이 같은 연도와 월의 passtime의 차이는 int 수치의 시간 범위 내에 있으므로 id3-id4의 Data는 같은 연도와 달이 주문됩니다.

문제 해결됨:

코드 수정: 다음과 같이 (int) (o.passTime - this.passTime)수정하세요 compare(o.passTime, this.passTime).

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

compare()다음과 같이 메소드의 소스 코드를 확인하세요 .

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

수정된 실행 결과:

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

Collections.sort() 사양 요구 사항의 Ali "java 개발 매뉴얼":
여기에 이미지 설명을 삽입하세요.

Supongo que te gusta

Origin blog.csdn.net/weixin_37598243/article/details/131612230
Recomendado
Clasificación