Showing posts with label Stream. Show all posts
Showing posts with label Stream. Show all posts

Saturday, October 21, 2017

Java 8 Stream, Collectors Examples


Here are the examples of the Java 8 Stream

Methods in Stream interface

collect, forEach, filter, flatMap,  flatMapToInt, limit, map, mapToInt, of, parallel, peek, reduce, stream.

flatMap: a set of collections is required to produce the final flattered collection.
parallel: a set of collections is required to run the combiner function.
peek: very useful for debugging.
collect and reduce: there are Collectors class that provides many convenient methods.

Methods in Collectors

averagingDouble, groupBy, partitionBy, toMap, toList, toSet.



import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.Set;
import java.util.TreeMap;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.junit.Test;

public class StreamExamples {
       static List<Employee> employeeList = Arrays.asList(new Employee("Tom Jones", 45, "A"),
                    new Employee("Harry Major", 25, "B"), new Employee("Ethan Hardy", 65, "A"),
                    new Employee("Nancy Smith", 15, "C"), new Employee("Deborah Sprightly", 29, "A"));

       @Test
       public void testFlatMapAndPeek() {
             List<String> originalStringList = Arrays.asList("Peter", "Adam", "John");
             Stream<String> a = originalStringList.stream();
             // Object array is required, s.split("") returns a String[], primitive
             // arrays such as char[] do not work here.
             Stream<String[]> b = a.map(s -> s.split("")).peek(s -> System.out.println(Arrays.toString(s)));
             Stream<String> d = b.flatMap(c -> Arrays.stream(c));
             Optional<String> e = d.limit(10).reduce((s1, s2) -> s1 + s2);
             System.out.println(e.get());
       }

       @Test
       public void testFlatMapAndFilterAndCount() {
             long count = Stream.of("Adam", "Peter", "Mike", "alice", "Linda", "pam").map(s -> s.toUpperCase())
                           .filter(s -> s.startsWith("A")).map(s -> s.split("")).flatMap(s -> Arrays.stream(s)).count();
             System.out.println("count:" + count);

             employeeList.stream().map(emp -> emp.getName()).forEach(System.out::println);
             employeeList.stream().map(emp -> emp.getName().split("")).flatMap(array -> Arrays.stream(array))
                           .map(str -> str.toUpperCase()).filter(str -> !(str.equals(" ")))
                           .forEach(str -> System.out.println(str));
       }

       @Test
       public void testMapToIntAndSum() {
             Stream<Integer> stream = Stream.of(1, 2, 3, 4);
             int sum = stream.filter(i -> i > 1).mapToInt(i -> i).sum();
             System.out.println("sum:" + sum);
       }

       @Test
       public void testStreamWithPrimitiveChar() {
             List<String> strList = new ArrayList<>();
             strList.add("Peter");
             strList.add("Jane");
             int[] ci = strList.stream().map(s -> s.chars()).flatMapToInt(i -> i).toArray();
             for (int c : ci) {
                    System.out.println((char) c);
             }
       }

       @Test
       public void testReduce() {
             System.out.println("===testReduce===");
             String r = Stream.of("Peter", "Jane").map(s -> s.split("")).flatMap(s -> Arrays.stream(s))
                           .peek(System.out::println).reduce("s", (a, b) -> a + b);
             System.out.println("r:" + r);

             OptionalInt sum = Stream.of("Peter", "Jane").map(s -> s.chars()).flatMapToInt(i -> i).peek(System.out::println)
                           .reduce((i, j) -> {
                                 return i + j;
                           });
             System.out.println("sum:" + sum.getAsInt());

             String reduced = Stream.of("123", "456").parallel().map(s -> s.split("")).flatMap(i -> Arrays.stream(i))
                           .peek(System.out::println).reduce("s", (i, j) -> i + ":" + j, (k, l) -> k + ";" + l);
             System.out.println("reduced:" + reduced);

             int reduced1 = Stream.of("123", "456").parallel().map(s -> s.split("")).flatMap(i -> Arrays.stream(i))
                           .peek(System.out::println).reduce(0, (i, j) -> i + Integer.parseInt(j), (k, l) -> k * l);
             System.out.println("reduced1:" + reduced1);
       }

       @Test
       public void testFunctionInterfaces() {
             Function<List<String>, List<String>> toUppderCase = a -> a.stream().map(s -> s.toUpperCase())
                           .collect(Collectors.toList());
             Function<List<String>, List<String>> filter = a -> a.stream().filter(s -> s.startsWith("A"))
                           .collect(Collectors.toList());
             Function<List<String>, StringBuilder> accumulateResult = a -> a.stream().collect(StringBuilder::new,
                           (response, element) -> response.append(" ").append(element),
                           (response1, response2) -> response1.append(",").append(response2.toString()));

             Function<List<String>, StringBuilder> f = toUppderCase.andThen(filter).andThen(accumulateResult);
              System.out.println("##############################################");
             System.out.println(f.apply(Arrays.asList("Adam", "Peter", "Mike", "alice", "Linda", "pam")));
       }

       @Test
       public void testCollectors() {
             System.out.println("===testCollectors===");
             String joinedResult = Stream.of("Adam", "Peter", "Mike", "alice", "Linda", "pam").map(s -> s.toUpperCase())
                           .filter(s -> s.startsWith("A")).collect(Collectors.joining(",", "name:[", "]"));
             System.out.println("joinedResult:" + joinedResult);

             Map<Integer, List<String>> a = Stream.of("Adam", "Peter", "Mike", "alice", "Linda", "pam")
                           .map(s -> s.toUpperCase()).collect(Collectors.groupingBy(String::length));
             System.out.println("groups:" + a);

             Map<String, List<Employee>> b = employeeList.stream().collect(Collectors.groupingBy(e -> e.getDepartment()));
             System.out.println("groups:" + b);

             Map<String, Set<String>> c = employeeList.stream().collect(Collectors.groupingBy(Employee::getDepartment,
                           TreeMap::new, Collectors.mapping(Employee::getName, Collectors.toSet())));
             System.out.println("groups:" + c);

             Double averageAge = employeeList.stream().collect(Collectors.averagingDouble(e -> e.getRate()));
             System.out.println("averageAge:" + averageAge);

             Map<Boolean, List<Employee>> d = employeeList.stream()
                           .collect(Collectors.partitioningBy(e -> e.getRate() > 30));
             System.out.println("groups:" + d);

             Map<Boolean, Set<String>> f = employeeList.stream().collect(Collectors.partitioningBy(e -> e.getRate() > 30,
                           Collectors.mapping(e -> e.getName(), Collectors.toSet())));
             System.out.println("groups:" + f);

             Map<String, String> g = employeeList.stream()
                           .collect(Collectors.toMap(e -> e.getDepartment(), e -> e.getName(), (a1, a2) -> a1 + "," + a2));
             System.out.println("groups:" + g);
       }

       @Test
       public void testCollectAndParallel() {
             StringBuilder result = Stream.of("Adam", "Peter", "Mike", "alice", "Linda", "pam").map(s -> s.toUpperCase())
                           .collect(StringBuilder::new, (stringBuilder, s) -> {
                                 int i = stringBuilder.length();
                                 if (i == 0) {
                                        stringBuilder.append(s);
                                 } else {
                                        stringBuilder.append("/").append(s);
                                 }
                           }, (response1, response2) -> response1.append(",").append(response2.toString()));
             System.out.println("result of non-parallel run:" + result);

             String result2 = Stream
                           .of(Arrays.asList("Adam", "Alan"), Arrays.asList("Peter", "Pam"),
                                        Arrays.asList("Mike", "alice", "Linda"))
                           .parallel().flatMap(s -> s.stream()).collect(StringBuilder::new, (stringBuilder, s) -> {
                                 int i = stringBuilder.length() + 1;
                                 if (i == 0) {
                                        stringBuilder.append(s);
                                 } else {
                                        stringBuilder.append("/").append(s);
                                 }
                           }, (response1, response2) -> response1.append(",").append(response2.toString())).toString();
             System.out.println("result of parallel run:" + result2);

       }

       public static class Employee {
             @Override
             public String toString() {
                    return "Employee [name=" + name + ", rate=" + rate + ", department=" + department + "]";
             }

             private final String name;
             private final Integer rate;
             private final String department;

             public Employee(final String name, final Integer rate, final String department) {
                    this.name = name;
                    this.rate = rate;
                    this.department = department;
             }

             public String getName() {
                    return name;
             }

             public Integer getRate() {
                    return rate;
             }

             public String getDepartment() {
                    return department;
             }
       }
}