问题描述
public class TestClass implements Cloneable {
private Long value;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class MainClass {
public Set method(List testList)
throws CloneNotSupportedException {
Set result = new HashSet<>();
for (int a = 0; a < 100000) {
for (TestClass test : testList) {
result.add(test.clone());
}
}
}
}
看上去,上述代码实现了对传入的 testList 去重的代码逻辑,虽然重复了很多很多次,但我们的去重代码并不会造成额外的空间浪费
但是事实上,clone、new 操作都是重新在内存中分配空间,这也就意味着他们的地址是不同的,而所有的类由于都继承了 Object,所以他们的 equals 方法都来源于 Object 类,默认的实现是返回对象地址
因此,虽然是 clone 得到的对象在 Set 中去重,但是 Set 还是认为他们是不同的对象,从而反复添加造成最终抛出 OutOfMemoryError
改进
改进方式很简单,对于自定义的类,添加所需的适当 equals 方法的实现即可
public class TestClass implements Cloneable {
private Long value;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public boolean equals(Object obj) {
return Objects.equals(obj.value, value);
}
}
public class MainClass {
public Set method(List testList)
throws CloneNotSupportedException {
Set result = new HashSet<>();
for (int a = 0; a < 100000) {
for (TestClass test : testList) {
result.add(test.clone());
}
}
}
}