It seems to be easy to do, just can't understand how.
I want to replace an object contained in a Set of objects. What's the way of doing this?
I think that your understanding of how objects are stored in a Set might not be completely accurate.
The Set itself only holds references to objects. If you remove that reference and the object is not referenced anywhere else, the garbage collector will drop that object and remove it from memory.
You cannot "replace" an object because the Set only holds a reference to your object.
The only way you can remove one object and insert another is the following:
set.remove(object);
set.add(anotherObject);
There appears to be no way in a Set to replace a reference to an object with a reference to a different object. Using the two operations of remove() followed by add() should suffice for most purposes, however doing so requires the object hash and lookup to occur twice instead of once.
The scenario in which Set replacement is potentially useful is when it involves a type for which differing objects may be considered equal (as given by its implementation of operator== and hashCode). In other words, the situation of interest is likely not
set.remove(object);
set.add(anotherObject);
but is rather
set.remove(anotherObject);
set.add(anotherObject);
where the set may contain an existing reference to a different object object such that anotherObject == object is true.
If replacement is somehow important, use of a Map with identical keys and values can be considered in place of a Set, since Maps do allow replacement. for example:
final map = <Object, Object>{};
final object = Object();
map[object] = object;
Additionally, it may also be worth mentioning that this is possible to achieve using a Set and introducing a layer of indirection:
class Indirect<T> {
T value;
Indirect(this.value);
@override
bool operator==(Object other) => value == other;
@override
int get hashCode => value.hashCode;
}
void main() {
final aset = <Indirect<Object>>{};
final object = Object();
final indirect = aset.lookup(object) ?? Indirect(object);
aset.add(indirect);
indirect.value = object;
}
This works because once added to the set, the Indirect never needs to be replaced--instead, the Indirect's value is simply overwritten as needed. And, crucially, an Indirect has the same hash and equality as the value it represents. However, in practice, there isn't a compelling motivation to use this approach, as it offers no advantages (still two hashes and lookups), yet introduces unnecessary complexity.
Either way, be cautious of premature optimization.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With