新的本机不可修改集合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的更多相关文章

  1. 重新想象 Windows 8.1 Store Apps (88) - 通信的新特性: 新的 HttpClient

    [源码下载] 重新想象 Windows 8.1 Store Apps (88) - 通信的新特性: 新的 HttpClient 作者:webabcd 介绍重新想象 Windows 8.1 Store ...

  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. 使用 ...

  3. Atitit.linux 内核 新特性 新功能

    Atitit.linux 内核 新特性 新功能 1.  Linux 3.2内核新特性 2012-02-12 22:41:471 1.1. EXT4:支持更大的块2 1.2. BTRFS:更快的数据清理 ...

  4. 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. ...

  5. 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. 使用 ...

  6. JDK1.8新特性(一) ----Lambda表达式、Stream API、函数式接口、方法引用

    jdk1.8新特性知识点: Lambda表达式 Stream API 函数式接口 方法引用和构造器调用 接口中的默认方法和静态方法 新时间日期API default   Lambda表达式     L ...

  7. iOS10 新特性-新功能,以及ReplayKit库

    iOS的10.0 本文总结了iOS的10,运行于目前推出iOS设备推出的主要开发者相关的功能. iOS版10引入了新的方法来增加您的应用程序通过帮助系统参与在适当的时候建议你的应用程序给用户.如果你在 ...

  8. Java 8新特性之旅:使用Stream API处理集合

    在这篇“Java 8新特性教程”系列文章中,我们会深入解释,并通过代码来展示,如何通过流来遍历集合,如何从集合和数组来创建流,以及怎么聚合流的值. 在之前的文章“遍历.过滤.处理集合及使用Lambda ...

  9. 【Java8新特性】关于Java8的Stream API,看这一篇就够了!!

    写在前面 Java8中有两大最为重要的改变.第一个是 Lambda 表达式:另外一个则是 Stream API(java.util.stream.*) ,那什么是Stream API呢?Java8中的 ...

随机推荐

  1. python,json解析字符串时ValueError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)

    今天写测试工具的时候,去excel取数据,用json解析字符串为字典时报错,后经调试,发现是单引号的原因,将单引号换位双引号即可 def getExcelValue_to_dic(filepath): ...

  2. 从零开始用golang创建一条简单的区块链

    区块链(Blockchain),是比特币的一个重要概念,它本质上是一个去中心化的数据库,同时作为比特币的底层技术,是一串使用密码学方法相关联产生的数据块,每一个数据块中包含了一批次比特币网络交易的信息 ...

  3. 推荐5款自学手机APP,请低调收藏,让你变得越来越优秀

    现在的手机APP真的是太多了,但里面的功能同类性又非常大,很难找到实用并且符合要求的APP.接下来就为小伙伴们推荐5款非常实用的APP软件,保证你会爱不释手,轻松秒变手机达人. 1.清爽视频编辑器 一 ...

  4. Idea 配置Jrebel热部署

    虽说Idea自带热更新功能,但是一旦mapper更改,则不能及时更新,影响开发效率. 接下来,我们来配置Jrebel热更新,简单方便实用. 第一步:进入插件下载页面. 第二步:安装jrebel插件. ...

  5. 【爬虫小程序:爬取斗鱼所有房间信息】Xpath

    # 本程序亲测有效,用于理解爬虫相关的基础知识,不足之处希望大家批评指正from selenium import webdriver import time class Douyu: "&q ...

  6. 【ADO.NET基础】——数据库连接

    SQL Sever连接字符串 (1)标准的安全连接 Data Source=myServerAddress;Initial Catalog=myDataBase;User Id=myUsername; ...

  7. 2019-ccpc秦皇岛现场赛

    https://www.cnblogs.com/31415926535x/p/11625462.html 昨天和队友模拟了下今年秦皇岛的区域赛,,,(我全程在演 题目链接 D - Decimal 签到 ...

  8. ieTESTER浏览器使用ie6崩溃问题

    打开浏览器在选项--internet属性--连接--局域网设置--将自动检测设置的对勾勾掉就可以  重启下浏览器

  9. IoC 之加载 Bean:总结

    上文中我们将bean已经加载到了IOC容器中,接下来我们将把IOC加载Bean出来进行代码解析 备注:(有些解释是参考别个博客的相关解释 )一起探讨请加我QQ:1051980588 bean 的初始化 ...

  10. javascript进阶-《原型对象和原型链》

    原创发布 by @一像素 2015.12 在Javascript中,万物皆对象,但对象也有区别,大致可以分为两类,即:普通对象Object 和 函数对象Function. 一般而言,通过new Fun ...