gpt4 book ai didi

java - LinkedHashSet 文档歧义 : Re-insert

转载 作者:行者123 更新时间:2023-12-02 05:50:30 27 4
gpt4 key购买 nike

LinkedHashSet 的 java 文档声明如下:

请注意,如果将元素重新插入集合中,插入顺序不会受到影响。 (如果在调用之前 s.contains(e) 返回 true 时调用 s.add(e),则元素 e 会重新插入到集合 s 中。)

对于最近的一个项目,我决定使用一个在客户端-服务器通信中保存一组数据 token ,以便在某些 ListView 小部件中向用户显示。我的想法是,我能够以廉价的方式重新插入具有更新数据的元素,并且用户不会感到惊讶,因为顺序不会改变。

显然情况并非如此,使用 Oracle JRE 1.7.0_55-b13 时,它的运行方式与任何其他 Set 一样。 ,正如这个简短的测试程序所示:

import java.util.LinkedHashSet;

import static java.util.Arrays.deepToString;

public class LhsStack
{
public static class T
{
public T ( int id ) { this.id = id; }

public final Integer id;
public String value;

@Override
public int hashCode () { return id.hashCode (); }

@Override
public boolean equals ( Object obj )
{
return obj instanceof T && id.equals ( ((T)obj).id );
}

@Override
public String toString () { return id + " => " + value; }
}

public static void main ( String [] args )
{
LinkedHashSet < T > set = new LinkedHashSet <> ();

T a = new T ( 1 ),
b = new T ( 1 ),
c = new T ( 2 ),
d = new T ( 3 );

a.value = "Hello, World";
b.value = "World, Hello";
c.value = "Foo";
d.value = "Bar";

System.out.println ( "a == b: " + a.equals ( b ) );

if ( set.add ( a ) ) {
System.out.println ( "Inserted: " + a.value );
}

System.out.println ( "set.contains ( a ): " + set.contains ( a ) );
System.out.println ( "set.contains ( b ): " + set.contains ( b ) );

set.add ( c ); set.add ( d );

System.out.println ( "Elements: " + set.size () );
System.out.println ( deepToString ( set.toArray () ) );

if ( set.add ( b ) ) {
System.out.println ( "Re-Inserted: " + b.value );
}
else
{
System.out.println ( "Removing and Adding: " + b.value );
set.remove ( b );
set.add ( b );
}

System.out.println ( "Elements: " + set.size () );
System.out.println ( deepToString ( set.toArray () ) );
}
}

输出

a == b: true
Inserted: Hello, World
set.contains ( a ): true
set.contains ( b ): true
Elements: 3
[1 => Hello, World, 2 => Foo, 3 => Bar]
Removing and Adding: World, Hello
Elements: 3
[2 => Foo, 3 => Bar, 1 => World, Hello]

因此,我的问题是,由于元素 b 没有重新插入到集合中(即必须将其删除,然后重新添加以更新其值),那么该元素的意义是什么java 文档中的注释?

谢谢!

最佳答案

通常,linkedHashSet.add(elementToAdd)使elementToAddlinkedHashSet 的最后一个元素。 Javadoc中注释的意义在于,如果elementToAdd已经出现在 linkedHashSet 内,然后linkedHashSet.add(elementToAdd)只会将其保留在原处(并且不会将其移动到末尾)。

对于您想要做的事情,最好使用 LinkedHashMap<Integer, T> 。然后您可以迭代其 values()获取您的T按迭代顺序排列的实例,具有更新映射的能力。 (如果需要,您可以将 LinkedHashMap<Integer, T> 包装在某种容器对象中,该对象不是提供 put(Integer, T) ,而是提供一个 add(T) 来处理幕后的键映射。事实上,它应该非常可以直接扩展 AbstractSet<T> 以创建 LinkedHashMap<Integer, T> 的基于 Set<T> 的实现。)

<小时/>

编辑更新的问题:啊,好吧,抱歉,我现在更好地理解您的困惑了。上面是对第一句的目的的解释(“注意,如果元素重新插入到集合中,插入顺序不会受到影响”);我没有意识到您误解了第二句话(“如果 e 被调用,而 s 将在调用之前立即返回 s.add(e),则元素 s.contains(e) 被重新插入到集合 true 中。”)

所以,让我解释一下。第二句话只是术语“重新插入”的定义;它没有描述任何行为。这句话并不是说一个LinkedHashSet如果您调用它 add ,则会执行称为“重新插入”的操作方法及其已包含的元素;相反,这句话说如果你调用它 add方法中已包含元素,则此调用称为“重新插入”。重新插入的(非)效果如第一句中所述,即它不会将元素移动到末尾。

LinkedHashSet.add仍然遵守Set.add的要求,它指定“如果指定元素尚不存在,则将其添加到此集合(可选操作)。[...]如果此集合已包含该元素,则调用将保持集合不变并返回 false 。”

在某些情况下,JDK 类不遵守它们声称要实现的接口(interface)的要求,但当发生这种情况时,它将以粗体警告的形式发出,而不仅仅是隐藏在括号内并且从未提及再次。请参阅the Javadoc of IdentityHashMap 举个例子。

关于java - LinkedHashSet 文档歧义 : Re-insert,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23576401/

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