lombok之hashCode

#Lombok重写hashCode

凶案现场

 在紧张的开发节奏下,毛十三需要对列表中id重复的对象进行去重,十三苦苦寻找,终于发现前辈们已经在中工具类中封装好了该方法,于是一行代码调用方法堪称完美的完成了需求,愉快的关机回家奋战王者峡谷。

 十三奋战到深夜,在QA同学的带领下狂掉十颗星,第二天垂头丧气的来到公司,QA同学为了表达掉星的不满,带着bug怒气冲冲的找上门了,你这个去重的太过分了,去多了,把我的星都去完了,十三一脸无辜,掉分也不能栽赃嫁祸吧,于是飞速debug,想要一洗清白。

 哐哐哐,一顿操作猛如虎,一看bug比0-5还伤心,于是回头土脸的向QA同学跪地求饶。

 然后卸载游戏,闭关修炼,陷入沉思,这个去重工具类里面究竟发生了啥,居然让我颜面扫地,我要把这段代码删掉~~~

场景还原

 十三带怒气冲冲的点进工具类,发现这段代码似乎没问题啊

	/**
     * 已脱敏
     */
    public static void duplicateTemplateList(List<TemplateVO> templateVOList) {
        Set<String> itemIdList = new HashSet<>();

        List<TemplateVO> filterList = new ArrayList<>();
        for (TemplateVO templateVO : templateVOList) {
            if (null == templateVO || StringUtils.isBlank(templateVO.getItemId())) {
                continue;
            }

            if (!itemIdList.contains(templateVO.getItemId())) {
                itemIdList.add(templateVO.getItemId());
            } else {
                filterList.add(templateVO);
            }
        }

        templateVOList.removeAll(filterList);
    }

然后十三复刻生产环境,龙潭虎穴也要一探究竟:

import lombok.Data;

import java.io.Serializable;

/**
 * @author maoshisan
 * @date 2020-01-14
 */
@Data
public class TemplateVO implements Serializable {

    private String itemId;


    /**
     * 你猜我有没有title
     */
    private String commonTitle;

    /**
     * 你别瞎扯了
     */
    private String commonDesc;
}  
 @Test
    public void testDuplicate() {
        List<TemplateVO> templateVOList = new ArrayList<>();
        templateVOList.add(new TemplateVO("111", "hahaha", "hahahha"));
        templateVOList.add(new TemplateVO("112", "hahahaxx", "hahahhaxx"));
        templateVOList.add(new TemplateVO("113", "hahahaxx", "hahahhaxx"));
        templateVOList.add(new TemplateVO("114", "hahahaxx", "hahahhaxx"));
        templateVOList.add(new TemplateVO("111", "hahahaxx", "hahahhaxx"));
        templateVOList.add(new TemplateVO("111", "hahaha", "hahahha"));
        templateVOList.add(new TemplateVO("112", "hahahaxx", "hahahhaxx"));

        ProductTemplateHelper.duplicateTemplateList(templateVOList);

        System.out.println(templateVOList);
    } 

先遍历找出需要去掉的对象,看起来一切正常
Stream创建流程
removeAll移除需去重的对象,结果让十三大跌眼镜,我的111和112咋全部不见了,filterList只有三个对象啊。
Stream创建流程

为了一探究竟,十三要看看究竟发生了啥,故事进展到这里十三似乎明白了,Lombok重写了hashCode,导致具有相同属性的对象hashCode相同,所以列表里的111和112全部被移除了
Stream创建流程

Lombok @Data使用注意小心呀

  1. @EqualsAndHashCode 注解中实现了hashCode和equals方法, @Data注解包含了@Getter @Setter @RequiredArgsConstructor @ToString @EqualsAndHashCode5个注解。
  2. @EqualsAndHashCode通过对象属性的计算hashCode和equals方法,与对象内存地址无关,因此具有相同属性的两个对象会被判断为相等,但是equals判断相等的两个对象并不一定指向同一内存地址
  3. 在继承关系中,父类的hashCode针对父类的所有属性进行运算,而子类的hashCode却只是针对子类才有的属性进行运算,那么就会存在部分对象在比较时,它们并不相等,却因为lombok自动生成的equals(Object other) 和 hashCode()方法判定为相等,从而导致出错。

反思

  1. 慎用lombok的hashCode和equals,如果业务区分两属性相同的对象,必须重写hashCode,带上内存地址System.identityHashCode(obj)
  2. 好好对待QA同学,千万别带他们掉分
发布了6 篇原创文章 · 获赞 0 · 访问量 1065
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览