场景:
数据存入HashSet<DeviceSchedulerStatusDto>中, 中间经过操作,对HashSet的数据中布尔类型的status属性进行了修改(true改成了false)
涉及到的类如下实体类DeviceSchedulerStatusDto
@Data
@AllArgsConstructor
@Builder
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class DeviceSchedulerStatusDto<S extends Thread> {
//枚举类型
private DeviceType deviceType;
private String number;
//布尔类型
private Boolean status;
//泛型,继承Thread
private S scheduler;
@Override
public String toString() {
return String.format("%s-%s", deviceType.getDescription(), number);
}
}
问题
如下代码,想要删除HashSet中经过修改的数据,Debug发现代码已经执行过 iterator.remove(),但是查看A.status中的数据仍然没有被删除掉。
public void getSchedulerStatusVo() {
//A.status是HashSet类型
Iterator<DeviceSchedulerStatusDto> iterator = A.status.iterator();
while (iterator.hasNext()){
DeviceSchedulerStatusDto status = iterator.next();
if (null != status.getScheduler()) {
iterator.remove();
}
}
}
经过查看的源码发现,HashSet存入的数据会进行hashcode()的计算,而在remove()时会再次调用对象的hashcode()方法来比较,如果hashcode()计算出来的值相同,才会真正执行remove。
而我们中间对HashSet中数据的属性进行了修改,但是它的hashcode()值是没有重新计算的,导致remove时调用hashcode()计算出的值HashSet中不存在,则没有进行删除操作。所以我们可以重写对象的hashcode()方法,来决定使用哪些属性进行hash计算.。
解决方法
实体类DeviceSchedulerStatusDto重写hsahcode方法:枚举类型取它的int值,String类型不动,Boolean类型及线程类型不加入hashcode()计算方法中,代码如下:
@Data
@AllArgsConstructor
@Builder
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@ApiModel(description = "设备调度线程状态")
public class DeviceSchedulerStatusDto<S extends Thread> {
@ApiModelProperty(value = "类型")
private DeviceType deviceType;
@ApiModelProperty(value = "编号")
private String number;
@ApiModelProperty(value = "调度线程当前状态:true 启动 ,false 停止")
private Boolean schedulerStatus;
@ApiModelProperty(value = "调度线程")
@JsonIgnore
private S scheduler;
@Override
public String toString() {
return String.format("%s-%s", deviceType.getDescription(), number);
}
@Override
public int hashCode() {
return Objects.hash(deviceType.getIntValue(), number);
}
}
这样就可以使用iterator的remove()方法实现删除操作了。