一次未重写父类hashCode和equal方法引发的线上问题

问题描述

定义一个集合用它来收集一些特殊对象,后续对集合中的元素做操作。 集合是一个HashSet,上线后发现异常,有些应该进去的偏偏进不去。 分析过程因为代码中使用到了RedisTemplate的HashOperations,因为我每次操作都是同一个HashOperations对象,所以开始怀疑HashOperations不是线程安全的,后面证实它在并发环境下没有问题。 于是线下模拟一遍, 发现HashSet永远只有一个,但是其实每次add进去的都是新的,为什么没有新增? 后面才发现原来自定义对象没有重写其父类的hashCodeequal方法。

定义类DownloadFinished,它继承一个父类BaseEntity

@Getter
@Setter
public class DownloadFinished extends BaseEntity {
    
    

    private Integer cd;

    private Long ruleId;

    private Object busId;
}

BaseEntity

@Data
public class BaseEntity implements Serializable {
    
    

    @TableId(type = IdType.AUTO)
    private Long id;

    private Date createTime;

    private Integer createBy;

    private Date updateTime;

    private Integer updateBy;
    @TableLogic
    private Long isDeleted;

    public Long getDeleted() {
    
    
        return isDeleted;
    }

    public void setDeleted(Long deleted) {
    
    
        isDeleted = deleted;
    }
}
    public static void main(String[] args) {
    
    
        Collection<DownloadFinished> finishedSet = Sets.newHashSet();

        for (int i = 0; i < 2; i++) {
    
    
            DownloadFinished finished = new DownloadFinished();
            finished.setCampaignId(i);
            finished.setVehicleId(i + 1);
            finishedSet.add(finished);
        }

        System.out.println(finishedSet);
        System.out.println(finishedSet.size());
    }

在这里插入图片描述
finishedVehicle集合应该有两个才对,但是只有一个。
因为HashSet底层还是用HashMap来实现的,所以判断两个对象是否一致会去看hashCode方法,因为DownloadFinished 没有重写父类BaseEntity的hashCode方法,又因父类属性没有改变,所以每次都当做是一样的了。

稍微调整后

@Getter
@Setter
@EqualsAndHashCode
public class DownloadFinished extends BaseEntity {
    
    

    private Integer cd;

    private Long ruleId;

    private Object busId;
}

直接使用lombok注解**@EqualsAndHashCode**来实现hashCode和equal方法的重写。

再次运行:
在这里插入图片描述
本来是很简单很基础的问题,但是自己却忽略了,归根到底还是因为自己没有深入理解其中的含义。 这块后续需加强JDK基础学习,深入JDK源码分析…

猜你喜欢

转载自blog.csdn.net/huangdi1309/article/details/122406529