在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 接口会更好?
我建议不要创建自定义
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);
}
}
}