具有日期和最大增量的类的 Java hashCode 方法

问题描述 投票:0回答:1

在java中,对于具有日期的类来说,什么是一个好的hashCode方法,如果日期具有预定义的最大差异,则对象被认为是相等的。 示例类:

public class Test {
    private static final int MILLISECONDS_IN_A_DAY = 24 * 60 * 60 * 1000;
    private Date date;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Test other = (Test) o;
        return ((date == null && other.date == null) ||
                (date != null && other.date != null &&
                 Math.abs(date.getTime() - other.date.getTime()) < MILLISECONDS_IN_A_DAY));
    }
}

我应该探索不同的策略吗?也许是另一个比较函数,无论是内部函数还是外部函数? 也许实现 Comparable 接口会更好?

java hashcode
1个回答
0
投票

我建议不要创建自定义

equals()
hashCode()
实现。

您需要为您的类定义一个比较器:

package org.example;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

public class ComparableDate implements Comparable<ComparableDate> {
    private static final long MILLISECONDS_IN_A_DAY = TimeUnit.DAYS.toMillis(1);

    private final LocalDateTime date;

    public ComparableDate(LocalDateTime date) {
        this.date = date;
    }

    public LocalDateTime getDate() {
        return date;
    }

    @Override
    public int compareTo(ComparableDate other) {
        if (this == other) return 0;
        if (other == null || other.date == null) return -1;
        if (date == null) return 1;
        long diffInMillis = ChronoUnit.MILLIS.between(date, other.date);
        if (Math.abs(diffInMillis) < MILLISECONDS_IN_A_DAY) return 0;
        return (int) Math.signum(diffInMillis - MILLISECONDS_IN_A_DAY);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        ComparableDate that = (ComparableDate) o;
        return Objects.equals(date, that.date);
    }

    @Override
    public int hashCode() {
        return Objects.hash(date);
    }

    public static void main(String[] args) {
        ComparableDate a = fromString("2023-12-25T08:00:00Z");
        ComparableDate b = fromString("2023-12-25T12:00:00Z");
        ComparableDate c = fromString("2023-12-26T12:00:00Z");

        System.out.println(a.compareTo(b)); // 0 "equal"
        System.out.println(a.compareTo(c)); // 1 "not equal"
    }

    private static ComparableDate fromString(String timestamp) {
        return new ComparableDate(LocalDateTime.parse(timestamp, DateTimeFormatter.ISO_DATE_TIME));
    }
}

或者更好的是,创建一个自定义比较器:

package org.example;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Comparator;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

public class ComparableDate {
    private final LocalDateTime date;

    public ComparableDate(LocalDateTime date) {
        this.date = date;
    }

    public LocalDateTime getDate() {
        return date;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        ComparableDate that = (ComparableDate) o;
        return Objects.equals(date, that.date);
    }

    @Override
    public int hashCode() {
        return Objects.hash(date);
    }

    public static void main(String[] args) {
        DateComprator comparator = new DateComprator();

        ComparableDate a = fromString("2023-12-25T08:00:00Z");
        ComparableDate b = fromString("2023-12-25T12:00:00Z");
        ComparableDate c = fromString("2023-12-26T12:00:00Z");

        System.out.println(comparator.compare(a, b)); // 0 "equal"
        System.out.println(comparator.compare(a, c)); // 1 "not equal"
    }

    private static ComparableDate fromString(String timestamp) {
        return new ComparableDate(LocalDateTime.parse(timestamp, DateTimeFormatter.ISO_DATE_TIME));
    }

    private static class DateComprator implements Comparator<ComparableDate> {
        private static final long MILLISECONDS_IN_A_DAY = TimeUnit.DAYS.toMillis(1);

        @Override
        public int compare(ComparableDate that, ComparableDate other) {
            if (that == other) return 0;
            if (other == null || other.date == null) return -1;
            if (that == null || that.date == null) return 1;
            long diffInMillis = ChronoUnit.MILLIS.between(that.date, other.date);
            if (Math.abs(diffInMillis) < MILLISECONDS_IN_A_DAY) return 0;
            return (int) Math.signum(diffInMillis - MILLISECONDS_IN_A_DAY);
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.