开发者

Java List with Objects - find and replace (delete) entry if Object with certain attribute already exists

I've been working all day and I somehow can't get this probably easy task figured out - probably a lack of coffee...

I have a synchronizedList where some Objects are being stored. Those objects have a field which is something like an ID. These objects carry information about a user and his current state (simplified).

The point is, that I only want one object for each user. So when the state of this user changes, I'd like to remove the "old" entry and store a new one in the List.

protected static class Objects{
    ...
    long time;
    Object ID;
    ... 
    }

...

if (Objects.contains(ID)) {
            Objects.remove(ID);
            Objects.add(newObject);
        } else {
            Objects.add(newObject);
        }

Obviously this is not the way to go but should illustrate what I'm looking for...

Maybe the data structure is not the best for this purpose but any help is welcome!


EDIT:

Added some information...

A Set does not really seem to fit my purpose. The Objects store some other fields besides the ID which change all the time. The purpose is, that the list will somehow represent the latest activities of a user. I only need to track the last state and only keep that object whi开发者_StackOverflow中文版ch describes this situation.

I think I will try out re-arranging my code with a Map and see if that works...


You could use a HashMap (or LinkedHashMap/TreeMap if order is important) with a key of ID and a value of Objects. With generics that would be HashMap<Object, Objects>();

Then you can use

if (map.containsKey(ID)) {
    map.remove(ID);
}

map.put(newID, newObject);

Alternatively, you could continue to use a List, but we can't just modify the collection while iterating, so instead we can use an iterator to remove the existing item, and then add the new item outside the loop (now that you're sure the old item is gone):

List<Objects> syncList = ...

for (Iterator<Objects> iterator = syncList.iterator(); iterator.hasNext();) {
    Objects current = iterator.next();

    if (current.getID().equals(ID)) {
        iterator.remove();
    }
}

syncList.add(newObject);


And you can't use a Set to have only the first one stored ?

because it basically is precisely what you require.


You could use a HashSet to store the objects and then override the hashCode method in the class that the HashSet will contain to return the hashcode of your identifying field.


A Map is easiest, but a Set reflects your logic better. In that case I'd advice a Set.

There are 2 ways to use a set, depending on the equals and hashCode of your data object.

If YourObject already uses the ID object to determine equals (and hashCode obeys the contract) you can use any Set you want, a HashSet is probably best then.

If YourObjects business logic requires a different equals, taking into account multiple fields beside the ID field, then a custom comparator should be used. A TreeSet is a Set which can use such a Comparator.

An example:

Comparator<MyObject> comp = new Comparator<MyObject>{
  public int compare(MyObject o1, MyObject o2) {
    // NOTE this compare is not very good as it obeys the contract but
    // is not consistent with equals. compare() == 0 -> equals() != true here
    // Better to use some more fields
    return o1.getId().hashCode() < o2.getId().hashCode();
  }
  public boolean equals(Object other) {
    return 01.getId().equals(o2.getId());
  }
}

Set<MyObject> myObjects = new TreeSet(comp);

EDIT I have updated the code above to reflect that id is not an int, as suggested by the question.


My first option would be a HashSet, this would require that you override the hashCode and equals methods (don't forget: if you override one, override consistently the other !) so that objects with the same ID field are considered equal.

But this might break something if this assumption is NOT to be made in other parts of your application. In that case you might opt for using a HashMap (with the ID as key) or implement your own MyHashSet class (backed by such a HashMap).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜