• Java11新特性


    新的本机不可修改集合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 = " 	 
    ";
    System.out.println(s1.isBlank()); // true
    

    去除字符串首尾空白

    示例代码:

    String s2 = "    	  123
    ".strip();
    System.out.println(s2); // 123
    

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

    去除尾/首部空格

    示例代码:

    String s2 = "    	  123
    ";
    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 = "    	  123
    123";
    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();
    }
    
  • 相关阅读:
    HTML网页基础知识
    velocity介绍及语法
    velocity中的表达式
    DecimalFormat 小数保留2位,金额千位分割
    UE.Editor下载
    Uncaught Could not find Flash element
    UE.Editor处理内容中含有多余图片问题
    vue路由
    vuejs基本结构
    vue.js组件的重要选项
  • 原文地址:https://www.cnblogs.com/fx-blog/p/11755560.html
Copyright © 2020-2023  润新知