Iterator As a Design Pattern
break & limit of Imperative style coding
/* LIMIT */
int limit = 3;
int counter = 0;
while (counter < limit) {
counter++; // Increment the counter to limit the number of iterations.
}
/* BREAK */
for (int i = 0; i < 10; i++) {
if (i == 5) {
break; // This will exit the loop when i is 5.
}
}
limit
and takeWhile
are the functional equivalent of break
from the
imperative style.
List<Integer> numbers = Stream.iterate(1, n -> n + 1)
.takeWhile(n -> n <= 10) // Take elements while the condition is true (less than or equal to 10).
.limit(5) // Limit the stream to the first 5 elements.
.toList();
Shared Mutability
Impurity in Functional Programming : The given functional pipeline is not pure due to shared mutability.
The result may be unpredictable if we ever change this code to run in *
*parallel** by adding
.parallel()
or by changing .stream()
to .parallelStream()
var ret = new ArrayList<String>();
// Code behaves - erratically with parallel Stream
list.parallelStream()
.filter(Objects::nonNull)
.filter(name -> name.length() > 4)
.map(nameInLowerCase -> nameInLowerCase.toUpperCase())
.limit(count)
.forEach(name -> ret.add(name));//BAD IDEA with ParallelStream - due to shared mutability - this is impure
Change the above code to use collect(Collectors.toList())
to collect the list
var ret = list.parallelStream()
.filter(Objects::nonNull)
.filter(name -> name.length() > 4)
.map(nameInLowerCase -> nameInLowerCase.toUpperCase())
.limit(count)
.collect(Collectors.toList());
Also, we should not use impure functions in the intermediate stages
//Really frustrating to replicate and unpredictable
var result2 = new ArrayList<String>();
names.stream()
.filter(name -> name.length() == 4)
//.map(name -> performImpureOperation(name)) //AVOID + DANGEROUS
.map(String::toUpperCase)
//.forEach(name -> result2.add(name)); //BAD IDEA with ParallelStream
.collect(Collectors.toList()); //to List is a better option
Functional pipeline offers internal iterators
- is less complex
- easy to modify
- easy to understand
BUT
- Avoid shared mutable variables
- Ensure that we make the functional pipeline pure