Quickly grasp the new features of Java 8

Lambda expression

Lambda expressions allow you to pass code like data by using functions as arguments to methods.

Basic grammar

<Functional interface> <Variable name> = (Parameter 1,Parameter 2...) -> {

   //Method body


The following are important features of lambda expressions:

  • Optional type declaration: there is no need to declare parameter types, and the compiler can uniformly identify parameter values.
  • Optional parameter parentheses: one parameter does not need to define parentheses, but multiple parameters need to define parentheses.
  • Optional curly braces: if the body contains a statement, curly braces are not required.
  • Optional return keyword: if the body has only one expression return value, the compiler will automatically return the value. Braces need to specify that the expression returns a value.

If an interface has only one abstract method, it is called a functional interface.

You can use the @ functional interface annotation to detect whether it is a functional interface

Common functional interfaces

Take Consumer as an example:

Method reference

Method reference is a short form of Lambda expression. If only a specific existing method is called in the method body of Lambda expression, method reference can be used.

Common forms:

Object:: instance method

Class:: static method

Class:: instance method

Class:: new

public class Demo2 {
    public static void main(String[] args) {
        //Object:: instance method
        Consumer<String> consumer = System.out::println;

        //Class:: static method
        Comparator<Integer> comparator = Integer::compare;

        //Class:: instance method
       Function<User,String> f = User::getUserName;
        //Class:: new
        Supplier<User> user = User::new;

Stream stream

What is Stream

The operation on a set or array is saved in a Stream, which is similar to a set, but data is saved in a set and operations are saved in a Stream. It's like a mechanical assembly line in a factory.

Characteristics of Stream:

  • Stream itself does not store elements
  • Stream does not change the source object; instead, it returns a new stream that holds the result
  • The Stream operation is delayed, which means that it will wait until the result is needed

Create Stream

  • Through the Stream() or parallelStream of the Collection object
  • Through the stream() method of the Arrays class
  • Through the of(), iterate(), generate() methods of the Stream interface
  • Through the of, range and rangeClosed methods in the IntStream, LongStream and DoubleStream interfaces
public class Demo3 {
    public static void main(String[] args) {
        //Through the Stream() or parallelStream of the Collection object
        ArrayList<String> list = new ArrayList<>();
        Stream<String> stream = list.stream();
        //Through the stream() method of the Arrays class
        String[] arr = {"a","b","c"};
        Stream<String> stream1 = Arrays.stream(arr);
        //Through the of(), iterate(), generate() methods of the Stream interface
        Stream<Integer> integerStream = Stream.of(10, 20, 30);
        System.out.println("=========Iterative flow");
        Stream<Integer> iterate = Stream.iterate(0, x -> x + 2);
        System.out.println("========Generate flow");
        Stream<Integer> generate = Stream.generate(() -> new Random().nextInt(10));
        //Through the of, range and rangeClosed methods in the IntStream, LongStream and DoubleStream interfaces
        IntStream intStream = IntStream.of(15, 20, 25);
        //Range rangeclosed (10, 50) (10, 50]
        IntStream range = IntStream.range(10, 50);
        IntStream rangeClosed = IntStream.rangeClosed(10, 50);

Intermediate operation

User class

public class User {
    private String userName;
    private Integer age;

    public User() {

    public User(String userName, Integer age) {
        this.userName = userName;
        this.age = age;

    public String getUserName() {
        return userName;

    public void setUserName(String userName) {
        this.userName = userName;

    public Integer getAge() {
        return age;

    public void setAge(Integer age) {
        this.age = age;

    public String toString() {
        return "User{" +
                "userName='" + userName + '\'' +
                ", age=" + age +

    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof User)) return false;

        User user = (User) o;

        if (!Objects.equals(userName, user.userName)) return false;
        return Objects.equals(age, user.age);

    public int hashCode() {
        int result = userName != null ? userName.hashCode() : 0;
        result = 31 * result + (age != null ? age.hashCode() : 0);
        return result;

Stream intermediate operation

import java.util.ArrayList;
import java.util.Comparator;

public class Demo4 {
    public static void main(String[] args) {
        ArrayList<User> list = new ArrayList<>();
        list.add(new User("Zhang San",21));
        list.add(new User("Li Si",22));
        list.add(new User("Wang Wu",23));
        list.add(new User("Ma Liu",20));
        list.add(new User("Ma Liu",20));
        //Intermediate operations 1. filter 2. limit 3. skip 4. distinct de duplication 5. sorted sorting
        System.out.println("-------filter filter");
                .filter(e -> e.getAge() > 22)
        System.out.println("-------limit limit");
        System.out.println("-------skip skip");
        System.out.println("-------distinct duplicate removal");
        System.out.println("-------sorted sort");
        System.out.println("---Intermediate operation 2  map");

Terminate operation



import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

public class Demo5 {
    public static void main(String[] args) {
        ArrayList<User> list = new ArrayList<>();
        list.add(new User("Zhang San",21));
        list.add(new User("Li Si",22));
        list.add(new User("Wang Wu",23));
        list.add(new User("Ma Liu",20));
        Optional<User> min = list.stream()
        System.out.println(min.get() );
        Optional<User> max = list.stream()
        long count = list.stream().count();
        System.out.println("Number of persons:"+count);
        Optional<Integer> reduce = list.stream()
        System.out.println("Sum of ages:"+reduce);
        List<String> collect = list.stream()

Date formatting problem

We know that SimpleDateFormat is thread unsafe

Then in Java 8, we can use DateTimeFormatter

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;

public class Demo6 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd");
        ExecutorService pool = Executors.newFixedThreadPool(10);
        Callable<LocalDate> callable = new Callable<LocalDate>() {
            public LocalDate call() throws Exception {
                return LocalDate.parse("20210602",dtf);

        List<Future<LocalDate>> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            Future<LocalDate> future = pool.submit(callable);
        for (Future<LocalDate> future:list) {

Posted on Sat, 23 Oct 2021 20:57:32 -0400 by mo0ness