You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中年月元组的hashCode实现方案(用于重复组合判断)

嘿,这个问题问到点子上了!正好《Effective Java》里的哈希码实现准则完全适配你的年月对象场景,我给你拆解一下怎么写,连带着把equals也补上——毕竟这俩方法是绑定在一起的,缺一不可~

第一步:定义你的年月对象并实现核心方法

首先先把包含year和month的类写出来,参数校验、equals、hashCode一个都不能少:

public class YearMonthPair {
    // 用final修饰保证不可变性,这对哈希表的稳定性很重要
    private final int year;
    private final int month;

    public YearMonthPair(int year, int month) {
        // 先做参数校验,避免无效的月份值混入
        if (month < 1 || month > 12) {
            throw new IllegalArgumentException("Month must be between 1 and 12");
        }
        this.year = year;
        this.month = month;
    }

    // 先实现equals,因为hashCode必须和equals逻辑保持一致
    @Override
    public boolean equals(Object o) {
        // 先判断是否是同一个对象,快速返回
        if (this == o) return true;
        // 空值或者类不匹配直接返回false
        if (o == null || getClass() != o.getClass()) return false;
        // 强转后比较两个核心字段
        YearMonthPair that = (YearMonthPair) o;
        return year == that.year && month == that.month;
    }

    // 重点:按照《Effective Java》推荐实现hashCode
    @Override
    public int hashCode() {
        // 初始值用第一个字段year
        int result = year;
        // 用31作为乘数,然后加上第二个字段month
        result = 31 * result + month;
        return result;
    }

    // 可选:重写toString方便调试和打印
    @Override
    public String toString() {
        return year + ":" + String.format("%02d", month);
    }
}
为什么这么实现hashCode?

这完全是遵循《Effective Java》里的经典原则:

  • 一致性:如果两个对象通过equals()判断相等,它们的hashCode()必须返回相同的值;反之,不等的对象尽量返回不同的哈希值(减少碰撞)。
  • 选择31作为乘数:31是一个奇素数,一方面能有效减少不同组合产生相同哈希值的概率,另一方面JVM会自动把31 * result优化为(result << 5) - result(左移5位等于乘32,减1就是乘31),效率很高。
  • 字段组合逻辑:先以year为基础,再叠加month,确保不同的年月组合(比如2018:03和2018:04、2017:12和2018:01)能生成差异化的哈希值。
实际使用示例

你可以直接把这个对象放进HashSet里完成去重操作,或者用HashMap做键:

import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class Demo {
    public static void main(String[] args) {
        List<String> rawYearMonthList = Arrays.asList("2018:03", "2019:05", "2018:03", "2020:12", "2019:05");
        Set<YearMonthPair> uniquePairs = new HashSet<>();

        for (String s : rawYearMonthList) {
            String[] parts = s.split(":");
            int year = Integer.parseInt(parts[0]);
            int month = Integer.parseInt(parts[1]);
            uniquePairs.add(new YearMonthPair(year, month));
        }

        // 输出去重后的结果
        uniquePairs.forEach(System.out::println);
    }
}
额外小提示

如果你用的是Java 8及以上版本,其实不用自己写这个类!JDK自带的java.time.YearMonth已经完美实现了equals()和hashCode(),还自带了很多日期处理的方法,直接用它更省心:

import java.time.YearMonth;

// 直接创建实例
YearMonth ym = YearMonth.of(2018, 3);
// 放进HashSet去重完全没问题
Set<YearMonth> uniqueYmSet = new HashSet<>();

内容的提问来源于stack exchange,提问作者JacksOnF1re

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 09:10:06