Ümit ÜNAL - n11.com
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = 0;
for (int n : numbers) {
if (n % 2 == 1) {
int square = n * n;
sum = sum + square;
}
}int sum = numbers.stream()
.filter(n -> n % 2 == 1)
.map(n -> n * n)
.reduce(0, Integer::sum);A stream supports two types of operations:

Step by step Stream
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream()
.filter(n -> n % 2 == 1)
.map(n -> n * n)
.reduce(0, Integer::sum);Step by step Stream
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream()
.filter(n -> n % 2 == 1)
.map(n -> n * n)
.reduce(0, Integer::sum);
Step by step Stream
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream()
.filter(n -> n % 2 == 1)
.map(n -> n * n)
.reduce(0, Integer::sum);
Step by step Stream
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream()
.filter(n -> n % 2 == 1)
.map(n -> n * n)
.reduce(0, Integer::sum);
Step by step Stream
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream()
.filter(n -> n % 2 == 1)
.map(n -> n * n)
.reduce(0, Integer::sum);

Streams from Values
<T> Stream<T> of(T t)
<T> Stream<T> of(T...values)
// Creates a stream with one string elements
Stream<String> stream = Stream.of("Hello");
// Creates a stream with four strings
Stream<String> stream = Stream.of("Ken", "Jeff", "Chris", "Ellen");
// Compute the sum of the squares of all odd integers in the list
int sum = Stream.of(1, 2, 3, 4, 5)
.filter(n -> n % 2 == 1)
.map(n -> n * n)
.reduce(0, Integer::sum);
System.out.println("Sum = " + sum);
// Result
Sum = 35
Streams from Values
String[] names = {"Ken", "Jeff", "Chris", "Ellen"};
// Creates a stream of four strings in the names array
Stream<String> stream = Stream.of(names);Streams from Functions
Stream.iterate(1L, n -> n + 2).limit(5)
.forEach(System.out::println);
// Result:
1
3
5
7
9
////////////////////////////////////
Stream.generate(Math::random).limit(5)
.forEach(System.out::println);
// Result:
0.05958352209327644
0.8122226657626394
0.5073323815997652
0.9327951597282766
0.4314430923877808Streams from Arrays
// Creates a stream from an int array with elements 1, 2, and 3
IntStream numbers = Arrays.stream(new int[]{1, 2, 3});
// Creates a stream from a String array with elements "Ken", and "Jeff"
Stream<String> names = Arrays.stream(new String[] {"Ken", "Jeff"});Streams from Collections
// Create and populate a set of strings
Set<String> names = new HashSet<>();
names.add("Ken");
names.add("jeff");
// Create a sequential stream from the set
Stream<String> sequentialStream = names.stream();
// Create a parallel stream from the set
Stream<String> parallelStream = names.parallelStream();Streams from Other Sources
String str = "5 apples and 25 oranges";
str.chars()
.filter(n -> !Character.isDigit((char)n) && !Character.isWhitespace((char)n))
.forEach(n -> System.out.print((char)n));
// Result :
applesandoranges
String str = "Ken,Jeff,Lee";
Pattern.compile(",")
.splitAsStream(str)
.forEach(System.out::println);
// Result :
Ken
Jeff
LeeCommon Stream Operations
Intermediate
Terminal
Debugging a Stream Pipeline
int sum = Stream.of(1, 2, 3, 4, 5)
.peek(e -> System.out.println("Taking integer: " + e))
.filter(n -> n % 2 == 1)
.peek(e -> System.out.println("Filtered integer: " + e))
.map(n -> n * n)
.peek(e -> System.out.println("Mapped integer: " + e))
.reduce(0, Integer::sum);
System.out.println("Sum = " + sum);
//Result:
Taking integer: 1
Filtered integer: 1
Mapped integer: 1
Taking integer: 2
Taking integer: 3
Filtered integer: 3
Mapped integer: 9
Taking integer: 4
Taking integer: 5
Filtered integer: 5
Mapped integer: 25
Sum = 35Applying the ForEach Operation
void forEach(Consumer<? super T> action)
void forEachOrdered(Consumer<? super T> action)
Person.persons()
.stream()
.filter(Person::isFemale)
.forEach(System.out::println);
//Result:
(3, Donna, FEMALE, 1962-07-29, 8700.00)
(5, Laynie, FEMALE, 2012-12-13, 0.00)Applying the ForEach Operation
// Get the list of persons
List<Person> persons = Person.persons();
// Print the list
System.out.println("Before increasing the income: " + persons);
// Increase the income of females by 10%
persons.stream()
.filter(Person::isFemale)
.forEach(p -> p.setIncome(p.getIncome() * 1.10));
// Print the list again
System.out.println("After increasing the income: " + persons);
Before increasing the income: [(1, Ken, MALE, 1970-05-04, 6000.00),
(2, Jeff, MALE, 1970-07-15, 7100.00),(3, Donna, FEMALE, 1962-07-29, 8700.00),
(4, Chris, MALE, 1993-12-16, 1800.00), (5, Laynie, FEMALE, 2012-12-13, 0.00),
(6, Li, MALE, 2001-05-09, 2400.00)]
After increasing the income: [..(3, Donna, FEMALE, 1962-07-29, 9570.00)..]Applying the Map Operation
<R> Stream<R> map(Function<? super T,? extends R> mapper)
DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper)
IntStream mapToInt(ToIntFunction<? super T> mapper)
LongStream mapToLong(ToLongFunction<? super T> mapper)
ToDoubleFunction:
@FunctionalInterface
public interface ToDoubleFunction<T> {
/**
* Applies this function to the given argument.
*
* @param value the function argument
* @return the function result
*/
double applyAsDouble(T value);
}
You can apply the map operation on a stream using one of the following methods of the Stream<T> interface
Applying the Map Operation
IntStream map(IntUnaryOperator mapper)
DoubleStream mapToDouble(IntToDoubleFunction mapper)
LongStream mapToLong(IntToLongFunction mapper)
<U> Stream<U> mapToObj(IntFunction<? extends U> mapper)
IntToDoubleFunction:
@FunctionalInterface
public interface IntToDoubleFunction {
/**
* Applies this function to the given argument.
*
* @param value the function argument
* @return the function result
*/
double applyAsDouble(int value);
}
Applying the Map Operation
IntStream.rangeClosed(1, 5).map(n -> n * n)
.forEach(System.out::println);
//Result :
1
4
9
16
25
Person.persons().stream().map(Person::getName)
.forEach(System.out::println);
//Result :
Ken
Jeff
Donna
Chris
Laynie
LiFlattening Streams
Stream.of(1, 2, 3)
.map(n -> Stream.of(n, n * n))
.forEach(System.out::println);
java.util.stream.ReferencePipeline$Head@372f7a8d
java.util.stream.ReferencePipeline$Head@2f92e0f4
java.util.stream.ReferencePipeline$Head@28a418fcFlattening Streams
Stream.of(1, 2, 3)
.map(n -> Stream.of(n, n * n))
.forEach(e -> e.forEach(System.out::println));
// Result :
1
1
2
4
3
9Flattening Streams
Stream.of(1, 2, 3)
.flatMap(n -> Stream.of(n, n * n))
.forEach(System.out::println);
1
1
2
4
3
9
Applying the Filter Operation
You can apply a filter operation to a stream using the filter() method of the Stream, IntStream, LongStream, and DoubleStream interfaces. The method accepts an instance of the Predicate interface.

Applying the Filter Operation
Person.persons()
.stream()
.filter(Person::isFemale)
.map(Person::getName)
.forEach(System.out::println);
//Result :
Donna
Laynie
Person.persons()
.stream()
.filter(p -> p.isMale() && p.getIncome() > 5000.0)
.map(Person::getName)
.forEach(System.out::println);
//Result :
Ken
JeffCollecting Data Using Collectors
<R> R collect(Supplier<R> supplier, BiConsumer<R,? super T> accumulator,
BiConsumer<R,R> combiner)
<R,A> R collect(Collector<? super T,A,R> collector)Collecting Data Using Collectors
// Using a lambda expression
Supplier<ArrayList<String>> supplier = () -> new ArrayList<>();
// Using a constructor reference
Supplier<ArrayList<String>> supplier = ArrayList::new;// Using a lambda expression
BiConsumer<ArrayList<String>, String> accumulator = (list, name) -> list.add(name);
// Using a constructor reference
BiConsumer<ArrayList<String>, String> accumulator = ArrayList::add;
// Using a lambda expression
BiConsumer<ArrayList<String>, ArrayList<String>> combiner =
(list1, list2) -> list1.addAll(list2);
// Using a constructor reference
BiConsumer<ArrayList<String>, ArrayList<String>> combiner = ArrayList::addAll;Collecting Data Using Collectors
List<String> names = Person.persons()
.stream()
.map(Person::getName)
.collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
System.out.println(names);
[Ken, Jeff, Donna, Chris, Laynie, Li]
Collecting Data Using Collectors
List<String> names = Person.persons()
.stream()
.map(Person::getName)
.collect(Collectors.toList());
System.out.println(names);
[Ken, Jeff, Donna, Chris, Laynie, Li]Collecting Data Using Collectors
Set<String> uniqueNames = Person.persons()
.stream()
.map(Person::getName)
.collect(Collectors.toSet());
System.out.println(uniqueNames);
[Donna, Ken, Chris, Jeff, Laynie, Li]Collecting Data Using Collectors
SortedSet<String> uniqueSortedNames= Person.persons()
.stream()
.map(Person::getName)
.collect(Collectors.toCollection(TreeSet::new));
System.out.println(uniqueSortedNames);
[Chris, Donna, Jeff, Ken, Laynie, Li]Collecting Data Using Collectors
List<String> sortedName = Person.persons()
.stream()
.map(Person::getName)
.sorted()
.collect(Collectors.toList());
System.out.println(sortedName);
[Chris, Donna, Jeff, Ken, Laynie, Li]Collecting Data Using Collectors
long count = Person.persons()
.stream()
.collect(Collectors.counting());
System.out.println("Person count: " + count);
Person count: 6
Collecting Data Using Collectors
long count = Person.persons()
.stream()
.count();
System.out.println("Persons count: " + count);
Persons count: 6Collecting Summary Statistics
Collecting Summary Statistics
DoubleSummaryStatistics incomeStats =
Person.persons()
.stream()
.collect(Collectors.summarizingDouble(Person::getIncome));
System.out.println(incomeStats);
DoubleSummaryStatistics{count=6, sum=26000.000000, min=0.000000,
average=4333.333333, max=8700.000000}Collecting Summary Statistics
DoubleSummaryStatistics stats = new DoubleSummaryStatistics();
stats.accept(100.0);
stats.accept(500.0);
stats.accept(400.0);
// Get stats
long count = stats.getCount();
double sum = stats.getSum();
double min = stats.getMin();
double avg = stats.getAverage();
double max = stats.getMax();
count=3, sum=1000.00, min=100.00, average=500.00, max=333.33Collecting Data in Maps
toMap(Function<? super T,? extends K> keyMapper,
Function<? super T,? extends U> valueMapper)
toMap(Function<? super T,? extends K> keyMapper,
Function<? super T,? extends U> valueMapper,
BinaryOperator<U> mergeFunction)Collecting Data in Maps
Map<Long,String> idToNameMap = Person.persons()
.stream()
.collect(Collectors.toMap(Person::getId, Person::getName));
System.out.println(idToNameMap);
{1=Ken, 2=Jeff, 3=Donna, 4=Chris, 5=Laynie, 6=Li}Collecting Data in Maps
Map<Person.Gender,String> genderToNamesMap = Person.persons()
.stream()
.collect(Collectors.toMap(Person::getGender, Person::getName));
The code throws the following runtime exception. java.lang.IllegalStateException: Duplicate key Ken
Collecting Data in Maps
Map<Person.Gender,String> genderToNamesMap = Person.persons()
.stream()
.collect(Collectors.toMap(
Person::getGender,
Person::getName,
(oldValue, newValue) -> String.join(", ", oldValue, newValue)
));
System.out.println(genderToNamesMap);
{FEMALE=Donna, Laynie, MALE=Ken, Jeff, Chris, Li}Collecting Data in Maps
Map<Person.Gender, Long> countByGender = Person.persons()
.stream()
.collect(Collectors.toMap(Person::getGender, p -> 1L,
(oldCount, newCount) -> oldCount++));
System.out.println(countByGender);
{MALE=4, FEMALE=2}Joining Strings Using Collectors
joining()
joining(CharSequence delimiter)
joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix)Joining Strings Using Collectors
String names = persons.stream()
.map(Person::getName)
.collect(Collectors.joining());
System.out.println("Joined names: " + names);
Joined names: KenJeffDonnaChrisLaynieLiJoining Strings Using Collectors
String delimitedNames = persons.stream()
.map(Person::getName)
.collect(Collectors.joining(", "));
System.out.println("Joined, delimited names: " + delimitedNames);
Joined, delimited names: Ken, Jeff, Donna, Chris, Laynie, Li
Joining Strings Using Collectors
String prefixedNames = persons.stream()
.map(Person::getName)
.collect(Collectors.joining(", ", "Hello ", ". Goodbye."));
System.out.println(prefixedNames);
Hello Ken, Jeff, Donna, Chris, Laynie, Li. Goodbye.
Grouping Data
groupingBy(Function<? super T,? extends K> classifier)
groupingBy(Function<? super T,? extends K> classifier,
Collector<? super T,A,D> downstream)
groupingBy(Function<? super T,? extends K> classifier,
Supplier<M> mapFactory,
Collector<? super T,A,D> downstream)Grouping Data
Map<Person.Gender, List<Person>> personsByGender =
Person.persons()
.stream()
.collect(Collectors.groupingBy(Person::getGender));
System.out.println(personsByGender);
// Result
{FEMALE=[(3, Donna, FEMALE, 1962-07-29, 8700.00),
(5, Laynie, FEMALE, 2012-12-13, 0.00)],
MALE=[(1, Ken, MALE, 1970-05-04, 6000.00),
(2, Jeff, MALE, 1970-07-15, 7100.00),
(4, Chris, MALE, 1993-12-16, 1800.00),
(6, Li, MALE, 2001-05-09, 2400.00)]}Grouping Data
Map<Person.Gender, Long> countByGender = Person.persons()
.stream()
.collect(
Collectors.groupingBy(Person::getGender,
Collectors.counting()));
System.out.println(countByGender);
{MALE=4, FEMALE=2}Grouping Data
Map<Person.Gender, String> namesByGender = Person.persons()
.stream()
.collect(Collectors.groupingBy(Person::getGender,
Collectors.mapping(Person::getName,
Collectors.joining(", "))));
System.out.println(namesByGender);
// Result :
{MALE=Ken, Jeff, Chris, Li, FEMALE=Donna, Laynie}Grouping Data
Map<Person.Gender, Map<Month, String>> personsByGenderAndDobMonth =
Person.persons()
.stream()
.collect(Collectors.groupingBy(Person::getGender,
Collectors.groupingBy(p -> p.getDob().getMonth(),
Collectors.mapping(Person::getName,
Collectors.joining(", ")))));
System.out.println(personsByGenderAndDobMonth);
// Result
{FEMALE={DECEMBER=Laynie, JULY=Donna},
MALE={DECEMBER=Chris, JULY=Jeff, MAY=Ken, Li}}
Grouping Data
List<Integer> integerList = Arrays.asList(new Integer[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 });
Map<Integer, List<Integer>> evenOddMap = integerList
.stream().collect(Collectors.groupingBy(i -> i % 2 == 0 ? 0 : 1));
// Will print 2, 4, 6, 8
System.out.println(evenOddMap.get(0));
// Will print 1, 3, 5, 7, 9
System.out.println(evenOddMap.get(1));Partitioning Data
partitioningBy(Predicate<? super T> predicate)
partitioningBy(Predicate<? super T> predicate,
Collector<? super T,A,D> downstream)Partitioning Data
Map<Boolean, List<Person>> partionedByMaleGender = Person.persons()
.stream()
.collect(Collectors.partitioningBy(Person::isMale));
System.out.println(partionedByMaleGender);
{false=[(3, Donna, FEMALE, 1962-07-29, 8700.00),
(5, Laynie, FEMALE, 2012-12-13, 0.00)],
true=[(1, Ken, MALE, 1970-05-04, 6000.00),
(2, Jeff, MALE, 1970-07-15, 7100.00),
(4, Chris, MALE, 1993-12-16, 1800.00),
(6, Li, MALE, 2001-05-09, 2400.00)]}Partitioning Data
Map<Boolean,String> partionedByMaleGender =
Person.persons()
.stream()
.collect(Collectors.partitioningBy(Person::isMale,
Collectors.mapping(Person::getName, Collectors.joining(", "))));
System.out.println(partionedByMaleGender);
{false=Donna, Laynie, true=Ken, Jeff, Chris, Li}boolean allMatch(Predicate<? super T> predicate)
boolean anyMatch(Predicate<? super T> predicate)
boolean noneMatch(Predicate<? super T> predicate)// Check if all persons are males
boolean allMales = Person.stream().allMatch(Person::isMale);
System.out.println("All males: " + allMales);
// Result :
All males: false// Check if any person was born in 1970
boolean anyoneBornIn1970 = Persons.stream()
.anyMatch(p -> p.getDob().getYear() == 1970);
System.out.println("Anyone born in 1970: " + anyoneBornIn1970);
// Result :
Anyone born in 1970: true// Check if any person was born in 1955
boolean anyoneBornIn1955 = Persons.stream()
.anyMatch(p -> p.getDob().getYear() == 1955);
System.out.println("Anyone born in 1955: " + anyoneBornIn1955);
// Result
Anyone born in 1955: falsepublic Set<String> findLongTracks(List<Album> albums) {
Set<String> trackNames = new HashSet<>();
for(Album album : albums) {
for (Track track : album.getTrackList()) {
if (track.getLength() > 60) {
String name = track.getName();
trackNames.add(name);
}
}
}
return trackNames;
}public Set<String> findLongTracks(List<Album> albums) {
Set<String> trackNames = new HashSet<>();
albums.stream()
.forEach(album -> {
album.getTracks()
.forEach(track -> {
if (track.getLength() > 60) {
String name = track.getName();
trackNames.add(name);
}
});
});
return trackNames;
}public Set<String> findLongTracks(List<Album> albums) {
Set<String> trackNames = new HashSet<>();
albums.stream()
.forEach(album -> {
album.getTracks()
.filter(track -> track.getLength() > 60)
.map(track -> track.getName())
.forEach(name -> trackNames.add(name));
});
return trackNames;
}public Set<String> findLongTracks(List<Album> albums) {
Set<String> trackNames = new HashSet<>();
albums.stream()
.flatMap(album -> album.getTracks())
.filter(track -> track.getLength() > 60)
.map(track -> track.getName())
.forEach(name -> trackNames.add(name));
return trackNames;
}
public Set<String> findLongTracks(List<Album> albums) {
return albums.stream()
.flatMap(album -> album.getTracks())
.filter(track -> track.getLength() > 60)
.map(track -> track.getName())
.collect(toSet());
}
Ümit ÜNAL

https://github.com/umitunal/java8-for-nerd/