There's no direct correlation between immutability and efficiency.
An immutable data structure can be efficient or largely inefficient when it comes to transforming from one collection of values to another. In Clojure, efficiency comes from the use of Tries and other highly efficient data structures.
In Java 8, efficiency comes from streams. That's one of the reason for the separation of stream and collect. Streams perform lazy evaluations and also tactfully postpone the creation of the target data structure.
If efficiency is the main concern, it would be good to run some benchmarks to measure the performance and then come to conclusion if one is better than the other.
The lack of immutable data structure is a concern, however, not from the point of view of efficiency, but from the point of view of errors that may arise due to inappropriate shared mutability. The anti-pattern of trying to update a data structure from within lambdas is something programmers are going to do and then learn to avoid.
The second parameter says after performing the grouping, instead of collecting the pairs for each group, instead collect the (in this example, the second) specific value from within the pair. Without the mapping, we will get a Map<Integer, List<Pair>> instead of Map<Integer, List<Integer>>.
This is certainly a concern if we create a divide in team where some people stays stagnant and others learn and move forward.
Given that almost all mainstream languages now support functional style, it is to great disadvantage to developers if they do not
become familiar with the style. It will largely limit there ability to program effectively in just about any language moving forward.
Over time, as we all get more familiar with the style, we will transition. In my observation, most programmers are fairly good at such
transition, when a language evolves. C# has gone through exactly this cycle, only a few years ahead.
Java will never be or become a true functional programming language. The imperative style and mutability is far too engrained in it.
It certainly has another style to program and the onus is on us to use that style judiciously in ways we can gain.
Several languages have done this. Smalltalk, Ruby, Scala,... there is a long list of languages that support both imperative and functional style.
I like having that flexibility and the wisdom to choose.
One of the tenets of FP is immutability. We do not mutate and especially mutate shared state. If we mutate state and cause side effects,
it will mess up several things that are possible in FP - referential transparency, lazy evaluations, potential concurrency and re-orderings.
Please see the link below:
"We should use extra caution not to mix mutability, shared state, and functional style.-->Can you just give me a rough example on this statement "
If the goal is to transform one list to another, then do the transformation first, using map, keeping the transformatio operation pure. Then convert the
abstraction of stream to a concrete collection, like list.
David, no in this book I focus only on Java 8. I've written books on Scala and Groovy, and also use quite a few other languages on the JVM on a regular basis. I do not see a reason to compare with one and not the other languages in a book like this. My objective for writing this book is to help Java programmers get up to speed on this newer facilities and so have kept it topics spot on that.
We can use it for just about anything. Imperative and functional are two different styles of programming the same things. With functional style, and the set of nice libraries, we can start to decompose the problem into a series of function composition and transformations. When we mix this with concepts and functions like lazy evaluation, pure functions, and parallel streams, we can implement a certain set of concurrency solutions, for example, a lot more effectively than we do with imperative style and shared mutability.