让我们来上课...
class Foo {
private Bar1 bar1;
private Bar2 bar2;
// many other fields
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Foo foo = (Foo) o;
if (!bar1.equals(foo.getBar1()) return false;
if (!bar2.equals(foo.getBar2()) return false;
// etc...
}
@Override
public int hashCode() {
int result = bar1.hashCode();
result = 31 * result + bar2.hashCode();
// etc...
}
// setters & getters follow...
}
每分钟创建,处理数千个Foo实例,然后在池中对其进行回收。工作流程如下:
Set<Foo> foos = new THashSet<>();
while (there-is-data) {
String serializedDataFromApi = api.getData();
Set<Foo> buffer = pool.deserializeAndCreate(serializedDataFromApi);
foos.addAll(buffer);
}
processor.process(foos);
pool.recycle(foos);
问题在于,不同的缓冲区之间可能存在重复的foo对象(具有相同的值)。它们被实现为Foo的不同实例,但是在调用foos.addAll(buffer)时被视为相等。
我的问题是:
答案 0 :(得分:2)
那些“重复”实例发生了什么? 他们“丢失”并收集垃圾了吗?
是的,这些对象将在while (there-is-data)
当前迭代完成后立即获得GC资格
如果我想让这些实例在池中保持可用,那么在使用addAll并回收实例插入之前,测试重复项的最有效方法是什么?
Set.add
如果插入了元素,则返回true
,如果是重复的,则返回false
。因此,您可以用
addAll
for (Foo f : buffer) {
if (!foos.add(f)) {
// handle duplicate
}
}
不会对性能造成任何影响,因为addAll
所做的相同-迭代并逐个添加。