Java11新特性 - 新加一些实用的API

1. 新的本机不可修改集合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对象时,不可以包含重复数据

2. Stream加强

Stream是Java8的新特性,我之前的博客对其进行了详细的介绍:Java8新特性 - Stream API。Java9开始对Stream新增了4个新方法。

2.1 增加单个参数构造方法,可为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);
    }

2.2 增加 takeWhile 和 dropWhile 方法

2.2.1 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方法的作用是:从流中一直获取判定器为真的元素,一旦遇到元素为假,就终止处理!

2.2.2 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方法的作用为:只要判定器为真,就一直丢弃元素,直到为假,取为假后的所有元素!

2.3 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);

3. 增加了一系列的字符串处理方法

3.1 判断字符串是否为空白

示例代码:

String s1 = " \t \r\n";
System.out.println(s1.isBlank()); // true

3.2 去除字符串首尾空白

示例代码:

String s2 = "    \t  123\r\n".strip();
System.out.println(s2); // 123

trim()大部分情况下效果等同于strip(),但是trim()只能去除码值小于等于32的空白字符,不能去除中文情况下的空白字符,strip()可以去除所有语言中的空白

3.3 去除尾/首部空格

示例代码:

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

3.4 复制字符串

String s3 = "做一个好人";
System.out.println(s3.repeat(3));
// 做一个好人做一个好人做一个好人

3.5 行数统计

String s2 = "    \t  123\r\n123";
System.out.println(s2.lines().count()); //2

s2.lines()获取的是一个流,将字符串根据换行符切割转换为Stream

4. Optional加强

Optional是Java中引进的容器类,主要用于避免空指针异常,我之前的博客对其进行了详细的介绍:Java8新特性 - Optional容器类。Java11中Opthonal 也增加了几个非常酷的方法。

4.1 ofNullable方法

参照前面Stream增强的介绍,使用Optional.of(T value);传入的参数是null时,会抛出空指针异常,所以Java11中新增了ofNullable,可以兼容空指针,但是实际传入null后要小心,不能用get接收,最好利用orElse方法接收,示例代码如下。

Optional<String> optional = Optional.ofNullable(null);
// 如果内部引用为空,则返回参数中引用,否则返回内部引用
System.out.println(optional.orElse("做一个好人")); // 做一个好人

4.2 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;
    }

4.3 or方法

也可以使用or()方法接收,当一个空 Optional 时给它一个替代的Optional,示例代码如下:

Optional<String> optional = Optional.ofNullable(null);
System.out.println(optional.or(() -> Optional.of("做一个好人!"))
        .get()); // 做一个好人!

5. 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();
}

原文地址:https://www.cnblogs.com/fx-blog/p/11755560.html

时间: 2024-07-30 07:18:05

Java11新特性 - 新加一些实用的API的相关文章

Atitit.mysql&#160;5.0&#160;5.5&#160;&#160;5.6&#160;5.7&#160;&#160;新特性&#160;新功能

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. 使用 memcached API 直接访问 NoSQL2 1.4. 更好的复制2 1.5. Performance Schema2 2. MySQL 5.7.62 2.1. 内建中文全文索引2 2.2. 多主复制2 2.3. other2 3. 参考2 1. MySQL  5.6    5 大新特性 M

Atitit.&#160;visual&#160;studio&#160;vs2003&#160;vs2005&#160;vs2008&#160;&#160;VS2010&#160;vs2012&#160;vs2015新特性&#160;新功能.doc

Atitit. visual studio vs2003 vs2005 vs2008  VS2010 vs2012 vs2015新特性 新功能.doc 1.1. Visual Studio2 1.2. Visual Studio 972 1.3. Visual Studio 6.02 1.4. Vs20022 1.5. Vs20032 1.6. Vs20052 1.6.1. 数据访问  Web开发     Windows Forms 方面的开发特性增强2 1.6.2. Refactoring 2

Atitit.mysql 5.0 5.5 &#160;5.6 5.7 &#160;新特性 新功能

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. 使用 memcached API 直接访问 NoSQL2 1.4. 更好的复制2 1.5. Performance Schema2 2. MySQL 5.7.62 2.1. 内建中文全文索引2 2.2. 多主复制2 2.3. other2 3. 参考2 1. MySQL  5.6    5 大新特性 M

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

[源码下载] 作者:webabcd 介绍重新想象 Windows 8.1 Store Apps 之通信的新特性 新的 HttpClient http get string http get stream http post string http post stream 示例HTTP 服务端WebServer/HttpDemo.aspx.cs /* * 用于响应 http 请求 */ using System; using System.IO; using System.Threading; u

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

在这篇“Java 8新特性教程”系列文章中,我们会深入解释,并通过代码来展示,如何通过流来遍历集合,如何从集合和数组来创建流,以及怎么聚合流的值. 在之前的文章“遍历.过滤.处理集合及使用Lambda表达式增强方法”中,我已经深入解释并演示了通过lambda表达式和方法引用来遍历集合,使用predicate接口来过滤集合,实现接口的默认方法,最后还演示了接口静态方法的实现. 源代码都在我的Github上:可以从 这里克隆. 内容列表 使用流来遍历集合. 从集合或数组创建流. 聚合流中的值. 1.

(六)Unity5.0新特性------新动画功能

?? unity 5.0 中的新动画功能 这里是你可以期待的新动画功能快速概述 ! State Machine Behaviours状态机行为 在Unity 5 中,你会能够将StateMachineBehaviour 脚本添加到您的states,当played状态时能接收callbacks回调: ?OnStateEnter ?OnStateUpdate ?OnStateExit ?OnStateMove ?OnStateIK 在你的状态,您可以创建尽可能多的StateMachineBehavi

(十)Unity5.0新特性------新UI系统实战

原文 Unity New GUI Tutorial – Part 1 Unity New GUI Tutorial- Part 2 Unity New GUI Tutorial – Part 3 大家可以看看他的游戏源代码,然后了解一下新UI的使用.  介绍的很详细: 需要指出的 UI的动画都是使用 Animator\Animation组件实现,在实际的项目开发中,会使用Dotween\  Dftween这些补间动画插件来实现.   用代码通知,更加灵活. 但是使用 Animator\Anima

H5新特性---新应用

1.持久化本地存储 可以不通过第三方插件实现数据的本地存储 2.WebSocket 页面之间可以双向通信 3.服务器推送事件(SSE) 从Web服务器将消息推送给浏览器(在手机中常见) 例如: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>LocalStorage</title> </head&g

java8新特性——新日期和时间API

一.LocalDate,LocalTime,LocalDateTime LocalDate,LocalTime,LocalDateTime类的实例是不可改变的,分别表示使用ISO-8601日历系统的日期,时间,日期和时间.他们提供了简单的日期或时间,并不包含当前的时间信息.也不包含与地区相关的信息. //1.当前时间对象 LocalDateTime ldt = LocalDateTime.now(); System.out.println(ldt); //2.自定义时间对象 LocalDateT