I disagree with this take. In both examples (the original article, as well as the one posted right above) the code under review was slow but simple.
Taking just the two from the comment right above this:
Double.parseDouble(foo.toString())
This will work for basically any possible value/type of foo, assuming foo supports .toString(). It will work for NaN, it will work for infinity, it will work if the value is
already a string.
It's explicitly avoiding the complexity of having to consider those cases at programming time, in exchange for taking the slow route (code someone else has written to already do that for you).
Simply casting to double will probably work, but not always - worse, the warnings you get, and the edge cases you might need to deal with will vary significantly across languages. Ex: Java will do different things than C++, which will do different things than C#, Python will vary by flavor (CPython and Jython use different underlying types).
Basically - it's saving the programmer a boat-load of complexity (reduces the edge cases down to just the exceptions parseDouble() might throw), in exchange for doing something slow.
---
Take the hashmap example right after the double example. Will a hashmap let you speed up some algorithms by avoiding n2 in favor of n? Sure - at the expense of memory size and longer initialization. In most places that's probably a sane call. Is it always the right call? Nope. Would not be ideal for my arduino - the memory is so limited n2 is unlikely to matter most times, and again - the memory is so limited I'd rather go slow and finish than try to go fast and segfault.
It's also not the right call when the expected length of the data is always going to be small values of n. If n is always going to be less than 5, I'd bet you good money the hash implementation will be slower in most cases.
----
Basically - optimize when optimizing becomes important, because something is slow and it sucks. Until then... slow is smooth and smooth is fast.