(inta) -> a * 2; // Calculate the double of aa -> a * 2; // or simply without type(a, b) -> a + b; // Sum of 2 parametersIf the lambda is more than one expression we can use { } and return
(x, y) -> {
intsum = x + y;
intavg = sum / 2;
returnavg;
}A lambda expression cannot stand alone in Java, it need to be associated to a functional interface.
interfaceMyMath {
intgetDoubleOf(inta);
}
MyMathd = a -> a * 2; // associated to the interfaced.getDoubleOf(4); // is 8All examples with "list" use :
List<String> list = [Bohr, Darwin, Galilei, Tesla, Einstein, Newton]sortsort(list, comparator)
list.sort((a, b) -> a.length() - b.length())
list.sort(Comparator.comparing(n -> n.length())); // samelist.sort(Comparator.comparing(String::length)); // same//> [Bohr, Tesla, Darwin, Newton, Galilei, Einstein]removeIf
list.removeIf(w -> w.length() < 6);
//> [Darwin, Galilei, Einstein, Newton]mergemerge(key, value, remappingFunction)
Map<String, String> names = newHashMap<>();
names.put("Albert", "Ein?");
names.put("Marie", "Curie");
names.put("Max", "Plank");
// Value "Albert" exists// {Marie=Curie, Max=Plank, Albert=Einstein}names.merge("Albert", "stein", (old, val) -> old.substring(0, 3) + val);
// Value "Newname" don't exists// {Marie=Curie, Newname=stein, Max=Plank, Albert=Einstein}names.merge("Newname", "stein", (old, val) -> old.substring(0, 3) + val);Allows to reference methods (and constructors) without executing them
// Lambda Form:getPrimes(numbers, a -> StaticMethod.isPrime(a));
// Method Reference:getPrimes(numbers, StaticMethod::isPrime);| Method Reference | Lambda Form |
|---|---|
StaticMethod::isPrime | n -> StaticMethod.isPrime(n) |
String::toUpperCase | (String w) -> w.toUpperCase() |
String::compareTo | (String s, String t) -> s.compareTo(t) |
System.out::println | x -> System.out.println(x) |
Double::new | n -> new Double(n) |
String[]::new | (int n) -> new String[n] |
Similar to collections, but
- They don't store their own data
- The data comes from elsewhere (collection, file, db, web, ...)
- immutable (produce new streams)
- lazy (only computes what is necessary !)
// Will compute just 3 "filter"Stream<String> longNames = list
.filter(n -> n.length() > 8)
.limit(3);Create a new stream
Stream<Integer> stream = Stream.of(1, 2, 3, 5, 7, 11);
Stream<String> stream = Stream.of("Jazz", "Blues", "Rock");
Stream<String> stream = Stream.of(myArray); // or from an arrayStream<String> stream = list.stream(); // or from a list// Infinit stream [0; inf[Stream<Integer> integers = Stream.iterate(0, n -> n + 1);Collecting results
// Collect into an array (::new is the constructor reference)String[] myArray = stream.toArray(String[]::new);
// Collect into a List or SetList<String> myList = stream.collect(Collectors.toList());
Set<String> mySet = stream.collect(Collectors.toSet());
// Collect into a StringStringstr = list.collect(Collectors.joining(", "));mapmap(mapper)
Applying a function to each element
// Apply "toLowerCase" for each elementStream<String> res = stream.map(w -> w.toLowerCase());
Stream<String> res = stream.map(String::toLowerCase);
//> bohr darwin galilei tesla einstein newtonStream<Integer> res = Stream.of(1, 2, 3, 4, 5).map(x -> x + 1);
//> 2 3 4 5 6filterfilter(predicate)
Retains elements that match the predicate
// Filter elements that begin with "E"res = stream.filter(n -> n.substring(0, 1).equals("E"));
//> Einsteinres = Stream.of(1, 2, 3, 4, 5).filter(x -> x < 3);
//> 1 2reduce
Reduce the elements to a single value
Stringreduced = stream.reduce("", (acc, el) -> acc + "|" + el);
//> |Bohr|Darwin|Galilei|Tesla|Einstein|Newtonlimitlimit(maxSize)
Select the n first elements
res = stream.limit(3);
//> Bohr Darwin Galileiskip
Discarding the first n elements
res = stream.skip(2); // skip Bohr and Darwin//> Galilei Tesla Einstein Newtondistinct
Remove duplicated elemetns
res = Stream.of(1, 0, 0, 1, 0, 1).distinct();
//> 1 0sorted
Sort elements (must be Comparable)
res = stream.sorted();
//> Bohr Darwin Einstein Galilei Newton Tesla allMatch / noneMatch
// Check if there is a "e" in each elementsbooleanres = words.allMatch(n -> n.contains("e"));anyMatch: Check if there is a "e" in an element
noneMatch: Check if there is no "e" in elements
parallel
Returns an equivalent stream that is parallel
findAny
faster than findFirst on parallel streams
Wrappers (like Stream) are inefficients. It requires a lot of unboxing and boxing for each element. Better to use IntStream, DoubleStream, etc.
Creation
IntStreamstream = IntStream.of(1, 2, 3, 5, 7);
stream = IntStream.of(myArray); // from an arraystream = IntStream.range(5, 80); // range from 5 to 80Randomgen = newRandom();
IntStreamrand = gen(1, 9); // stream of randomsUse mapToX (mapToObj, mapToDouble, etc.) if the function yields Object, double, etc. values.
Collectors.groupingBy
// Groupe by lengthMap<Integer, List<String>> groups = stream.collect(Collectors.groupingBy(w -> w.length()));
//> {4=[Bohr], 5=[Tesla], 6=[Darwin, Newton], 7=[Galilei], 8=[Einstein]}Collectors.toSet
// Same as before but with SetMap<String, Set<String>> groups2 = stream.collect(Collectors.groupingBy(w -> w.substring(0, 1), Collectors.toSet()));
//> {B=[Bohr], T=[Tesla], D=[Darwin], E=[Einstein], G=[Galilei], N=[Newton]}Collectors.counting
Count the number of values in a group
Collectors.summing__summingInt, summingLong, summingDouble to sum group values
Collectors.averaging__averagingInt, averagingLong, ... to average group values
// Average length of each element of a groupCollectors.averagingInt(String::length)PS: Don't forget Optional (like Map<T, Optional<T>>) with some Collection methods (like Collectors.maxBy).
Creation
Stream<String> parStream = list.parallelStream();
Stream<String> parStream = Stream.of(myArray).parallel();unordered
Can speed up the limit or distinct
stream.parallelStream().unordered().distinct();PS: Work with the streams library. Eg. use filter(x -> x.length() < 9) instead of a forEach with an if.
In Java, it is common to use null to denote absence of result.
Problems when no checks: NullPointerException.
// Optional<String> contains a string or nothingOptional<String> res = stream
.filter(w -> w.length() > 10)
.findFirst();
// length of the value or "" if nothingintlength = res.orElse("").length();
// run the lambda if there is a valueres.ifPresent(v -> results.add(v));Return an Optional
Optional<Double> squareRoot(doublex) {
if (x >= 0) { returnOptional.of(Math.sqrt(x)); }
else { returnOptional.empty(); }
}Note on inferance limitations
interfacePair<A, B> {
Afirst();
Bsecond();
}A steam of type Stream<Pair<String, Long>> :
stream.sorted(Comparator.comparing(Pair::first)) // okstream.sorted(Comparator.comparing(Pair::first).thenComparing(Pair::second)) // dont work
Java cannot infer type for the .comparing(Pair::first) part and fallback to Object, on which Pair::first cannot be applied.
The required type for the whole expression cannot be propagated through the method call (.thenComparing) and used to infer type of the first part.
Type must be given explicitly.
stream.sorted(
Comparator.<Pair<String, Long>, String>comparing(Pair::first)
.thenComparing(Pair::second)
) // okThis cheat sheet was based on the lecture of Cay Horstmann http://horstmann.com/heig-vd/spring2015/poo/