gpt4 book ai didi

java - 如何有效删除更新的 HashSet 项

转载 作者:行者123 更新时间:2023-12-03 20:23:39 26 4
gpt4 key购买 nike

鉴于以下代码段,我们如何有效地删除先前已更新/更改的元素?

public static class Foo {
@Override
public int hashCode() {
return new Random().nextInt();
}
}

public static void main(String[] args) {
Set<Foo> set = new HashSet<>();

set.add(new Foo());
set.removeIf(f -> true); // Returns true, but no deletion occurs

assert set.size() == 0; // Fails as set still contains it's single item
}
注意:上面的代码片段旨在模拟不同的 Foo下次调用 Object::hashCode (在 Set::remove 和 Set::removeIf 上)。
编辑:
对于那些不了解“随机哈希”部分的人,这里是对上述问题的不同看法:
public static class Bar {

public String firstName;
public String lastName;

public Bar() {
this(null, null);
}

public Bar(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}

@Override
public int hashCode() {
int result = 1;

result *= 59 + (firstName == null ? 43 : firstName.hashCode());
result *= 59 + (lastName == null ? 43 : lastName.hashCode());

return result;
}

}

public static void main(String[] args) {
Set<Bar> set = new HashSet<>();

String originalFirstName = "FOO";
String updatedFirstName = "FOO_CHANGED";

// Create bar
Bar bar = new Bar();
bar.firstName = originalFirstName;
bar.lastName = "BAR";

// Add bar
set.add(bar);

// Change bar
System.out.println("Bar hash (now): " + bar.hashCode());
bar.firstName = updatedFirstName;
System.out.println("Bar hash (new): " + bar.hashCode());

Bar oldBar = new Bar(originalFirstName, bar.lastName);
Bar changedBar = new Bar(bar.firstName, bar.lastName);

System.out.println("Old bar hash: " + oldBar.hashCode()); // Hash matches old value
System.out.println("Changed bar hash: " + changedBar.hashCode()); // Hash matches new value

set.remove(oldBar); // Removes no elements (returns false)
set.remove(changedBar); // Removes no elements (returns false)
set.removeIf(f -> true); // Removes no elements (returns true)

Iterator<Bar> iterator = set.iterator();

while (iterator.hasNext()) {
iterator.next();
iterator.remove(); // Fails silently
}

assert set.size() == 0;
}
根本没有随机散列。
确实有不同的哈希值,但显然,如果元素被更改(因此,它们的哈希值),则无论如何都无法删除元素。我们可以在 Set::remove 上确认这一点。电话,在哪里 set.remove(oldBar)应该将元素删除为 oldBar hash 等于 bar 时的 hash加入。

最佳答案

这里的问题是,如果您以哈希码不同的方式修改对象,那么它在结构上不再是相同的对象。另一种说法,original.equals(modified)false (或者至少应该是由于 equals()hashCode() 的契约。一种解决方案是修改 hashCode() 以基于一些不变量进行计算。换句话说,返回的哈希码仅基于Foo 无论如何都不会改变的对象。例如,这可能是一个 id ,例如映射到基础数据库表的对象。
或者,您可以找到更适合您的用例的不同数据结构。例如 ArrayList可能更合适,因为您可以删除给定索引处的项目,而不管该对象的状态如何。

关于java - 如何有效删除更新的 HashSet 项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65834166/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com