更新集合中的对象

Yuv*_*val 16 java set data-structures

假设我的应用程序中有这种类型:

public class A {
  public int id;
  public B b;

  public boolean equals(Object another) { return this.id == ((A)another).id; }
  public int hashCode() { return 31 * id; //nice prime number }
}
Run Code Online (Sandbox Code Playgroud)

和一个结构.现在,我有一个类型的对象,并希望执行以下操作:Set<A>A

  • 如果我A在集合中,请更新其字段b以匹配我的对象.
  • 否则,将其添加到集合中.

所以检查它是否在那里很容易(contains),并且添加到集合也很容易.我的问题是:如何获得更新对象的句柄?接口Set没有get方法,我能想到的最好的方法是删除集合中的对象并添加我的对象.另一种,更糟糕的是,替代方法是使用迭代器遍历集合以尝试定位对象.

我很乐意接受更好的建议......这包括有效使用其他数据结构.

Yuval = 8-)

编辑:谢谢大家回答...不幸的是我不能'接受'这里的最佳答案,建议使用a Map,因为为此目的而根本改变集合的类型只会有点极端(这个集合是已经通过Hibernate映射...)

Pau*_*lin 17

由于Set只能包含一个对象实例(由equals和hashCode方法定义),因此只需将其删除然后添加即可.如果已经有一个,那么另一个将从Set中删除并替换为您想要的那个.

我有类似的代码 - 我正在缓存对象,以便在gui上的一堆不同的地方出现一个特定的对象,它总是相同的.在这种情况下,不是使用Set我使用Map,然后我得到更新,我从Map检索它并在适当的位置更新它而不是创建一个新实例.

  • 这不是'添加'所做的......如果集合包含一个相等的对象,'add'将返回false.见http://java.sun.com/javase/6/docs/api/java/util/Set.html#add(E) (2认同)

Jas*_*hen 11

你真的想用a Map<Integer,A>而不是a Set<A>.

然后将ID(即使它也存储在A!中)映射到对象.所以存储新是这样的:

A a = ...;
Map<Integer,A> map = new HashMap<Integer,A>();
map.put( a.id, a );
Run Code Online (Sandbox Code Playgroud)

您的完整更新算法是:

public static void update( Map<Integer,A> map, A obj ) {
  A existing = map.get( obj.id );
  if ( existing == null )
     map.put( obj.id, obj );
  else
     existing.b = obj.b;
}
Run Code Online (Sandbox Code Playgroud)

但是,它可能更简单. 我假设你的领域多于你所提供的领域A. 如果不是这种情况,只是使用a Map<Integer,B>实际上是你想要的,那么它就会崩溃为零:

Map<Integer,B> map = new HashMap<Integer,B>();
// The insert-or-update is just this:
map.put( id, b );
Run Code Online (Sandbox Code Playgroud)


18R*_*bit 6

如果您使用Set,我认为您不能比使用remove/add更容易.

    set.remove(a);
    set.add(a);
Run Code Online (Sandbox Code Playgroud)

如果找到匹配的A,它将被删除,然后你添加新的,你甚至不需要if (set.contains(A))条件.

如果您有一个具有ID和更新字段的对象,并且您并不真正关心该对象的任何其他方面,请将其抛出并替换它.

如果你需要对匹配该ID的A做任何其他事情,那么你将不得不遍历Set以找到它或使用不同的Container(如Jason建议的Map).


Kev*_*Day 5

还没有人提到这一点,但是基于hashCodeequals基于可变属性是您不应该做的非常非常重要的事情之一。离开构造函数后,不要考虑对象标识 - 这样做会大大增加您遇到真正难以解决的错误的机会。即使您没有遇到错误,确保您始终正确更新依赖equalshashCode保持一致的任何和所有数据结构的会计工作将远远超过能够仅更改对象 id 的任何感知好处当你跑步时。

相反,我强烈建议您通过构造函数传入 id,如果您需要更改它,请创建 A 的新实例。这将强制您的对象的用户(包括您自己)与集合类(以及许多其他)依赖于equals和 中的不可变行为hashCode