当使用lombok @Data后使相等更简单的坑

最近在用到removeAll时遇到的疑问。

分析问题

实体类

@Data
public class EntityVo extends Entity {

    .....
}

通过Collection集合去实现删除包含的元素

    collection.removeAll(arr);

代码一执行,全部都被删了

原因解析: 先看API

boolean removeAll(Collection<?> c)

从列表中移除指定 collection 中包含的其所有元素(可选操作)。 

没错,就是移除子集合包含的元素 再看API说明,移除所包含的其所有元素,注意这个字眼:包含! 因为在执行removeAll方法时,会先对集合元素进行比较,如果元素相等才执行移除操作,说到这,相信很多人都已经明白是怎么回事了,因为相等(equals),所以执行移除。

查看源码进一步证实上述猜测,remove和removeAll的方法实现在:

java.util.AbstractCollection<E>
具体代码为:

 public boolean removeAll(Collection<?> c) {
        boolean modified = false;
        Iterator<?> it = iterator();
        while (it.hasNext()) {
            if (c.contains(it.next())) {
                it.remove();
                modified = true;
            }
        }
        return modified;
}

得出问题原因

可以看到在调用removeAll方法时,实际上是循环调用了remove方法,而remove方法中有一段关键的代码:if (o.equals(it.next())) !

So,得出结论,因为上述例子实体类中加入了lombok @Data!而在执行removeAll方法时是通过equals方法来判断集合元素是否相等的,EqualsAndHashCode 不会调用父类的 equals 方法,所以会出现上述问题!

@Data 相当于 @Getter @Setter @RequiredArgsConstructor @ToString @EqualsAndHashCode 这5个注解的合集。 通过官方文档,可以得知,当使用@Data注解时,则有了@EqualsAndHashCode注解,那么就会在此类中存在equals(Object other)hashCode()方法,且不会使用父类的属性,这就导致了可能的问题。

比如,有多个类有相同的部分属性,把它们定义到父类中,恰好id(数据库主键)也在父类中,那么就会存在部分对象在比较时,它们并不相等,却因为lombok自动生成的equals(Object other)hashCode()方法判定为相等,从而导致出错。

解决办法

修复此问题的方法很简单:

  1. 使用@Getter @Setter @ToString代替@Data并且自定义equals(Object other)hashCode()方法,比如有些类只需要判断主键id是否相等即足矣。
  2. 或者使用在使用@Data时同时加上@EqualsAndHashCode(callSuper=true)注解。
@Data
+ @EqualsAndHashCode(callSuper=true)
public class Entity {

    .....
}

转载于:https://my.oschina.net/johnsken/blog/3049611

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值