Java 8 streams presentation using https://github.com/gnab/remark
npm install
node make
grunt
go to localhost:8000
To change, edit boilerplate-local.html
.
Presentation below (in markdown):
- Introduction
- Internal/external iteration
- Lazy / eager
- map / filter / reduce
int count = 0;
for (Artist artist : allArtists) {
if (artist.isFrom("London")) {
count++;
}
}
--
Old way? Give me a break, what's wrong with it?
--
-
hard to understand what it does --
-
it does three things at once:
- it iterates over a colletion
- it applies some condition for each element
- it increments some previously created variable
Iterator<Artist> iterator = allArtists.iterator();
while(iterator.hasNext()) {
Artist artist = iterator.next();
if (artist.isFrom("London")) {
count++;
}
}```
--
<center><img src='image1.png' width="250" /></center>
--
<center>It mixes <strong>what</strong> you are doing with <strong>how</strong> you are doing it.</center>
---
# External iteration
```java
long count = allArtists.stream()
.filter(artist -> artist.isFrom("London"))
.count();```
--
<center><img src='image2.png' width="250" /></center>
--
- two operations:
* _filter_
* _count_
--
- but filtering is lazy
--
- _count_ is _eager_
---
# Lazy? Eager? What do you mean?
```java
List result = artists.stream()
.filter(artist -> artist.isFrom("London"))
.map(Artist::getName)
.map(String::toUpperCase)
.filter(name -> name.startsWith("a"))
.collect(Collectors.toList());```
--
### Lazy: _map_, _filter_
--
### Eager: _collect_
---
# Why won't just we use _forEach_?
### With side-effects:
```java
ArrayList<String> results = new ArrayList<>();
stream.filter(s -> pattern.matcher(s).matches())
.forEach(s -> results.add(s));```
--
### Without side-effects:
```java
List<String>results = stream.filter(s -> pattern.matcher(s).matches())
.collect(Collectors.toList());```
--
## <center>Not only it looks better but it is _thread-safe_ !</center>
---
# Eager methods:
- collect
- toArray
--
- reduce
- max
- min
- count
--
- allMatch
- anyMatch
- noneMatch
--
- findAny
- findFirst
---
# Lazy methods:
- filter
- map (mapToDouble, mapToInt, mapToLong)
- flatMap (flatMapToDouble, flatMapToInt, flatMapToLong)
--
- distinct
- limit
- sorted
--
- peek
- skip
---
# map
<center><img src='map.png' width="250" /></center>
```java
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
--
Stream<T> filter(Predicate<? super T> predicate);
--
Optional<T> reduce(BinaryOperator<T> accumulator);
T reduce(T identity, BinaryOperator<T> accumulator);
<U> U reduce(U identity,
BiFunction<U, ? super T, U> accumulator,
BinaryOperator<U> combiner);
--
https://github.com/RichardWarburton/java-8-lambdas-exercises
(defn my-map
"Implementation of `map` using `reduce`"
[f coll]
(reduce (fn [acc x] (conj acc (f x))) [] coll))
(deftest test-map
(is (= (map inc [1 2 3]) (my-map inc [1 2 3]))))
--
public static <I, O> List<O> map(Stream<I> stream, Function<I, O> mapper) {
return stream.reduce(new ArrayList<O>(), (acc, item) -> {
List<O> list = new ArrayList<>(acc);
list.add(mapper.apply(item));
return list;
}, (List<O> left, List<O> right) -> {
List<O> newLeft = new ArrayList<>(left);
newLeft.addAll(right);
return newLeft;
});
}
(defn my-filter
"Implementation of `filter` using `reduce`"
[f coll]
(reduce (fn [acc x] (if (f x) (conj acc x) acc)) [] coll))
(deftest test-filter
(is (= (filter odd? [1 2 3]) (test-filter odd? [1 2 3]))))
--
public static <I> List<I> filter(Stream<I> stream, Predicate<I> predicate) {
return stream.reduce(new ArrayList<I>(), (List<I> acc, I item) -> {
List<I> list = new ArrayList<>(acc);
if (predicate.test(item)) {
list.add(item);
}
return list;
}, (List<I> left, List<I> right) -> {
List<I> newLeft = new ArrayList<>(left);
newLeft.addAll(right);
return newLeft;
});
}