gpt4 book ai didi

Java LinkedHashSet 索引有效性

转载 作者:行者123 更新时间:2023-11-30 07:25:41 26 4
gpt4 key购买 nike

我一直在将一大块 Java 代码移植到 C++,并且在我离开时不得不实现 LinkedHashSet 之类的东西。我已经使用 Boost 的多索引容器对 LinkedHashSet/Map 进行了合理的复制。

在移植代码时,我遇到了一些关于 multi_index 的有趣内容,因为包含的对象不是可变的(除非您将类的特定字段标记为可变)。但是,如果 key 是根据所包含类的一些可变成员计算的,那么事情就会变得有趣。

为了澄清一些事情,我想我会用 Java 编写一个简单的示例来检查其 LinkedHashSet 的行为。结果让我有点惊讶;看起来它们的行为类似于 Boost 的 Multi Index 容器,因为当包含的对象被修改时(如您所料)不会重新生成索引;但是编译器不会以任何方式提示 --- 似乎很容易搬起石头砸自己的脚(我正在移植的代码似乎犯了上述的错误,谁知道它仍然如何工作)。

这只是 Java 中缺少 const_iterators 的限制,还是我设法做了一些特别愚蠢或棘手的事情?

这是一个简单的例子:

class StringContainer                                                        
{
public String s;

public StringContainer(String s)
{
this.s = s;
}

public boolean equals(Object t1)
{
StringContainer other = (StringContainer) t1;
return this.s == other.s;
}

public int hashCode()
{
int val = 8;
for (int i = 0; i < s.length(); i++)
val += s.charAt(i);
return val;
}

public String toString()
{
return s;
}
}

class test
{
public static void main(String[] args)
{
Set<StringContainer> set = new LinkedHashSet();
set.add(new StringContainer("Foo"));
set.add(new StringContainer("Bar"));
set.add(new StringContainer("Baz"));
set.add(new StringContainer("Qux"));


Iterator<StringContainer> it = set.iterator();
while (it.hasNext())
{
StringContainer s = it.next();
if (s.s == "Baz")
s.s = "Baz2";
System.out.println(s);
}

System.out.println("\nRe-iterate:\n");

it = set.iterator();
while (it.hasNext())
{
StringContainer s = it.next();
System.out.println(s);
}

System.out.println();

if (set.contains(new StringContainer("Foo")))
System.out.println("Contains Foo");

if (set.contains(new StringContainer("Baz")))
System.out.println("Contains Baz");
else
System.out.println("Does not contain Baz");

if (set.contains(new StringContainer("Baz2")))
System.out.println("Contains Baz2");
else
System.out.println("Does not contain Baz2");
}
}

它打印出以下内容:

Foo
Bar
Baz2
Qux

Re-iterate:

Foo
Bar
Baz2
Qux

Contains Foo
Does not contain Baz
Does not contain Baz2

有趣的是它知道 Baz 变了;但是它仍然没有找到 Baz2。

显然这是人为设计的,但我正在查看的非常合理的代码似乎(通过多个间接寻址)导致了这个问题。使用 Boost Multi Index 至少你必须 const-cast 一个迭代器来导致这个!

最佳答案

不建议在 Set 中使用可变对象(或作为 Map 中的键)。作为 Set 的 Javadoc说:

Note: Great care must be exercised if mutable objects are used as set elements. The behavior of a set is not specified if the value of an object is changed in a manner that affects equals comparisons while the object is an element in the set.

因此,您的示例直接切入点,并将您的 Set 置于“行为...未指定”区域。

根本原因正如 Paul Bellora 在他的回答中所说。

关于Java LinkedHashSet 索引有效性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10778970/

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