Java8
1、Lambda 表达式
- 概念描述
Lambda 是一个匿名函数, 我们可以把 Lambda表达式理解为是一段可以传递的代码 。
- 语法表达式
类型推断:Lambda 表达式中无需指定类型, 程序依然可以编译, 这是因为 javac 根据程序的上下文, 在后台推断出了参数的类型。 Lambda 表达式的类型依赖于上下文环境, 是由编译器推断出来的。
2、函数式接口
- Java 四大核心函数式接口
3. 方法与构造器引用
4 Stream API
- Stream 操作的三个步骤
创建Stream -> 中间操作 -> 终止操作
package con.andrew.demo.java8;
import com.sun.org.apache.xpath.internal.operations.Bool;
import con.andrew.demo.domain.Employee;
import con.andrew.demo.domain.Person;
import java.lang.reflect.Field;
import java.time.Duration;
import java.time.Instant;
import java.util.*;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.stream.Collectors;
import java.util.stream.LongStream;
import java.util.stream.Stream;
/**
* 中间操作
*
* 筛选与切片
*
* <p> filter 接收 lambda ,从流中过滤某些元素
* limit 截取流,使其元素不超过指定数量
* skip 跳过元素,返回一个扔掉前 n 个元素的流。若流中元素不足 n 个,则返回一个空流
* distinct 筛选,通过流所生成的元素 hasCode 和 equal 去除重复元素
*
*
* 映射
* map 接收 lambda ,将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被映射到每个元素上,并将其映射成一个新的元素
* flatMap 接收一个函数作为参数,将流中的每个值转换为另一个流,再拼接所有流
*
* 排序
* sorted() 自然排序
* sorted(comparator com) 定制排序
*
* 查找与匹配
* allMatch 检查是否匹配所有元素
* anyMatch 检查是否至少匹配一个元素
* noneMatch 检查是否没有匹配所有元素
* findFirst 返回第一个元素
* findAny 返回当前流中的任意元素
* count 返回流中元素的总个数
* max 返回流中最大值
* min 返回流中最小值
*
* 规约
* reduce(T identity, BinaryOperator) / reduce(BinaryOperator) 将流中元素反复结合起来,得到一个值
*
* 收集
* collect 将流转换为其他形式,接收一个 Collector 接口的实现,用于给 Stream 中元素汇总的方法
*/
public class StreamStudy {
List<Employee> employees = Arrays.asList(
new Employee("andrew", 18, "man"),
new Employee("tom", 12, "man"));
/**
* 内部迭代
*/
public void demo01() {
Stream<Employee> stream = employees.stream()
.filter(e -> {
System.out.println("中间操作");
return e.getAge() > 10;
});
stream.forEach(System.out::println);
}
/**
* 外部迭代
*/
public void demo02() {
Iterator<Employee> iterator = employees.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
/**
* 字符串装箱
*
* @param str 输入字符串
* @return 字符集合
*/
public static Stream<Character> filterCharacter(String str) {
List<Character> list = new ArrayList<>();
for (Character character : str.toCharArray()) {
list.add(character);
}
return list.stream();
}
/**
* 映射
*/
public void demo03() {
List<String> list = Arrays.asList("aaa", "bbb", "ccc", "ddd");
// {{a, a, a}, {b, b, b}, {c, c, c}}
Stream<Stream<Character>> stream1= list.stream().map(StreamStudy::filterCharacter);
stream1.forEach(stream -> {stream.forEach(System.out::println);});
System.out.println("------------------------");
// {a, a, a, b, b, b, c, c, c}
Stream<Character> stream2 = list.stream().flatMap(StreamStudy::filterCharacter);
stream2.forEach(System.out::println);
}
/**
* 排序
*/
public void demo04() {
List<String> list = Arrays.asList("aaa", "bbb", "ccc", "ddd");
list.stream()
.sorted()
.forEach(System.out::println);
System.out.println("=================");
employees.stream()
.sorted((e1, e2) -> {
if (e1.getAge() == e2.getAge()) {
return e1.getName().compareTo(e2.getName());
} else {
return Integer.compare(e1.getAge(), e2.getAge());
}
}).forEach(System.out::println);
}
/**
* 规约操作
*/
public void demo05() {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 0);
// 无累加初始值
Optional<Integer> sum1 = list.stream().reduce((x, y) -> x + y);
System.out.println(sum1.get());
// 有累加初始值
Integer sum2 = list.stream().reduce(10, (x, y) -> x + y);
System.out.println(sum2);
// 并行流
String sum3 = Stream.of(1, 2, 3).parallel().reduce(String.valueOf("1"),
(acc, i) -> String.valueOf(Integer.valueOf(acc)) + i,
(acc1, acc2) -> String.valueOf(Integer.valueOf(acc1) + Integer.valueOf(acc2)));
System.out.println(sum3);
}
/**
* 收集
*/
public void demo06() {
// 转换为 list
List<String> list = employees.stream().map(Employee::getName).collect(Collectors.toList());
// 总数
Long count = employees.stream().collect(Collectors.counting());
// 平均值
Double avg = employees.stream().collect(Collectors.averagingDouble(Employee::getAge));
// 总和
Double sum = employees.stream().collect(Collectors.summingDouble(Employee::getAge));
// 最大值
Optional<Employee> max = employees.stream().collect(Collectors.maxBy((e1, e2) -> Integer.compare(e1.getAge(), e2.getAge())));
// 最小值
Optional<Employee> min = employees.stream().collect(Collectors.minBy((e1, e2) -> Integer.compare(e1.getAge(), e2.getAge())));
// 分组
Map<Integer, List<Employee>> map = employees.stream().collect(Collectors.groupingBy(Employee::getAge));
// TODO 多级分组
// 分区
Map<Boolean, List<Employee>> map1 = employees.stream().collect(Collectors.partitioningBy(e -> e.getAge() > 10));
// 整合运算资源
DoubleSummaryStatistics doubleSummaryStatistics = employees.stream().collect(Collectors.summarizingDouble(Employee::getAge));
// 连接符
String str = employees.stream().map(Employee::getName).collect(Collectors.joining("==="));
}
/**
* 并行流
*/
public void demo07() {
// 获取当前时间
Instant start = Instant.now();
ForkJoinPool pool = new ForkJoinPool();
ForkJoinTask<Long> task = new ForkJoinCalculate(0, 100000000L);
Long sum = pool.invoke(task);
Instant end = Instant.now();
System.out.println("结果:" + sum + "耗时:" + Duration.between(start, end).toMillis());
System.out.println("============并行流==========");
LongStream.rangeClosed(0, 1000000000L).parallel().reduce(0, Long::sum);
}
5. 并行流与串行流
并行流就是把一个内容分成多个数据块, 并用不同的线程分别处理每个数据块的流。
Stream API 可以声明性地通过 parallel() 与 sequential() 在并行流与顺序流之间进行切换
- Fork / Join 框架
6. 时间API
LocalDate、 LocalTime、 LocalDateTime 类的实例是不可变的对象, 分别表示使用 ISO-8601日历系统的日期、 时间、 日期和时间。 它们提供了简单的日期或时间, 并不包含当前的时间信息。 也不包含与时区相关的信息。
package con.andrew.demo.java8;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjuster;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
/**
* Optional 容器类
*
* 接口允许有默认方法与静态方法
*
* 安全时间类
*
* TemporalAdjuster 时间校正器
*
*/
public class OtherFeature {
/**
* 安全时间类
*
* @throws ExecutionException 执行异常
* @throws InterruptedException 线程暂停异常
*/
public void demo01() throws ExecutionException, InterruptedException {
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyMMdd");
Callable<LocalDate> task = new Callable<LocalDate>() {
@Override
public LocalDate call() throws Exception {
return LocalDate.parse("20220723", dateTimeFormatter);
}
};
ExecutorService executorService = Executors.newFixedThreadPool(10);
List<Future<LocalDate>> results = new ArrayList<>();
for (int i = 0; i < 10; i++) {
results.add(executorService.submit(task));
}
for (Future<LocalDate> future : results) {
System.out.println(future.get());
}
}
/**
* 获取两个日期之间的间隔
*/
public void demo02() {
// LocalDate LocalTime LocalDateTime
// Instant 默认获取 UTC 时区
Instant instant = Instant.now();
System.out.println(instant);
// 获取两个时间的间隔
Instant instant1 = Instant.now();
Instant instant2 = Instant.now();
Duration between = Duration.between(instant1, instant2);
System.out.println(between);
// 获取两个日期之间的间隔
LocalDate localDate1 = LocalDate.of(2022, 10, 10);
LocalDate localDate2 = LocalDate.now();
Period period = Period.between(localDate1, localDate2);
System.out.println(period);
}
/**
* 时间校正器
*/
public void demo03() {
LocalDateTime localDateTime1 = LocalDateTime.now();
System.out.println(localDateTime1);
LocalDateTime localDateTime2 = localDateTime1.withDayOfMonth(10);
System.out.println(localDateTime2);
LocalDateTime localDateTime3 = localDateTime1.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
System.out.println(localDateTime3);
// 自定义:下一个工作日
LocalDateTime localDateTime5 = localDateTime1.with( localDateTime -> {
LocalDateTime localDateTime4 = (LocalDateTime) localDateTime;
DayOfWeek dayOfWeek = localDateTime4.getDayOfWeek();
if (dayOfWeek.equals(DayOfWeek.FRIDAY)) {
return localDateTime4.plusDays(3);
} else if (dayOfWeek.equals(DayOfWeek.SATURDAY)) {
return localDateTime4.plusDays(2);
} else {
return localDateTime4.plusDays(1);
}
});
System.out.println(localDateTime5);
}
/**
* 时间格式化
*/
public void demo04() {
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ISO_DATE;
LocalDateTime localDateTime = LocalDateTime.now();
String str = dateTimeFormatter.format(localDateTime);
System.out.println(str);
}
/**
* 时区操作
*/
public void demo05() {
LocalDateTime localDateTime = LocalDateTime.now(ZoneId.of("Europe/Tallinn"));
System.out.println(localDateTime);
}
}
7. Instant 时间戳
- Duration:用于计算两个“时间” 间隔
- Period:用于计算两个“日期” 间隔