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

新的本机不可修改集合API

自从Java9开始,JDK里面为集合(List/Set/Map)都添加了of和copyOf方法,他们能够来建立不可变的集合。html

Question1:什么叫作不可变集合?

不能对集合进行添加、删除、替换、排序等操做,不然会报java.lang.UnsupportedOperationException错误。 示例代码:java

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()建立的集合也是一个不可变的集合ide

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新推出的特性局部变量类型推断,这里面再也不赘述。ui

第一段代码和第二段代码差很少,为何返回结果不同呢?咱们来看一下他们的源码:this

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。spa

**扩展:**使用Set.of()方法建立Set对象时,不能够包含重复数据指针

Stream增强

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

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

原文出处:https://www.cnblogs.com/fx-blog/p/11755560.html

相关文章
相关标签/搜索