Design for collections upgrades
peter.levart at marand.si
Mon Mar 14 01:07:52 PDT 2011
On 03/10/11, Rémi Forax wrote:
> Le 10/03/2011 13:10, Peter Levart a écrit :
> > Let Iterable by default (via defender methods) be lazy but let Collection (also via defender methods) override the same methods an make them eager. Also privide two methods to switch between eager and lazy on the Iterable itself (and override in Collection and subtypes).
> If Collection.filter overrides Iterable.filter, they should have the
> same semantics.
> And as I already say, how to implement toEager() ?
Now after more discussion on the list, I'm not supporting my suggestion any further. But I'm not keen on a new "Stream" type either. The original fear that lazy evaluation of filtering/mapping/reducing/etc... operations on collections would feel unnatural to casual programmer, because collections library is currently not using any form of lazy evaluation is, I think, at least partialy unfounded.
Lazy evaluation of operations on collection can be described as having two subtle semantic properties:
1. The evaluation of predicates, mappers, reducers, etc. happens at the latest possible moment, when the resulting data is requested (iterated over, collected into a propper collection, etc...)
2. The original data that is the source for the operations is stored in the source collection (the resulting Iterable is not detatched from original data - it is a transformed view over source collection). So modifying source collection before or in the middle of iteration over the result has a consequence on the result.
The 2nd property is already known to users of collections library (Map.keySet(), Map.values(), ...) and therefore, if propperly documented, can not present any additional confusion.
The 1st property is something new that everyone will have to learn since more and more APIs can be expected to exhibit this behaviour after lambdas are introduced to Java. Programmers will have to learn about pure functions and why they are their friends...
I'm now a supporter of lazy java.lang.Iterable (and by inheritance also java.util.Collection). Overall it represents simpler and more consistent API with no need for additional Stream type. It does not exhibit problems that eager evaluation does:
- what should the eager result type be and what implementation should be choosen (ArrayList/HashSet/TreeSet)
- inherent sub-optimabillity (think of how easy it is to write: s = s + "xxx"; s = s + "..."; ...instead of using StringBuilder)
More information about the lambda-dev