In most applications, we have three tiers of time durations.
Tier One: During an interaction/animation you must update the screen every 16ms. Code may not run longer than 16ms (less in practice).
Tier Two: You are not interacting, but may begin interacting with something at some unknown time. Code may not block the UI thread for longer than about 50ms so that there is a guarantee of not introducing perceivable delays into the interface.
Tier Three: Long running tasks which should be executed in parallel with the UI thread/process.
If going from O(1) to O(log(n)) still allows you to meet your deadlines for whichever latency tier you are targeting in whichever supported device classes you want to support, then it's worth it in order to program with better abstractions. Blocking for 1ms is as good as blocking for 13ms in Tier 1. Blocking for 25.5 is as good as blocking for 40ms in Tier 2. (This is helped by a decent event loop/task scheduler etc).
Again, all of this assumes you genuinely value immutability as a programming paradigm over mutability. If you'd really rather mutate, then you should just be using mutations/observables. I would not rather. Sometimes, I still perform mutations for the most critical parts of a UI abstraction (such as a scroller animation etc) - but I am up front about it being a compromise of what I'd rather do.