Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replace an object in a Set

Tags:

flutter

dart

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?

like image 687
Zhangir Siranov Avatar asked Mar 16 '26 19:03

Zhangir Siranov


2 Answers

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);
like image 178
creativecreatorormaybenot Avatar answered Mar 19 '26 14:03

creativecreatorormaybenot


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.

like image 23
Chuck Batson Avatar answered Mar 19 '26 16:03

Chuck Batson



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!