1

i am making a lightweight event system, and i need a list of callbacks to be triggered for the event. My question is, since collections work with hashmaps and equality, how does this interact with lambdas, and how can i make sure that i can do list.remove() of the same lambda to remove it from the callbacks?

e.g

list.add(evt -> evt.toString()) list.remove(evt -> evt.toString())

Will these too always result in the same element removed?

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
dac1n
  • 309
  • 2
  • 11
  • 3
    You need to be _really_ careful. Stateless lambdas will be essentially singletons, and thus if you re-used that lambda (which would usually be pretty intentional: `Consumer listener = evt -> evt.toString()`), then they would be the same. However, separate lambdas as you've denoted may be separate instances, and would not pass an equality check here. It'd likely be better (and no less lightweight) to wrap these lambdas in a class like `RegisteredListener` or somesuch, which would provide a `#cancel` or `#remove` method to unregister the listener using the instance you provided. – Rogue Oct 05 '22 at 17:05
  • Have you tried actually running list.remove(lambda)? It throws errors for me. As for removal, lambda must inherit equals from object, so the way you try to do this it will be two different lambdas, hence you can't remove it. – Vitaly Chura Oct 05 '22 at 17:14
  • Alternately don't use lambdas. Make your own type `MyEventTask` and use concrete classes and class types to manage it manually. Personally I always prefer code that is least likely to give me an unpleasant surprise or be brittle and fail in the future. Not using lambdas might seem unsophisticated but there's a certain smartness to systems that work in obvious ways and are hard to break. – markspace Oct 05 '22 at 17:15
  • thank you all for the help, i think i will go with concrete classes to make the code clearer – dac1n Oct 05 '22 at 17:24
  • 1
    Actually, the difference to concrete classes is tiny. If you use `list.add(new Consumer() { public void accept(Event evt) { evt.toString(); } })` you have exactly the same issue. You have to remember the instance in a variable if you want to call `remove` later on. The difference is at the other side: two listeners implemented as lambda expressions doing the same *might* become the same instance in some environments. The solution is not to use sets. Normally, event sources allow adding the same listener multiple times. And usually the listener count to too low to benefit from hashing. – Holger Oct 06 '22 at 07:15

0 Answers0