JDK1.8 新特性
记录一些在开发中常用到的一些小案例。
Lamdba 表达式
是一个匿名函数,简化代码书写。
前提:当接口中只有一个需要被实现的方法时,可以使用Lambda表达式来简化书写。
如何简化?
- 这里直接上例子进行对比:
// 匿名内部类
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("inner");
}
}).start();
// lambda 表达式
// ():表示run方法,无参数
// ->:执行
// {}:方法体,要执行的内容
new Thread(() -> {System.out.println("lambda")}).start();
- 再来个例子:
// 匿名内部类
persionEntities.sort(new Comparator<PersionEntity>() {
@Override
public int compare(PersionEntity o1, PersionEntity o2) {
return o1.getAge() - o2.getAge();
}
});
// lamdba
persionEntities.sort((o1, o2) -> {return o1.getAge() - o2.getAge();});
// 当只有一句返回值时,再次简化,省略{}和return语句
// 当只有一个参数时,括号可省略不写
// 当没有参数货参数个数不止一个时,括号不可省略
persionEntities.sort((o1, o2) -> o1.getAge() - o2.getAge());
优点是:极大的简化了重复性代码的书写,提高开发效率;
缺点是:可读性不高,debug的时候不好调试。
接下来将结合Stream流进行讲解。
Stream流
- 常用生成方式:
//集合
List<String> collection = new ArrayList<>();
Stream<String> stream = collection.stream();
//数组
String[] arr = {"a", "b", "c"};
Stream<String> stream1 = Arrays.stream(arr);
//静态方法
Stream<String> stream2 = Stream.of("a", "b");
- 终止操作(转换):
Collection<PersionEntity> collection = new ArrayList<>();
//转换成list
List<PersionEntity> list = collection.stream().collect(Collectors.toList());
//转换成set
Set<PersionEntity> set = collection.stream().collect(Collectors.toSet());
//以id为key,生成map
Map<Long, PersionEntity> map = collection.stream().collect(Collectors.toMap(key -> key.getId(), val -> val, (k1, k2) -> k1));
//通过age分组
Map<Integer, List<PersionEntity>> groupByMap = collection.stream().collect(Collectors.groupingBy(e -> e.getAge()));
- 终止操作(过滤,抽取):
List<Integer> list = Arrays.asList(2,1,3,4,5);
List<List<String>> lists = new ArrayList<>();
lists.add(list);
// 全都不匹配
boolean b2 = list.stream().noneMatch(e -> e.equals(2));
// 全都匹配
boolean b1 = list.stream().allMatch(e -> e.equals(2));
// 任意一个匹配
boolean b = list.stream().anyMatch(e -> e.equals(2));
// 取任意一个元素
Optional<Integer> any = list.stream().findAny();
// 取第一个元素
Optional<Integer> first = list.stream().findFirst();
// 总个数
long count = list.stream().count();
// 最大值
Optional<Integer> max = list.stream().max((k1, k2) -> k1 - k2);
// 最小值
Optional<Integer> min = list.stream().min((k1, k2) -> k1 - k2);
// 计算 (这里算出所有元素的总和)
Optional<Integer> reduce = list.stream().reduce(((e1, e2) -> e1 + e2));
- 终止操作(统计):
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
IntSummaryStatistics statistics = list.stream().mapToInt(e -> e).summaryStatistics();
//list.stream().mapToDouble();
//list.stream().mapToLong();
double average = statistics.getAverage();
long count = statistics.getCount();
int max = statistics.getMax();
int min = statistics.getMin();
long sum = statistics.getSum();
- 中间操作:
// 去重
List<Integer> distinct = list.stream().distinct().collect(Collectors.toList());
// 过滤出大于2的元素
Set<Integer> filter = list.stream().filter(e -> e > 2).collect(Collectors.toSet());
// 取前3个
List<Integer> limit = list.stream().limit(3).collect(Collectors.toList());
// 跳过前3个
List<Integer> skip = list.stream().skip(3).collect(Collectors.toList());
// 映射成新元素
List<Double> tomap = list.stream().map(e -> Double.parseDouble(e.toString())).collect(Collectors.toList());
// 排序
List<Integer> sorted = list.stream().sorted((e1, e2) -> e1 - e2).collect(Collectors.toList());
// 循环遍历输出list中的元素
list.forEach(System.out::println);
// 与forEach不同的是不会截断流,可继续操作流
Stream<String> peek = list.stream().peek(System.out::println);
//将所有流中的元素并到一起连接成一个流
List<String> collect = lists.stream().map(e -> e.stream()).flatMap(e -> e).collect(Collectors.toList());
List<String> collect2 = lists.stream().flatMap(e -> e.stream().filter(k -> k.equals("1"))).collect(Collectors.toList());
- parallelStream流:
parallelStream()与stream()区别是parallelStream()使用多线程去并发遍历,而stream()是单线程。
注意:parallelStream()是线程非安全的。当在循环遍历中进行多次数据库操作时,可以考虑使用提高效率。
默认方法
- JDK1.8为接口新增了默认方法和静态方法:
public interface TestInterface {
default void fun(){
System.out.println("我是一个默认方法!");
}
static void fun(){
System.out.println("我是一个静态方法!");
}
}
默认方法和静态方法无需实现类去实现其方法
Optional 类
可以为null的容器对象,常用于解决空指针异常
PersionEntity persion = null;
// 若传递的对象为null,则抛出 NullPointerException
Optional<PersionEntity> persion1 = Optional.of(persion);
// 允许传递的对象为null 返回 Optional.empty
Optional<PersionEntity> persion2 = Optional.ofNullable(persion);
// 判断值 值存在 返回true 值不存在 返回false
boolean present = persion2.isPresent();
// 如果值存在,则执行()内的语句
persion2.ifPresent(e -> System.out.println(e.getAge()));
// 返回值,值为空时,则抛出 NoSuchElementException
PersionEntity persion5 = persion2.get();
// 值为null时, 返回()中的, 不为null则返回原有的
PersionEntity persion3 = persion2.orElse(new PersionEntity());
// 与orElse 的区别是,当persion2不为空时,orElse会执行()内的代码;而orElseGet不会执行()内的代码
PersionEntity persion4 = persion2.orElseGet(PersionEntity::new);
// 当匹配filter时,正常返回,否则返回 Optional.empty
Optional<PersionEntity> persionEntity = persion2.filter(e -> e.getAge() == 20);
// 值为空时,抛出()中的异常
persion2.orElseThrow(new Supplier<Throwable>() {
@Override
public Throwable get() {
System.out.println("err");
return new RuntimeException();
}
});
日期时间类
- 本地化日期时间(方法太多,这里只列举部分LocalDateTime的,LocalDate和LocalTime用法类似)
//日期时间对象
LocalDateTime now = LocalDateTime.now();
//日期对象
LocalDate localDate = LocalDate.now();
//时间对象
LocalTime localTime = LocalTime.now();
//指定日期时间
LocalDateTime of = LocalDateTime.of(2021, 11, 2, 1, 1);
//指定时区
LocalDateTime asiaNow = LocalDateTime.now(ZoneId.of("Asia/Kolkata"));
//周几
DayOfWeek dayOfWeek = now.getDayOfWeek();
//加一天
LocalDateTime now1 = now.plusDays(1);
//减两个小时
LocalDateTime now2 = now1.minusHours(2);
//时间比较
boolean before = now1.isBefore(now2);
// LocalDate, LocalDateTime , LocalTime 之间的转换
LocalDate localDate1 = now.toLocalDate();
LocalTime localTime1 = now.toLocalTime();
LocalDateTime localDateTime = localDate1.atTime(localTime1);
LocalDateTime localDateTime1 = localTime1.atDate(localDate1);
//格式化
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
//字符串转日期
LocalDateTime parse = LocalDateTime.parse("2021-08-08 12:12:12", df);
//日期转字符串
String format = now.format(df);
好了,暂时想到的就这么多了,其他后续想到了在补充进去。。。