Java List with Objects - find and replace (delete) entry if Object with certain attribute already exists
Solution 1
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.
Solution 2
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);
Solution 3
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.
Solution 4
And you can't use a Set to have only the first one stored ?
because it basically is precisely what you require.
![Gnark](https://i.stack.imgur.com/CBPTi.gif?s=256&g=1)
Gnark
Updated on September 04, 2022Comments
-
Gnark almost 2 years
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 afield
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...
ASet
does not really seem to fit my purpose. TheObjects
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 which describes this situation.
I think I will try out re-arranging my code with aMap
and see if that works...-
extraneon over 14 yearsYes, the Set's add method is a problem in your case. Good luck with the Map!
-
Gnark over 14 yearsthanks, it worked like a charm - the "pseudo-iteration" over a HashMap is a little iffy but works as well :-)
-
-
Dan over 14 yearsIf an instance of Objects has other properties (besides ID), then he does not need the first one stored, but the latest one with the same ID value.
-
extraneon over 14 yearsIf you really need a Set then a TreeSet with comparator can also be used, and might better fit the model.
-
Steve Kuo over 14 yearsWhy does compare using the object's hash code? This is just wrong.