Skip to main content
better syntax highlighting | incorporated one of the links | added markdown highlighting to the graph
Source Link

The Java team has done a ton of great work removing barriers to functional programming in Java 8. In particular, the changes to the java.utiljava.util Collections do a great job of chaining transformations into very fast streamed operations. Considering how good a job they have done adding first class functions and functional methods on collections, why have they completely failed to provide immutable collections or even immutable collection interfaces?

Without changing any existing code, the Java team could at any time add immutable interfaces that are the same as the mutable ones, minus the "set"setter methods and make the existing interfaces extend from them, like this:

 ImmutableIterable ____________/ | / | Iterable ImmutableCollection | _______/ / \ \___________ | / / \ \ Collection ImmutableList ImmutableSet ImmutableMap ... \ \ \_________|______________|__________ | \ \___________|____________ | \ | \___________ | \ | \ | List Set Map ... 
 ImmutableIterable ____________/ | / | Iterable ImmutableCollection | _______/ / \ \___________ | / / \ \ Collection ImmutableList ImmutableSet ImmutableMap ... \ \ \_________|______________|__________ | \ \___________|____________ | \ | \___________ | \ | \ | List Set Map ... 

Sure, operations like List.add()List.add() and Map.put()Map.put() currently return a boolean or previous value for the given key to indicate whether the operation succeeded or failed. Immutable collections would have to treat such methods as factories and return a new collection containing the added element - which is incompatible with the current signature. But that could be worked-around by using a different method name like ImmutableList.append()ImmutableList.append() or .addAt().addAt() and ImmutableMap.putEntry()ImmutableMap.putEntry(). The resulting verbosity would be more than outweighed by the benefits of working with immutable collections, and the type system would prevent errors of calling the wrong method. Over time, the old methods could be deprecated.

  • Simplicity - reasoning about code is simpler when the underlying data does not change.
  • Documentation - if a method takes an immutable collection interface, you know it isn't going to modify that collection. If a method returns an immutable collection, you know you can't modify it.
  • Concurrency - immutable collections can be shared safely across threads.

As someone who has tasted languages which assume immutability, it is very hard to go back to the Wild West of rampant mutation. Clojure's collections (sequence abstraction) already have everything that Java 8 collections provide, plus immutability (though maybe using extra memory and time due to synchronized linked-lists instead of streams). Scala Scala has both mutable and immutable collections with a full set of operations, and though those operations are eager, calling .iterator.iterator gives a lazy view (and there are other ways of lazily evaluating them). I don't see how Java can continue to compete without immutable collections.

Can someone point me to the history or discussion about this? SurelySurely it's public somewhere.

The Java team has done a ton of great work removing barriers to functional programming in Java 8. In particular, the changes to the java.util Collections do a great job of chaining transformations into very fast streamed operations. Considering how good a job they have done adding first class functions and functional methods on collections, why have they completely failed to provide immutable collections or even immutable collection interfaces?

Without changing any existing code, the Java team could at any time add immutable interfaces that are the same as the mutable ones, minus the "set" methods and make the existing interfaces extend from them, like this:

 ImmutableIterable ____________/ | / | Iterable ImmutableCollection | _______/ / \ \___________ | / / \ \ Collection ImmutableList ImmutableSet ImmutableMap ... \ \ \_________|______________|__________ | \ \___________|____________ | \ | \___________ | \ | \ | List Set Map ... 

Sure, operations like List.add() and Map.put() currently return a boolean or previous value for the given key to indicate whether the operation succeeded or failed. Immutable collections would have to treat such methods as factories and return a new collection containing the added element - which is incompatible with the current signature. But that could be worked-around by using a different method name like ImmutableList.append() or .addAt() and ImmutableMap.putEntry(). The resulting verbosity would be more than outweighed by the benefits of working with immutable collections, and the type system would prevent errors of calling the wrong method. Over time, the old methods could be deprecated.

  • Simplicity - reasoning about code is simpler when the underlying data does not change.
  • Documentation - if a method takes an immutable collection interface, you know it isn't going to modify that collection. If a method returns an immutable collection, you know you can't modify it.
  • Concurrency - immutable collections can be shared safely across threads.

As someone who has tasted languages which assume immutability, it is very hard to go back to the Wild West of rampant mutation. Clojure's collections (sequence abstraction) already have everything that Java 8 collections provide, plus immutability (though maybe using extra memory and time due to synchronized linked-lists instead of streams). Scala has both mutable and immutable collections with a full set of operations, and though those operations are eager, calling .iterator gives a lazy view (and there are other ways of lazily evaluating them). I don't see how Java can continue to compete without immutable collections.

Can someone point me to the history or discussion about this? Surely it's public somewhere.

The Java team has done a ton of great work removing barriers to functional programming in Java 8. In particular, the changes to the java.util Collections do a great job of chaining transformations into very fast streamed operations. Considering how good a job they have done adding first class functions and functional methods on collections, why have they completely failed to provide immutable collections or even immutable collection interfaces?

Without changing any existing code, the Java team could at any time add immutable interfaces that are the same as the mutable ones, minus the setter methods and make the existing interfaces extend from them, like this:

 ImmutableIterable ____________/ | / | Iterable ImmutableCollection | _______/ / \ \___________ | / / \ \ Collection ImmutableList ImmutableSet ImmutableMap ... \ \ \_________|______________|__________ | \ \___________|____________ | \ | \___________ | \ | \ | List Set Map ... 

Sure, operations like List.add() and Map.put() currently return a boolean or previous value for the given key to indicate whether the operation succeeded or failed. Immutable collections would have to treat such methods as factories and return a new collection containing the added element - which is incompatible with the current signature. But that could be worked-around by using a different method name like ImmutableList.append() or .addAt() and ImmutableMap.putEntry(). The resulting verbosity would be more than outweighed by the benefits of working with immutable collections, and the type system would prevent errors of calling the wrong method. Over time, the old methods could be deprecated.

  • Simplicity reasoning about code is simpler when the underlying data does not change.
  • Documentation if a method takes an immutable collection interface, you know it isn't going to modify that collection. If a method returns an immutable collection, you know you can't modify it.
  • Concurrency immutable collections can be shared safely across threads.

As someone who has tasted languages which assume immutability, it is very hard to go back to the Wild West of rampant mutation. Clojure's collections (sequence abstraction) already have everything that Java 8 collections provide, plus immutability (though maybe using extra memory and time due to synchronized linked-lists instead of streams). Scala has both mutable and immutable collections with a full set of operations, and though those operations are eager, calling .iterator gives a lazy view (and there are other ways of lazily evaluating them). I don't see how Java can continue to compete without immutable collections.

Can someone point me to the history or discussion about this? Surely it's public somewhere.

Question Protected by gnat
deleted 15 characters in body
Source Link
GlenPeterson
  • 15k
  • 7
  • 50
  • 75
  Enumerable (already immutable)ImmutableIterable __________________________/  | / | Iterable ImmutableCollection | _______/ / \ \___________ | / / \ \ Collection ImmutableList ImmutableSet ImmutableMap ... \ \ \_________|______________|__________ | \ \___________|____________ | \ | \___________ | \ | \ | List Set Map ... 
  Enumerable (already immutable) ______________/ | / | Iterable ImmutableCollection | _______/ / \ \___________ | / / \ \ Collection ImmutableList ImmutableSet ImmutableMap ... \ \ \_________|______________|__________ | \ \___________|____________ | \ | \___________ | \ | \ | List Set Map ... 
 ImmutableIterable ____________/  | / | Iterable ImmutableCollection | _______/ / \ \___________ | / / \ \ Collection ImmutableList ImmutableSet ImmutableMap ... \ \ \_________|______________|__________ | \ \___________|____________ | \ | \___________ | \ | \ | List Set Map ... 
added 112 characters in body
Source Link
GlenPeterson
  • 15k
  • 7
  • 50
  • 75
  IterableEnumerable (already immutable) ______________/ |  / |   | Iterable ImmutableCollection   | _______/ / \ \___________   | / / \ \ Collection ImmutableList ImmutableSet ImmutableMap ... \ \ \_________|______________|__________ | \ \___________|____________ | \ | \___________ | \ | \ | List Set Map ... 
  • Simplicity - reasoning about code is simpler when the underlying data does not change.
  • Documentation - if a method takes an immutable collection interface, you know it isn't going to modify that collection. If a method returns an immutable collection, you know you can't modify it.
  • Concurrency - immutable collections can be shared safely across threads.
  Iterable (already immutable) |  ImmutableCollection   _______/ / \ \___________   / / \ \ Collection ImmutableList ImmutableSet ImmutableMap ... \ \ \_________|______________|__________ | \ \___________|____________ | \ | \___________ | \ | \ | List Set Map ... 
  • Simplicity - reasoning about code is simpler when the underlying data does not change
  • Documentation - if a method takes an immutable collection interface, you know it isn't going to modify that collection
  • Concurrency - immutable collections can be shared safely across threads
 Enumerable (already immutable) ______________/ |  /   | Iterable ImmutableCollection | _______/ / \ \___________ | / / \ \ Collection ImmutableList ImmutableSet ImmutableMap ... \ \ \_________|______________|__________ | \ \___________|____________ | \ | \___________ | \ | \ | List Set Map ... 
  • Simplicity - reasoning about code is simpler when the underlying data does not change.
  • Documentation - if a method takes an immutable collection interface, you know it isn't going to modify that collection. If a method returns an immutable collection, you know you can't modify it.
  • Concurrency - immutable collections can be shared safely across threads.
Notice removed Reward existing answer by gnat
Bounty Ended with daniel gratzer's answer chosen by gnat
Notice added Reward existing answer by gnat
Bounty Started worth 50 reputation by gnat
Tweeted twitter.com/#!/StackProgrammer/status/413664540837302272
It looked like I asked about Java providing only immutable collections, when really I meant to ask about ADDING immutable collections to the existing API (leaving the mutable ones alone) so I rephrased to clarify.
Source Link
GlenPeterson
  • 15k
  • 7
  • 50
  • 75
Loading
added 1 characters in body
Source Link
GlenPeterson
  • 15k
  • 7
  • 50
  • 75
Loading
Incorporated Karl's insights about Scala laziness.
Source Link
GlenPeterson
  • 15k
  • 7
  • 50
  • 75
Loading
deleted 34 characters in body
Source Link
GlenPeterson
  • 15k
  • 7
  • 50
  • 75
Loading
Source Link
GlenPeterson
  • 15k
  • 7
  • 50
  • 75
Loading