Lambda表达式
Lambda表达式允许将函数作为方法的参数,将代码像数据一样传递。
基本语法
<函数式接口> <变量名> = (参数1,参数2...) -> {
//方法体
};
以下是lambda表达式的重要特征:
- 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
- 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
- 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
- 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。
如果一个接口只有一个抽象方法,则该接口称为函数式接口。
可以使用@FunctionalInterface注解来检测是否为函数式接口
常见的函数式接口
用Consumer举个例子:
方法引用
方法引用是Lambda表达式的一种简写形式,如果Lambda表达式方法体中只是调用一个特定的已经存在的方法,则可以使用方法引用。
常见的形式:
对象::实例方法
类::静态方法
类::实例方法
类::new
public class Demo2 {
public static void main(String[] args) {
//对象::实例方法
Consumer<String> consumer = System.out::println;
consumer.accept("北京");
//类::静态方法
Comparator<Integer> comparator = Integer::compare;
System.out.println(comparator.compare(1,2));
//类::实例方法
Function<User,String> f = User::getUserName;
System.out.println(f);
//类::new
Supplier<User> user = User::new;
System.out.println(user.get());
}
}
Stream流
什么是Stream
流中保存对集合或者数组的操作,和集合类似,但是集合中保存的是数据,Stream中保存的是操作。就像工厂里的机械流水线。
Stream的特点:
- Stream自己不会存储元素
- Stream不会改变源对象,相反,它会返回一个持有结果的新Stream
- Stream的操作是延迟执行的,这就意味着它会等到需要结果的时候才执行
创建Stream
- 通过Collection对象的Stream()或parallelStream
- 通过Arrays类的stream()方法
- 通过Stream接口的of()、iterate()、generate()方法
- 通过IntStream、LongStream、DoubleStream接口中的of、range、rangeClosed方法
public class Demo3 {
public static void main(String[] args) {
//通过Collection对象的Stream()或parallelStream
ArrayList<String> list = new ArrayList<>();
list.add("北京");
list.add("武汉");
list.add("南京");
Stream<String> stream = list.stream();
stream.forEach(System.out::println);
//通过Arrays类的stream()方法
String[] arr = {"a","b","c"};
Stream<String> stream1 = Arrays.stream(arr);
stream1.forEach(System.out::println);
//通过Stream接口的of()、iterate()、generate()方法
Stream<Integer> integerStream = Stream.of(10, 20, 30);
integerStream.forEach(System.out::println);
System.out.println("=========迭代流");
Stream<Integer> iterate = Stream.iterate(0, x -> x + 2);
iterate.limit(3).forEach(System.out::println);
System.out.println("========生成流");
Stream<Integer> generate = Stream.generate(() -> new Random().nextInt(10));
generate.limit(4).distinct().forEach(System.out::println);
//通过IntStream、LongStream、DoubleStream接口中的of、range、rangeClosed方法
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);
}
}
中间操作
User类
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流中间操作
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("张三",21));
list.add(new User("李四",22));
list.add(new User("王五",23));
list.add(new User("马六",20));
list.add(new User("马六",20));
//中间操作 1、filter过滤 2、limit 3、skip 4、distinct 去重 5、sorted排序
System.out.println("-------filter过滤");
list.stream()
.filter(e -> e.getAge() > 22)
.forEach(System.out::println);
System.out.println("-------limit限制");
list.stream()
.limit(2)
.forEach(System.out::println);
System.out.println("-------skip跳过");
list.stream()
.skip(2)
.forEach(System.out::println);
System.out.println("-------distinct去重");
list.stream()
.distinct()
.forEach(System.out::println);
System.out.println("-------sorted排序");
list.stream()
.sorted(Comparator.comparingInt(User::getAge))
.forEach(System.out::println);
System.out.println("---中间操作2 map");
list.stream()
.map(User::getUserName)
.forEach(System.out::println);
}
}
终止操作
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("张三",21));
list.add(new User("李四",22));
list.add(new User("王五",23));
list.add(new User("马六",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("人数:"+count);
System.out.println("----reduce");
Optional<Integer> reduce = list.stream()
.map(User::getAge)
.reduce(Integer::sum);
System.out.println("年龄之和:"+reduce);
System.out.println("-------collect");
List<String> collect = list.stream()
.map(User::getUserName)
.collect(Collectors.toList());
collect.forEach(System.out::println);
}
}
日期格式化问题
我们知道SimpleDateFormat是线程不安全的
那么在java8中我们可以使用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();
}
}