Java11新特性 - 新加一些实用的API
新的本机不可修改集合API
自从Java9开始,JDK里面为集合(List/Set/Map)都添加了of和copyOf方法,他们可以来创建不可变的集合。
Question1:什么叫做不可变集合?
不能对集合进行添加、删除、替换、排序等操作,否则会报java.lang.UnsupportedOperationException错误。
示例代码:
List<String> list = List.of("aa", "bb", "cc");
list.add("dd");
报错信息:
Exception in thread "main" java.lang.UnsupportedOperationException
at java.base/java.util.ImmutableCollections.uoe(ImmutableCollections.java:71)
at java.base/java.util.ImmutableCollections$AbstractImmutableCollection.add(ImmutableCollections.java:75)
扩展:Arrays.asList()创建的集合也是一个不可变的集合
Question2:of方法与copyOf方法之间的区别
示例代码:
var list1 = List.of("aa", "bb", "cc");
var copy1 = List.copyOf(list1);
System.out.println(list1 == copy1);
//运行结果: true
var list2 = new ArrayList<String>();
var copy2 = List.copyOf(list2);
System.out.println(list2 == copy2);
//运行结果: false
注意:var也是Java11新推出的特性局部变量类型推断,这里面不再赘述。
第一段代码和第二段代码差不多,为什么返回结果不一样呢?我们来看一下他们的源码:
static <E> List<E> of(E e1, E e2, E e3) {
return new ImmutableCollections.ListN<>(e1, e2, e3);
}
static final class ListN<E> extends AbstractImmutableList<E>
implements Serializable {
static final List<?> EMPTY_LIST = new ListN<>();
@Stable
private final E[] elements;
@SafeVarargs
ListN(E... input) {
// copy and check manually to avoid TOCTOU
@SuppressWarnings("unchecked")
E[] tmp = (E[])new Object[input.length]; // implicit nullcheck of input
for (int i = 0; i < input.length; i++) {
tmp[i] = Objects.requireNonNull(input[i]);
}
elements = tmp;
}
@Override
public boolean isEmpty() {
return size() == 0;
}
@Override
public int size() {
return elements.length;
}
@Override
public E get(int index) {
return elements[index];
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
throw new InvalidObjectException("not serial proxy");
}
private Object writeReplace() {
return new CollSer(CollSer.IMM_LIST, elements);
}
}
static <E> List<E> copyOf(Collection<? extends E> coll) {
return ImmutableCollections.listCopy(coll);
}
static <E> List<E> listCopy(Collection<? extends E> coll) {
if (coll instanceof AbstractImmutableList && coll.getClass() != SubList.class) {
return (List<E>)coll;
} else {
return (List<E>)List.of(coll.toArray());
}
}
从源码可以看出,copyOf 方法会先判断来源集合是不是 AbstractImmutableList 类型的,如果是,就直接返回,如果不是,则调用 of 创建一个新的集合。第二段代码因为用的 new 创建的集合,不属于不可变 AbstractImmutableList 类的子类,所以 copyOf 方法又创建了一个新的实例,所以为false。
扩展:使用Set.of()方法创建Set对象时,不可以包含重复数据。
Stream加强
Stream是Java8的新特性,我之前的博客对其进行了详细的介绍:Java8新特性 - Stream API。Java9开始对Stream新增了4个新方法。
增加单个参数构造方法,可为null
在Java8,新建一个值为null的Stream,会报错java.lang.NullPointerException错误。
示例代码:
Stream stream = Stream.of(null);
错误:
Exception in thread "main" java.lang.NullPointerException
at java.util.Arrays.stream(Arrays.java:5004)
at java.util.stream.Stream.of(Stream.java:1000)
错误分析:
查看Stream.of()源码
@SafeVarargs
@SuppressWarnings("varargs") // Creating a stream from an array is safe
public static<T> Stream<T> of(T... values) {
return Arrays.stream(values);
}
public static <T> Stream<T> stream(T[] array) {
return stream(array, 0, array.length);
}
可以看见传入null会被解析为时一个数组对象,会进一步访问它的长度信息,导致了NullPointerException异常。
在Java11中,新增了ofNullable方法,可以传入null。因为无法推断类型,所以返回的值为Object,示例代码如下:
Stream stream = Stream.ofNullable(null);
stream.forEach(System.out::println);
从源码中可以看出,当传入的是一个null时,返回的是一个空的对象。
public static<T> Stream<T> ofNullable(T t) {
return t == null ? Stream.empty()
: StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false);
}
增加 takeWhile 和 dropWhile 方法
takeWhile
首先来看一段示例代码:
Stream<Integer> stream = Stream.of(3, 6, 9, 12, 15);
stream.takeWhile(n -> n % 2 != 0)
.forEach(System.out::println);
第一次看这段代码,可能第一印象就是找出流中的奇数打印出来,但是实际输出为:
3
所以takeWhile方法在计算到n % 2 == 0的时候就终止了,takeWhile方法的作用是:从流中一直获取判定器为真的元素,一旦遇到元素为假,就终止处理!
dropWhile
与上面takeWhile一样的代码:
Stream<Integer> stream = Stream.of(3, 6, 9, 12, 15);
stream.dropWhile(n -> n % 2 != 0)
.forEach(System.out::println);
返回的结果为:
6
9
12
15
结果正好与takeWhile相反,dropWhile方法的作用为:只要判定器为真,就一直丢弃元素,直到为假,取为假后的所有元素!
iterate重载
流的迭代,主要用于创建流,在指定初值的情况下,经过处理,然后将处理过的值作为初值,不断迭代。所以iterate创建的是一个无限流。
示例代码:
Stream.iterate(1, t -> 2 * t + 1)
.limit(10)
.forEach(System.out::println);
无限流有一个问题,在数值溢出之后,会一直重复-1的值。Java11进行了优化,以让你提供一个 Predicate (判断条件)来指定什么时候结束迭代,进行有限的迭代,示例代码如下:
Stream.iterate(1, t -> t< 1000, t -> 2 * t + 1)
.forEach(System.out::println);
增加了一系列的字符串处理方法
判断字符串是否为空白
示例代码:
String s1 = " \t \r\n";
System.out.println(s1.isBlank()); // true
去除字符串首尾空白
示例代码:
String s2 = " \t 123\r\n".strip();
System.out.println(s2); // 123
trim()大部分情况下效果等同于strip(),但是trim()只能去除码值小于等于32的空白字符,不能去除中文情况下的空白字符,strip()可以去除所有语言中的空白
去除尾/首部空格
示例代码:
String s2 = " \t 123\r\n";
System.out.println(s2.strip().length()); // 3
// 去除首部的空白
System.out.println(s2.stripLeading().length()); // 5
// 去除尾部的空白
System.out.println(s2.stripTrailing().length()); // 10
复制字符串
String s3 = "做一个好人";
System.out.println(s3.repeat(3));
// 做一个好人做一个好人做一个好人
行数统计
String s2 = " \t 123\r\n123";
System.out.println(s2.lines().count()); //2
s2.lines()获取的是一个流,将字符串根据换行符切割转换为Stream
Optional加强
Optional是Java中引进的容器类,主要用于避免空指针异常,我之前的博客对其进行了详细的介绍:[Java8新特性 - Optional容器类](https://www.cnblogs.com/fx-blog/p/11747058.html"Java8新特性 - Optional容器类")。Java11中Opthonal 也增加了几个非常酷的方法。
ofNullable方法
参照前面Stream增强的介绍,使用Optional.of(T value);传入的参数是null时,会抛出空指针异常,所以Java11中新增了ofNullable,可以兼容空指针,但是实际传入null后要小心,不能用get接收,最好利用orElse方法接收,示例代码如下。
Optional<String> optional = Optional.ofNullable(null);
// 如果内部引用为空,则返回参数中引用,否则返回内部引用
System.out.println(optional.orElse("做一个好人")); // 做一个好人
orElseThrow方法
也可以使用orElseThrow()方法接收,直接在orElseThrow()时抛出异常。
Optional<String> optional = Optional.ofNullable(null);
System.out.println(optional.orElseThrow());
错误如下:
Exception in thread "main" java.util.NoSuchElementException: No value present
at java.base/java.util.Optional.orElseThrow(Optional.java:382)
源码如下:
public T orElseThrow() {
if (value == null) {
throw new NoSuchElementException("No value present");
}
return value;
}
or方法
也可以使用or()方法接收,当一个空 Optional 时给它一个替代的Optional,示例代码如下:
Optional<String> optional = Optional.ofNullable(null);
System.out.println(optional.or(() -> Optional.of("做一个好人!"))
.get()); // 做一个好人!
InputStream加强
Java11中新增了transferTo方法,把输入流中的所有数据直接自动地复制到输出流中,这是在处理原始数据流时非常实用的一种用法,不用写循环,也不需要缓冲区,示例代码如下:
public void test() throws Exception {
var classLoader = this.getClass().getClassLoader();
var inputStream = classLoader.getResourceAsStream("file");
try (var outputStream = new FileOutputStream("file2")) {
inputStream.transferTo(outputStream);
}
inputStream.close();
}
Java11新特性 - 新加一些实用的API的更多相关文章
- 重新想象 Windows 8.1 Store Apps (88) - 通信的新特性: 新的 HttpClient
[源码下载] 重新想象 Windows 8.1 Store Apps (88) - 通信的新特性: 新的 HttpClient 作者:webabcd 介绍重新想象 Windows 8.1 Store ...
- Atitit.mysql 5.0 5.5 5.6 5.7 新特性 新功能
Atitit.mysql 5.0 5.5 5.6 5.7 新特性 新功能 1. MySQL 5.6 5 大新特性1 1.1. 优化器的改进1 1.2. InnoDB 改进1 1.3. 使用 ...
- Atitit.linux 内核 新特性 新功能
Atitit.linux 内核 新特性 新功能 1. Linux 3.2内核新特性 2012-02-12 22:41:471 1.1. EXT4:支持更大的块2 1.2. BTRFS:更快的数据清理 ...
- Atitit. visual studio vs2003 vs2005 vs2008 VS2010 vs2012 vs2015新特性 新功能.doc
Atitit. visual studio vs2003 vs2005 vs2008 VS2010 vs2012 vs2015新特性 新功能.doc 1.1. Visual Studio2 1.2. ...
- Atitit.mysql 5.0 5.5 5.6 5.7 新特性 新功能
Atitit.mysql 5.0 5.5 5.6 5.7 新特性 新功能 1. MySQL 5.6 5 大新特性1 1.1. 优化器的改进1 1.2. InnoDB 改进1 1.3. 使用 ...
- JDK1.8新特性(一) ----Lambda表达式、Stream API、函数式接口、方法引用
jdk1.8新特性知识点: Lambda表达式 Stream API 函数式接口 方法引用和构造器调用 接口中的默认方法和静态方法 新时间日期API default Lambda表达式 L ...
- iOS10 新特性-新功能,以及ReplayKit库
iOS的10.0 本文总结了iOS的10,运行于目前推出iOS设备推出的主要开发者相关的功能. iOS版10引入了新的方法来增加您的应用程序通过帮助系统参与在适当的时候建议你的应用程序给用户.如果你在 ...
- Java 8新特性之旅:使用Stream API处理集合
在这篇“Java 8新特性教程”系列文章中,我们会深入解释,并通过代码来展示,如何通过流来遍历集合,如何从集合和数组来创建流,以及怎么聚合流的值. 在之前的文章“遍历.过滤.处理集合及使用Lambda ...
- 【Java8新特性】关于Java8的Stream API,看这一篇就够了!!
写在前面 Java8中有两大最为重要的改变.第一个是 Lambda 表达式:另外一个则是 Stream API(java.util.stream.*) ,那什么是Stream API呢?Java8中的 ...
随机推荐
- KeyValue对RDDs
创建KeyValue对RDDs 使用函数map,返回keyvalue对 例如,包含数行数据的RDD,那每行的第一个单词作为keys. sparl.txt中的内容如下: hello ! hello wo ...
- Appium+python自动化(三十八) - Appium自动化测试框架综合实践 - 框架简介-助你冲击高薪,迎娶白富美(超详解)
简介 好久没有更新博客了,博友们是不是有点等不及了.不好意思啊,中秋节过后太忙了,这篇是好不容易抽点零碎时间写的.从这一篇开始小伙伴或者童鞋们,就跟随宏哥的脚步,一步步的从无到有,从0到1的搭建一个完 ...
- html常见的块元素与内联(行内)元素用法说明(一)
html平时常见的块元素有:div, p, h1, h2, h3等,内联元素有:span, a, img等. 块元素的属性:无论内容是什么,都会独占一整行.主要用于页面布局. 内联元素的属性:只占自身 ...
- spring5 源码深度解析----- AOP的使用及AOP自定义标签
我们知道在面向对象OOP编程存在一些弊端,当需要为多个不具有继承关系的对象引入同一个公共行为时,例如日志,安全检测等,我们只有在每个对象里引入公共行为,这样程序中就产生了大量的重复代码,所以有了面向对 ...
- JAVA设计模式---单例模式篇
单例模式(singleton):是JAVA中最简单的一种设计模式,属于创建型模式.所谓单例,就是整个程序有且仅有一个实例. 特点: 构造方法私有化 在本类中实例化一个对象作为本类的属性 对外提供一个访 ...
- phpStudy后门漏洞利用复现
phpStudy后门漏洞利用复现 一.漏洞描述 Phpstudy软件是国内的一款免费的PHP调试环境的程序集成包,通过集成Apache.PHP.MySQL.phpMyAdmin.ZendOptimiz ...
- jenkins+ant构建项目时候build.xml需要改动的地方说明
上一节将build.xml文件代码列出来了,这一节给出说明,要想使用该文件,需要变更的地方有哪些.
- Linux 删除命令rm
Linux rm命令用于删除一个文件或者目录. 语法:rm [options] name... 参数: 1.-i 删除前逐一询问确认. 2.-f 即使原档案属性设为唯读,亦直接删除,无需逐一确认. 3 ...
- 如何解决myeclipse2014突然无法打开的问题
今天突然发现我的myeclipse2014打开不了,昨晚还好好的,上网找了一下没有找到解决方法,于是新建一个工作区间Workspace Test,再打开File->Switch WorkSpac ...
- $(document).height 与$(window).height的区别
$(document).scrollTop() 获取垂直滚动的距离 (即当前滚动的地方的窗口顶端到整个页面顶端的距离)$(document).scrollLeft() 这是获取水平滚动条的距离 要获取 ...