JDK 8以上新特性
2023-05-10 21:58:36 13 举报
AI智能生成
jdk 8 以上新特性
作者其他创作
大纲/内容
方法与构造方法引用 ::
语法
左边 容器(类名/实例名):: 右边对应的方法名
Student::getAge
Lambda 表达式
本质:匿名内部类
函数式接口: 1> Consumer<T> :消费型接口 void accept(T t);
2> Supplier<T> :供给型接口 T get();
3> Function<T,R> :函数型接口 R apply(T t);
4> Predicate<T> :断言型接口 boolean test(T t);
() -> {}:用lambda表达式实现Runnable
new Thread( () -> System.out.println("In Java8, Lambda expression rocks !!") ).start();
(T) ->{}; 使用Java 8 lambda表达式进行事件处理
show.addActionListener((e) -> {
System.out.println("Light, Camera, Action !! Lambda expressions Rocks");
});
forEach() 使用lambda表达式对列表进行迭代
List features = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API");
features.forEach(n -> System.out.println(n));
filter() 使用lambda表达式和函数式接口Predicate
Predicate<String> startsWithJ = (n) -> n.startsWith("J");
Predicate<String> fourLetterLong = (n) -> n.length() == 4;
names.stream()
.filter(startsWithJ.and(fourLetterLong))
.forEach((n) -> System.out.print("nName, which starts with 'J' and four letter long is : " + n));
map() Java 8中使用lambda表达式的Map
List costBeforeTax = Arrays.asList(100, 200, 300, 400, 500);
costBeforeTax.stream().map((cost) -> cost + .12*cost).forEach(System.out::println);
reduce() Java 8中使用lambda表达式的Reduce
List costBeforeTax = Arrays.asList(100, 200, 300, 400, 500);
double bill = costBeforeTax.stream().map((cost) -> cost + .12*cost).reduce((sum, cost) -> sum + cost).get();
计算集合元素的最大值、最小值、总和以及平均值
List<Integer> primes = Arrays.asList(2, 3, 5, 7, 11, 13, 17, 19, 23, 29);
IntSummaryStatistics stats = primes.stream().mapToInt((x) -> x).summaryStatistics();
集合框架 stream 流的使用
of 函数 快速创建 stream
Stream.of(1,2,3,4).collect(Collectors.toList());
map 函数 将流中的每一个元素映射成R(类似 类型转换)
List<String> list = Arrays.asList("aaa","bbb","ccc");
List<String> lists =
list.stream().map(x ->"集合"+x).collect(Collectors.toList());
filter 函数 通过设置条件过滤元素
获取 a 开头的元素
List<String> list = Arrays.asList("aaa","bbb","ccc");
list.stream().filter(x ->x.startsWith("a")).collect(Collectors.toList());
sorted 函数 排序 默认升序
list.stream().sorted().collect(Collectors.toList());
降序排序
list.stream()
.sorted(Comparator.comparing(y ->y.length(),Comparator.reverseOrder()))
.collect(Collectors.toList());
list.stream()
.sorted(Comparator.comparing(String::length)
.reversed()).collect(Collectors.toList());
limit 函数 截断流
获取排第一的元素
list.stream().limit(1).collect(Collectors.toList());
allmatch 和 anymatch 函数
anymatch 全匹配 List<String> list = Arrays.asList("x","aaa","bbb");
Boolean flag = list.stream().allMatch(x ->x.length()>2);
anymatch 部分匹配 List<String> list = Arrays.asList("x","aaa","bbb");
Boolean flag = list.stream().anyMatch(x ->x.length()>2);
max 和 min 函数的使用
//取最长没有返回“”
List<String> list = Arrays.asList("x","aaaa","bbb");
String maxlenth = list.stream().max(Comparator.comparing(String::length)).orElse("");
//取最短 没有返回“”
List<String> list = Arrays.asList("x","aaaa","bbb");
String minlenth = list.stream().min(Comparator.comparing(String::length)).orElse("");
parallelStream 并行流的使用
注意点:
1、并行流不一定比串行流速度快 看处理的数量一般万条数据不推荐使用
原因:forkjoin框架需要时间进行任务分配
2、不是数据量大就一定使用并行流 要考虑线程安全问题 需要使用线程安全的集合
for(int i=0;i<100;i++){
List list1 = new CopyOnWriteArrayList();
IntStream.range(0,100).parallel().forEach(list1::add);
System.out.println(list1.size());
} 这里不能使用arraylist 因为是线程不安全的 没有共用list
list.parallelStream().forEach(System.out::println);
list 一般不会存储 几万几十万对象 因为JVM内存,可能OOM(内存溢出),所以一般是几个到几十个所以这里推荐使用串行流
reduce 聚合函数的使用
源码:Optional<T> reduce(BinaryOperator<T> accumulator);
求和: Integer i = Stream.of(1,2,3,4,5).reduce((x,b)->x+b).orElse(0);
比较大小取最大值 : Integer i = Stream.of(1,2,3,4,5).reduce((x,b)->x>b?x:b).orElse(0);
foreach 遍历函数
源码:default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
list.forEach(System.out::println);
注意点:
1、不能修改循环外部的变量值
2、不能使用break、return、continue等结束和跳过循环
收集器和集合统计
collect 收集方法
List<Integer> integerList = Stream.of(1,2,3,4).collect(Collectors.toList());
Set<String> stringSet = list.stream().collect(Collectors.toCollection(TreeSet::new));
list.stream().collect(Collectors.toSet());
joining 函数
源码:
无参 public static Collector<CharSequence, ?, String> joining() {
return new CollectorImpl<CharSequence, StringBuilder, String>(
StringBuilder::new, StringBuilder::append,
(r1, r2) -> { r1.append(r2); return r1; },
StringBuilder::toString, CH_NOID);
}
带参:
public static Collector<CharSequence, ?, String> joining(CharSequence delimiter) {
return joining(delimiter, "", "");
}
带三个参数:
public static Collector<CharSequence, ?, String> joining(CharSequence delimiter,
CharSequence prefix,
CharSequence suffix) {
return new CollectorImpl<>(
() -> new StringJoiner(delimiter, prefix, suffix),
StringJoiner::add, StringJoiner::merge,
StringJoiner::toString, CH_NOID);
}
把所有字符串拼接在一起
List<String> list = Arrays.asList("x","aaaa","bbb");
String stringSet = list.stream().collect(Collectors.joining());
以“_”分隔符 连接 String stringSet = list.stream().collect(Collectors.joining("_"));
单词用双引号 并以“_”分割 String stringSet = list.stream().collect(Collectors.joining("_","\"","\""));
partitioningBy 函数 条件分组
源码:
public static <T> Collector<T, ?, Map<Boolean, List<T>>> partitioningBy(Predicate<? super T> predicate) {
return partitioningBy(predicate, toList());
}
public static <T> Collector<T, ?, Map<Boolean, List<T>>> partitioningBy(Predicate<? super T> predicate) {
return partitioningBy(predicate, toList());
}
Map<Boolean,List<Integer>> result = Stream.of(1,2,3)
.collect(Collectors.partitioningBy(obj ->obj.intValue()>2));
结果:{false=[1, 2], true=[3]}
groupingBy 分组函数
源码:
public static <T, K> Collector<T, ?, Map<K, List<T>>>
groupingBy(Function<? super T, ? extends K> classifier) {
return groupingBy(classifier, toList());
}
List<Student> list = Arrays.asList(new Student("北京","22"),
new Student("南京","23"),new Student("上海","20"),new Student("北京","21"));
根据省份分组 : Map<String,List<Student> students> map = list.stream().collect(Collectors.groupingBy(x ->x.getProvince()));
counting 分组进阶 统计
源码:
public static <T> Collector<T, ?, Long>
counting() {
return reducing(0L, e -> 1L, Long::sum);
}
List<Student> list = Arrays.asList(new Student("北京","22"),
new Student("南京","23"),new Student("上海","20"),new Student("北京","21"));
Map<String,Long> map = list.stream()
.collect(Collectors.groupingBy(obj->obj.getProvince(),Collectors.counting()));
结果: {上海=1, 南京=1, 北京=2}
summarizing 统计函数
summarizingInt
源码:
public static <T>
Collector<T, ?, IntSummaryStatistics> summarizingInt(ToIntFunction<? super T> mapper) {
return new CollectorImpl<T, IntSummaryStatistics, IntSummaryStatistics>(
IntSummaryStatistics::new,
(r, t) -> r.accept(mapper.applyAsInt(t)),
(l, r) -> { l.combine(r); return l; }, CH_ID);
}
List<Student> list = Arrays.asList(new Student("北京",22),
new Student("南京",23),new Student("上海",21),new Student("北京",24));
IntSummaryStatistics statistics = list.stream()
.collect(Collectors.summarizingInt(Student::getAge));
System.out.println("最大值"+statistics.getMax());
System.out.println("最小值"+statistics.getMin());
System.out.println("平均值"+statistics.getAverage());
System.out.println("总和"+statistics.getSum());
System.out.println("总数"+statistics.getCount());
summarizingDouble
summarizingLong
小小思维练习
求两集合的交集
注: 对比较对象的equals、hashcode方法重写 否则比较结果错误 打印问题重 写tostring
List<VideoOrder> list1 = Arrays.asList(new VideoOrder("2019110601",21,"springboot教程"),
new VideoOrder("2019110602",23,"redis 教程"),
new VideoOrder("2019110603",21,"sql教程"));
List<VideoOrder> list2 = Arrays.asList(new VideoOrder("2019110601",21,"springcloud教程"),
new VideoOrder("2019110602",23,"netty 教程"),
new VideoOrder("2019110603",21,"sql教程"));
Stream<VideoOrder> orderStream = list1.stream().filter(list2::contains);
@Override
public int hashCode() {
return title.hashCode();
}
@Override
public boolean equals(Object obj) {
if(obj instanceof VideoOrder){
return ((VideoOrder) obj).title.equals(this.title);
}
return super.equals(obj);
}
List<VideoOrder> list1 = Arrays.asList(new VideoOrder("2019110601",21,"springboot教程"),
new VideoOrder("2019110602",23,"redis 教程"),
new VideoOrder("2019110603",21,"sql教程"));
List<VideoOrder> list2 = Arrays.asList(new VideoOrder("2019110601",21,"springcloud教程"),
new VideoOrder("2019110602",23,"netty 教程"),
new VideoOrder("2019110603",21,"sql教程"));
Stream<VideoOrder> orderStream = list1.stream().filter(list2::contains);
@Override
public int hashCode() {
return title.hashCode();
}
@Override
public boolean equals(Object obj) {
if(obj instanceof VideoOrder){
return ((VideoOrder) obj).title.equals(this.title);
}
return super.equals(obj);
}
求两集合的差集
//交集
List<VideoOrder> videoOrders = list1.stream().filter(list2::contains).collect(Collectors.toList());
//差集
List<VideoOrder> orders = list1.stream().filter(obj -> !list2.contains(obj)).collect(Collectors.toList());
求两集合的并集
List<VideoOrder> collect = list1.parallelStream().collect(Collectors.toList());
collect.addAll(list2);
求两集合的去重并集
List<VideoOrder> collect = list1.parallelStream().collect(Collectors.toList());
collect.addAll(list2);
List<VideoOrder> distinct = collect.parallelStream().distinct().collect(Collectors.toList());
求两集合平均值
金额平均值: Double aDouble = list1.stream().collect(Collectors.averagingInt(VideoOrder::getMoney));
求两集合的某属性和
long sum = list1
.stream().collect(Collectors.summarizingInt(VideoOrder::getMoney)).getSum();
Integer final collect1 = list1
.stream().collect(Collectors.summingInt(VideoOrder::getMoney));
JDK 9的一些新特性
工具 jshell
接口新增私有方法
接口新增私有方法:jdk 8新增 静态+默认方法 静态方法是不能被实现类或接口继承的 而9中private方法也不能
public interface testjdk {
void fun();
private void fun3(){
}
}
注意:(面试题)<br>
==接口中的静态方法不能被实现类或子接口继承非静态的default方法可以<br>
类中的静态方法可以被继承==
jdk 9的增强 try-with-resource
可以在外部声明 会自动关闭流
```
void test(String filePath) {
OutputStream out1 = new FileOutputStream(filePath);
OutputStream out2 = new FileOutputStream(filePath);
try (out1;out2){
outputStream.write("测试输出流".getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
jdk 9 之快速创建只读集合
1、什么叫只读集合? —— 只能读取不能写入或删除元素
旧写法:<br>
```
List<VideoOrder> list1 = Arrays.asList(new VideoOrder("2019110601",21,"springboot教程"),
new VideoOrder("2019110602",23,"redis 教程"),
new VideoOrder("2019110603",21,"sql教程"));
//设置只读
Collections.unmodifiableList(list);
```
新写法:<br>
```
List<String> list3 = List.of("springboot","MySQL","Redis");
list3是无法修改的
或者使用
Collections.unmodifiableList(list);
JDK 10,11的新特性
jdk 10增加局部变量推断 var
```
for(var i =0;i<10;i++){
}
for(var obj:list){
}
var flag = Boolean.valueOf("true");
注:仅适用于局部变量,如增强for循环索引 传统for循环局部变量<br>
不能作为方法形参,构造方法形参,方法返回类型 或者任何类型的变量声明<br>
标识符var不是关键字 只是一个保留类型名称<br>
jdk 11新增 HttpClient 客户端
文件流异常处理 try-with-resource (jdk 7的新特性)
旧写法:
private static void test(String filepath) {
OutputStream outputStream = new FileOutputStream(filepath);
try {
outputStream.write("测试输出流".getBytes());
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
新写法:
private static void test(String filepath) {
try ( OutputStream outputStream = new FileOutputStream(filepath);){
outputStream.write("测试输出流".getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
原因: OutputStream 实现了自动关闭流
public interface Closeable extends AutoCloseable {}
public abstract class OutputStream implements Closeable, Flushable {}
*新内存空间 Matespace(只有Hotspot版本虚拟机有此新特性)
虚拟机类别 版本
oracle-Sun Hotspot、oracle jrockit、IBM J9、Taobao JVM
虚拟机方面 OON 永久代空间问题
Java.lang.OutOfMemoryError:PermGen space 永久空间不够 类太多导致 内存空间不够
原因:
JDK 8之前的永久空间 用来存储class和mate信息 而永久空间大小不仅和内存大小有关 还需要使用指令XX:MaxPermSize 来设定这块区域大小
修复:
JDK 8取消了 永久代空间 使用了本地内存存储元数据信息 所以默认matespace 大小和本地内存大小有关 初始值 是 20.8M 大小
一些关于元数据查询命令
查询 Java程序大小
jstat -gc pid Linux命令
MC: matespace capatity 总大小
MU:matespace utilization 已使用大小
Optional类
of(T values); values not null
Optional<T > optionalInteger = Optional.of(T value);
源码分析:
public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}
ofNullable(T value);value nullable
Optional<Integer> optionalInteger = Optional.ofNullable(integer);
源码分析: public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
public static<T> Optional<T> empty() {
@SuppressWarnings ("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
private static final Optional<?> EMPTY = new Optional<>();
访问opt对象的值 get();
Optional<T > optionalInteger = Optional.of(T value);
Integer integer1 = optionalInteger.get();
源码分析:
public T get() {
if (value == null) {
throw new NoSuchElementException("No value present");
}
return value;
}
兜底方法 orElse(T valu);
Integer integer = null;
Integer integer1 = 1;
Integer i = Optional.ofNullable(integer).orElse(integer1);
student student = null;
Integer i = Optional.ofNullable(student).map(obj ->obj::getage())).orElse(6);
如果map获取对象数值失败 则获取orelse()兜底数据 6
源码分析:
public T orElse(T other) {
return value != null ? value : other;
}
isPresent 判断是否为空方法
List<VideoOrder> list1 = Arrays.asList(new VideoOrder("2019110601",21,"springboot教程"),
new VideoOrder("2019110602",23,"redis 教程"));
final boolean present = Optional.ofNullable(list1).isPresent();
源码分析:
public boolean isPresent() {
return value != null;
}
ifPresent 如果是空
List<VideoOrder> list1 = Arrays.asList(new VideoOrder("2019110601",21,"springboot教程"),
new VideoOrder("2019110602",23,"redis 教程"));
Optional.ofNullable(list1).ifPresent(x->x.add(new VideoOrder()));
new VideoOrder("2019110602",23,"redis 教程"));
Optional.ofNullable(list1).ifPresent(x->x.add(new VideoOrder()));
源码分析:
public void ifPresent(Consumer<? super T> consumer) {
if (value != null)
consumer.accept(value);
}
时间处理类
LocalDate
LocalDateTime
LocalDateTime localDateTime = LocalDateTime.now(); 实例化
String localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:MM:SS")); 格式化
int month = localDateTime.getDayOfMonth();
DayOfWeek week = localDateTime.getDayOfWeek();
int year = localDateTime.getDayOfYear();
int hour = localDateTime.getHour();
int minute = localDateTime.getMinute();
将LocalDateTime转为自定义的时间格式的字符串
public static String getDateTimeAsString(LocalDateTime localDateTime, String format) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);
return localDateTime.format(formatter);
}
将long类型的timestamp转为LocalDateTime
public static LocalDateTime getDateTimeOfTimestamp(long timestamp) {
Instant instant = Instant.ofEpochMilli(timestamp);
ZoneId zone = ZoneId.systemDefault();
return LocalDateTime.ofInstant(instant, zone);
}
将LocalDateTime转为long类型的timestamp
public static long getTimestampOfDateTime(LocalDateTime localDateTime) {
ZoneId zone = ZoneId.systemDefault();
Instant instant = localDateTime.atZone(zone).toInstant();
return instant.toEpochMilli();
}
将某时间字符串转为自定义时间格式的LocalDateTime
public static LocalDateTime parseStringToDateTime(String time, String format) {
DateTimeFormatter df = DateTimeFormatter.ofPattern(format);
return LocalDateTime.parse(time, df);
}
LocalTime
新增 base 64加解密API
Base64.Encode encode = Base64.getEncode(); 加密
Base64.Decode Decode = Base64.getDecode(); 解密
接口加入 default 关键字
接口内部可以有default方法实现
hashmap 新结构
旧版本结构
*HashMap的底层实现是一个哈希表即数组+链表;
*HashMap初始容量大小16,扩容因子为0.75,扩容倍数为2;
HashMap本质是一个一定长度的数组,数组中存放的是链表。
新版本结构
由此可以看出 hash由原来的hash数组+链表变成了 数组+红黑树 和链表混合模式
但是实际应用是不存在这种情况的 因为hashmap早就扩容了
0 条评论
下一页