Common functional interfaces

  1. Consumer takes a parameter and returns no value
void accept(T t); Example: List<Integer> List = arrays. asList(1, 2, 3, 4, 5, 6, 7, 8); list.forEach(a -> System.out.println(a)); ForEach receives the ConsumerCopy the code
  1. Function takes a parameter and returns a value
R apply(T t); List. Stream ().map(a -> a * a).foreach (system.out ::println); Map receives FunctionCopy the code
  1. The Comparator takes two arguments and returns int
int compare(T o1, T o2); Usage example: collections.sort (list, comparator.reverseOrder ()); The second parameter that Collections receives is the ComparatorCopy the code
  1. Predicate takes a parameter and returns Boolean
boolean test(T t); Example: list.stream().filter(a -> a > 5).foreach (system.out ::println); Predicate private void conditionFilter(List<Integer> List, Predicate<Integer> predicate) { for (Integer i : list) { if (predicate.test(i)) { System.out.println(i); } } } ins.conditionFilter(list, a -> a % 2 == 0); ins.conditionFilter(list, a -> a > 4); ins.conditionFilter(list, a -> true); A functional interface that passes behavior, not dataCopy the code
  1. Supplier does not accept arguments and returns a value
T get();

Supplier fun = FunctionTest::new;
Copy the code
  1. Optional value-base class. This is not a functional interface
Employee employee= new Employee();
employee.setName("zhangsan");

Employee employee2=new Employee();
employee2.setName("lisi");

Company company = new Company();
company.setName("company1");

List<Employee> employees = Arrays.asList(employee, employee2);
company.setEmployees(employees);

Optional<Company> optional = Optional.ofNullable(company);

System.out.println(optional.map(theCompany-> theCompany.getEmployees()).orElse(Collections.emptyList()));
Copy the code

Method references

Method references fall into four categories:

  1. Class name :: Static method name
  2. Reference name (object name):: Instance method name
  3. Class name :: Instance method name
  4. Constructor reference: class name ::new

stream

  • Collection provides a new stream() method
  • Streams do not store values; they are piped to them
  • Functional in nature, the flow operation generates a result, but does not modify the underlying data source. The collection can be used as the underlying data source for the flow
  • Delayed look-ups, many stream operations (filtering, mapping, sorting, etc.) can be delayed
  • Iterators differ in that Stream can be parallelized; iterators can only be imperative and serialized
  • When traversing in serial mode, the next item is read after each item is finished
  • With parallel traversal, the data is divided into segments, each of which is processed in a different thread, and the results are output together
  • Parallel operation of streams relies on the Fork/Join framework introduced in Java7

The stream collect method is usually called at the end of a collection operation to return the processed stream. For example:

Stream<String> stream = Stream.of("hello", "world", "juejin");
List<String> list = stream.collect(Collectors.toList());
Copy the code

Method definition of collect:

<R> R collect(Supplier<R> supplier,
              BiConsumer<R, ? super T> accumulator,
              BiConsumer<R, R> combiner);
Copy the code

As defined above, it can be called like this:

ArrayList<Object> list1 = stream.collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
Copy the code

This makes it obvious that method calls are passing behavior, not data.

Small exercise: find the elements greater than 2 in the flow, then multiply each element by 2, then ignore the first two elements in the flow, then take the first two elements in the flow, and finally find the larger value of the elements in the flow.

Stream<Integer> stream = Stream.iterate(1, item -> item + 2).limit(100);
stream.filter(item -> item > 2).mapToInt(item -> item * 2).skip(2).limit(2).max().ifPresent(System.out::println);
Copy the code

Concurrent current and current short circuit

  • Concurrent flow
ArrayList<Object> list = new ArrayList<>(5000000); for (int i = 0; i < 5000000; i++) { list.add(UUID.randomUUID().toString()); } system.out.println (" start ordering "); long start = System.currentTimeMillis(); list.stream().sorted().count(); System.out.println(" time: "+ (system.currentTimemillis () -start));Copy the code

Stream sort time Start sort time: 4689

When a change to the list. ParallelStream (.) sorted (). The count (); Concurrent stream start ordering time: 2473

  • Short circuit operation
List<String> list = Arrays.asList("hello", "world", "hello world");
list.stream().mapToInt(item -> {
    int length = item.length();
    System.out.println(item);
    return length;
}).filter(length -> length == 5).findFirst().ifPresent(System.out::println);
Copy the code

The operation of the printed result: Hello 5 stream is to first apply all the operations to the first element, the second, and the third…… Instead of applying the first action to the first element, to the second, to the third, applying the second action to the first element, to the second, to the third

Little practice:

  1. “Hello Welcome “,” World Hello “, “Hello world Hello “,” Hello Welcome “are printed as distinct strings
List<String> list = Arrays.asList("hello welcome", "world hello", "hello world hello", "hello welcome");
list.stream().map(item -> item.split(" ")).flatMap(Arrays::stream).distinct().forEach(System.out::println);

Copy the code
  1. Merge the values of the two lists
List<String> List = arrays.aslist ("Hi", "Hello", "Hello"); List<String> list2 = Arrays.asList("zhangsan", "lisi", "wangwu", "zhaoliu"); List<String> result = list.stream().flatMap(item -> list2.stream().map(item2 -> item + " " + item2)).collect(Collectors.toList()); result.forEach(System.out::println);Copy the code

Results:

Hi Zhangsan Hi lisi Hi Wangwu Hi zhaoliu Hello Zhangsan Hello lisi Hello Wangwu Hello zhaoliu Hello Zhangsan Hi Lisi Hello Hi wangwu zhaoliuCopy the code

The stream grouping

Student student1 = new Student("zhangsan", 100, 20);
student student2 = new student("lisi", 90, 20);
Student student3 = new student ("wangwu", 90, 30);
Student student4 = new student("zhangsan", 80, 40);

List<Object> students = Arrays.asList(student1, student2, student3, student4);
students.stream().collect(Collectors.groupingBy(Student::getNames));
Copy the code

collect

  1. Collect:
  2. Collector takes the parameter of the collect method
  3. Collector is an interface that is a variable aggregation operation that accumulates input elements into a variable result container; It converts the cumulative result into a final representation (an optional operation) after all elements have been processed; It supports both serial and parallel execution.
  4. The Collectors themselves provide a common aggregation implementation for Collectors, and the Collectors themselves are actually a factory.
  5. To ensure the equivalence of serial and parallel results, the Collector function needs to satisfy two conditions: identity and associativity.
  6. a == combiner.apply(a, supplier.get())
  7. The best thing about functional programming is that it represents what to do, not how to do it.

Official example of collect:

// Accumulate names into a List * List<String> list = people.stream().map(Person::getName).collect(Collectors.toList());  * * // Accumulate names into a TreeSet * Set<String> set = people.stream().map(Person::getName).collect(Collectors.toCollection(TreeSet::new)); * * // Convert elements to strings and concatenate them, separated by commas * String joined = things.stream() * .map(Object::toString) * .collect(Collectors.joining(", ")); * * // Compute sum of salaries of employee * int total = employees.stream() * .collect(Collectors.summingInt(Employee::getSalary))); * * // Group employees by department * Map<Department, List<Employee>> byDept * = employees.stream() * .collect(Collectors.groupingBy(Employee::getDepartment)); * * // Compute sum of salaries by department * Map<Department, Integer> totalByDept * = employees.stream() * .collect(Collectors.groupingBy(Employee::getDepartment, * Collectors.summingInt(Employee::getSalary))); * * // Partition students into passing and failing * Map<Boolean, List<Student>> passingFailing = * students.stream() * .collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD));Copy the code