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; consumer.accept("Beijing"); //Class:: static method Comparator<Integer> comparator = Integer::compare; System.out.println(comparator.compare(1,2)); //Class:: instance method Function<User,String> f = User::getUserName; System.out.println(f); //Class:: new Supplier<User> user = User::new; System.out.println(user.get()); } }
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<>(); list.add("Beijing"); list.add("Wuhan"); list.add("Nanjing"); Stream<String> stream = list.stream(); stream.forEach(System.out::println); //Through the stream() method of the Arrays class String[] arr = {"a","b","c"}; Stream<String> stream1 = Arrays.stream(arr); stream1.forEach(System.out::println); //Through the of(), iterate(), generate() methods of the Stream interface Stream<Integer> integerStream = Stream.of(10, 20, 30); integerStream.forEach(System.out::println); System.out.println("=========Iterative flow"); Stream<Integer> iterate = Stream.iterate(0, x -> x + 2); iterate.limit(3).forEach(System.out::println); System.out.println("========Generate flow"); Stream<Integer> generate = Stream.generate(() -> new Random().nextInt(10)); generate.limit(4).distinct().forEach(System.out::println); //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); System.out.println(intStream.max()); range.forEach(System.out::println); System.out.println("--------rangeClosed"); rangeClosed.forEach(System.out::println); } }
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; } @Override public String toString() { return "User{" + "userName='" + userName + '\'' + ", age=" + age + '}'; } @Override 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); } @Override 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"); list.stream() .filter(e -> e.getAge() > 22) .forEach(System.out::println); System.out.println("-------limit limit"); list.stream() .limit(2) .forEach(System.out::println); System.out.println("-------skip skip"); list.stream() .skip(2) .forEach(System.out::println); System.out.println("-------distinct duplicate removal"); list.stream() .distinct() .forEach(System.out::println); System.out.println("-------sorted sort"); list.stream() .sorted(Comparator.comparingInt(User::getAge)) .forEach(System.out::println); System.out.println("---Intermediate operation 2 map"); list.stream() .map(User::getUserName) .forEach(System.out::println); } }
Terminate operation
forEach,min,max,count
reduce,collect
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)); System.out.println("------min"); Optional<User> min = list.stream() .min(Comparator.comparingInt(User::getAge)); System.out.println(min.get() ); System.out.println("------max"); Optional<User> max = list.stream() .max(Comparator.comparingInt(User::getAge)); System.out.println(max.get()); System.out.println("------count"); long count = list.stream().count(); System.out.println("Number of persons:"+count); System.out.println("----reduce"); Optional<Integer> reduce = list.stream() .map(User::getAge) .reduce(Integer::sum); System.out.println("Sum of ages:"+reduce); System.out.println("-------collect"); List<String> collect = list.stream() .map(User::getUserName) .collect(Collectors.toList()); collect.forEach(System.out::println); } }
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>() { @Override 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); list.add(future); } for (Future<LocalDate> future:list) { System.out.println(future.get()); } pool.shutdown(); } }