In a lot of ways, I think the map solution is actually worse. There isn't an easy way to figure out what code is used for a given enum value with the map alone. The searchability depends on how the map is initialized. Not to mention a map will always introduce null or option types that you have to handle.
A map can be a good solution though, particularly if it's something like mapping enum values to strings that is constructed via EnumClass.values().map... or something so that you know the map is a total function.
Using a map also completely sidesteps the point of cyclomatic complexity because there are no code paths to count anymore; now they're data. And even though the function does the same as before, the linter will congratulate you on the reduced complexity.
And you'd have essentially replaced statically understood control flow with the equivalent of a computed goto. It's not like it's a bad approach, but from a code path standpoint, it's unequivocally worse, not better. (Imagine if that map was mutable!)
> Not to mention a map will always introduce null or option types that you have to handle.
It is the same with the switch, at least in C/C++. You either have a default, or must list all the possible cases and still return something "at the bottom".
A map can be a good solution though, particularly if it's something like mapping enum values to strings that is constructed via EnumClass.values().map... or something so that you know the map is a total function.