JAVA8 新特性学习笔记

ajzx3880 4年前
   <h3>语法的新特性:</h3>    <h2>一、 接口 <strong>默认方法和静态方法</strong> ,给接口赋予了类的能力,增强了java的灵活性。</h2>    <p>接口中可加入default默认方法或static静态方法。</p>    <p>可有多个但必须实现其方法体。Java接口中定义了默认方法,实现类不用每个方法都实现一遍了。而且不需要修改继承接口的实现类,就给接口添加了新的方法实现。其给接口赋予了抽象类的能力,增强了java的灵活性。</p>    <h2>二、 方法引用</h2>    <p>ClassName::methodName (静态方法 + 实例方法 都可使用)</p>    <p>super::methodName (超类上的实例方法使用)</p>    <p>Class::new (创建新实例时可使用)</p>    <p>TypeName[]::new</p>    <h2>三、 Lambda表达式(也叫做闭包)</h2>    <pre>  <code class="language-java">Collections.sort(names, (String a, String b) -> {           return b.compareTo(a);       });        Collections.sort(names, (String a, String b) -> b.compareTo(a));        Collections.sort(names, (a, b) -> b.compareTo(a));</code></pre>    <p>Lambda 作用域 ​</p>    <p>在lambda表达式中可以访问外层局部变量,但不能修改外层局部变量。(闭包的作用域)</p>    <p>和本地变量不同的是,lambda内部对于实例的字段或类的静态变量是即可读又可写。</p>    <h2>四、 函数式接口</h2>    <p>函数式接口 <strong>有且仅有一个抽象方法</strong> ,每一个lambda匹配这个抽象方法。因为static与defualt默认方法不是抽象的,所以可以在函数式接口中自由的添加。</p>    <p>函数式接口应该用@FunctionalInterface来注解接口,但可省略。</p>    <p>函数式接口的作用是使lambda表达式融入java的类型系统。每一个lambda相当于一种指定类型的函数式接口的实现。</p>    <pre>  <code class="language-java">@FunctionalInterface     public interface MyFuncitonalInterface {         void fun();     }       MyFuncitonalInterface mf = () -> System.out.println(666);             mf.fun();</code></pre>    <p>常用javaAPI标准函数接口:</p>    <ol>     <li> <p>Predicate 断言,一般用来判断是否满足某条件</p> </li>     <li> <p>Consumer 接收一个参数,无返回值</p> </li>     <li> <p>Function 接收T对象,返回R对象</p> </li>     <li> <p>Supplier 类似工厂,调用时会返回一个指定类型的对象</p> </li>     <li> <p>UnaryOperator 执行一元操作(与、或、非)</p> </li>     <li> <p>BinaryOperator 接收两个参数,返回一个值</p> </li>    </ol>    <p>一些函数式接口的典型用例:</p>    <pre>  <code class="language-java">public class Lambda {           @FunctionalInterface         interface Fun {             void foo();         }           public static void main(String[] args) throws Exception {               // Predicates               Predicate<String> predicate = (s) -> s.length() > 0;               predicate.test("foo");              // true             predicate.negate().test("foo");     // false               Predicate<Boolean> nonNull = Objects::nonNull;             Predicate<Boolean> isNull = Objects::isNull;               Predicate<String> isEmpty = String::isEmpty;             Predicate<String> isNotEmpty = isEmpty.negate();               // Functions               Function<String, Integer> toInteger = Integer::valueOf;             Function<String, String> backToString = toInteger.andThen(String::valueOf);//在toInteger加入apply结束后执行的方法,生成新的Function               backToString.apply("123");     // "123"               // Suppliers               Supplier<Person> personSupplier = Person::new;             personSupplier.get();   // new Person               // Consumers               Consumer<Person> greeter = (p) -> System.out.println("Hello, " + p.firstName);             greeter.accept(new Person("Luke", "Skywalker"));               // Comparators               Comparator<Person> comparator = (p1, p2) -> p1.firstName.compareTo(p2.firstName);               Person p1 = new Person("John", "Doe");             Person p2 = new Person("Alice", "Wonderland");               comparator.compare(p1, p2);             // > 0             comparator.reversed().compare(p1, p2);  // < 0               // Runnables               Runnable runnable = () -> System.out.println(UUID.randomUUID());             runnable.run();               // Callables               Callable<UUID> callable = UUID::randomUUID;             callable.call();         }       }</code></pre>    <p>小结:</p>    <p>以上新增的语言特性使Java 能够实现一部分“函数式”的编程范式,可以用简单的函数式风格(例如filter和map)简化笨重的代码。但Java需要用类型来表示它们。如java.util.function中的Predicate、Function和Consumer接口。</p>    <h3>java库的新特性</h3>    <h2>五、 Stream 流操作</h2>    <p>java.util.Stream 表示能应用在一组元素上一次执行的操作序列。</p>    <p>Stream 操作分为中间操作或者最终操作两种,最终操作返回一特定类型的计算结果,而中间操作返回Stream本身,这样你就可以将多个操作依次串起来。</p>    <p>Stream 的创建需要指定一个数据源,比如 java.util.Collection的子类,List或者Set, Map不支持。通过 Collection.stream() 或者 Collection.parallelStream() 来创建一个Stream。</p>    <p>Stream的操作可以串行执行或者并行(parallelStream)执行。</p>    <p>常用操作:</p>    <p>forEach 遍历</p>    <pre>  <code class="language-java">stringCollection        .stream()      .forEach(System.out::println);</code></pre>    <p>Filter 过滤</p>    <p>过滤通过一个predicate接口来过滤并只保留符合条件的元素,该操作属于中间操作,所以我们可以在过滤后的结果来应用其他Stream操作(比如forEach)。forEach需要一个函数来对过滤后的元素依次执行。forEach是一个最终操作,所以我们不能在forEach之后来执行其他Stream操作。</p>    <pre>  <code class="language-java">stringCollection        .stream()      .filter((s) -> s.startsWith("a"))      .forEach(System.out::println);</code></pre>    <p>Sort 排序</p>    <p>排序是一个中间操作,返回的是排序好后的Stream。如果你不指定一个自定义的Comparator则会使用默认排序。需要注意的是,排序只创建了一个排列好后的Stream,而不会影响原有的数据源,排序之后原数据stringCollection是不会被修改的:</p>    <pre>  <code class="language-java">stringCollection        .stream()      .sorted()      .filter((s) -> s.startsWith("a"))      .forEach(System.out::println);</code></pre>    <p>Map 映射</p>    <p>中间操作map会将元素根据指定的Function接口来依次将元素转成另外的对象,下面的示例展示了将字符串转换为大写字符串。你也可以通过map来讲对象转换成其他类型,map返回的Stream类型是根据你map传递进去的函数的返回值决定的。</p>    <pre>  <code class="language-java">stringCollection        .stream()      .map(String::toUpperCase)      .sorted((a, b) -> b.compareTo(a))      .forEach(System.out::println);</code></pre>    <p>Match 匹配</p>    <p>Stream提供了多种匹配操作,允许检测指定的Predicate是否匹配整个Stream。所有的匹配操作都是最终操作,并返回一个boolean类型的值。</p>    <pre>  <code class="language-java">boolean anyStartsWithA =        stringCollection          .stream()          .anyMatch((s) -> s.startsWith("a"));  System.out.println(anyStartsWithA);      // true    boolean allStartsWithA =        stringCollection          .stream()          .allMatch((s) -> s.startsWith("a"));  System.out.println(allStartsWithA);      // false    boolean noneStartsWithZ =        stringCollection          .stream()          .noneMatch((s) -> s.startsWith("z"));  System.out.println(noneStartsWithZ);      // true</code></pre>    <p>Count 计数</p>    <p>计数是一个最终操作,返回Stream中元素的个数,返回值类型是long。</p>    <pre>  <code class="language-java">long startsWithB =        stringCollection          .stream()          .filter((s) -> s.startsWith("b"))          .count();</code></pre>    <p>Reduce</p>    <p>这是一个最终操作,允许通过指定的函数来讲stream中的多个元素规约为一个元素,规约后的结果是通过Optional接口表示的:</p>    <pre>  <code class="language-java">Optional<String> reduced =        stringCollection          .stream()          .sorted()          .reduce((s1, s2) -> s1 + "#" + s2);  reduced.ifPresent(System.out::println);</code></pre>    <p>collect获取集合</p>    <pre>  <code class="language-java">//获取年龄大于12的用户列表           List<User> list = users.parallelStream().filter(p -> p.age > 12)                   .collect(Collectors.toList());           System.out.println(list);</code></pre>    <h2>六、 Optional 处理空指针问题</h2>    <p>Optional内部封装了要处理的值value,对外提供了一下方法:</p>    <pre>  <code class="language-java">//============创建方法=====================================//  <T> Optional<T> empty() ;//返回空对象    <T> Optional<T> of(T value);//返回封装value的Optional对象,内部用Objects.requireNonNull,判断value为null的情况抛出NullPointerException    <T> Optional<T> ofNullable(T value);//返回一个封装value的Optional对象,value为null的情况返回空的Optional对象    //============使用方法=====================================//  T get();// 返回value,若value为nul抛出NoSuchElementException    boolean isPresent();//判断value是否存在    void ifPresent(Consumer<? super T> consumer) ;//若value非null,执行consumer.accept(value)方法    Optional<T> filter(Predicate<? super T> predicate);//若value存在并且value符合predicate的判定,返回Optional对象,否则返回空Optional对象    <U> Optional<U> map(Function<? super T, ? extends U> mapper);//若value存在执行mapper.apply(value)并返回Optional对象,否则返回空Optional对象。flatMap略(为空抛出NullPointerException)    T orElse(T other);//返回value,若value为null返回other    T orElseGet(Supplier<? extends T> other);//返回value,若value为null返回other.get()的返回值    <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X ;//返回value,若value为null抛出exceptionSupplier.get()的返回值</code></pre>    <pre>  <code class="language-java">//典型用例:  //获取字符串s,若为null返回""  String str = Optional.fromNullable(s).orElse("");    //获取车辆对象,若为null则new一个  Car car = Optional.fromNullable(car).orElse(Car::new);</code></pre>    <p>其他:</p>    <ul>     <li> <p>Objects工具类, 对Object空指针问题进行了处理。</p> </li>     <li> <p>数组工具类:Arrays.parallelSort 并行排序</p> </li>     <li> <p>Map新增方法:</p> </li>    </ul>    <p>map.forEach((id, val) -&gt; System.out.println(val));</p>    <p>map.getOrDefault(42, &quot;not found&quot;);&nbsp; // 没有返回默认值</p>    <ul>     <li> <p>HashMap 内部结构变为:数组+链表+红黑树(解决hashCode冲突使用链地址法,将key加入链表,当链表长度大于8时转换为红黑树,引入红黑树利用红黑树快速增删改查的特点大程度优化了HashMap的性能。这个数据结构很屌但很复杂(⊙o⊙)?)</p> </li>     <li> <p>多重Annotation:允许我们把同一个类型的注解使用多次,只需要给该注解标注一下@Repeatable即可。还增加到两种新的target:@Target({ElementType.TYPE <em>PARAMETER, ElementType.TYPE</em> USE})</p> </li>     <li> <p>全新的时间日期API。</p> </li>     <li> <p>JVM的新特性:JVM内存永久区已经被metaspace替换(JEP 122)。JVM参数 -XX:PermSize 和 –XX:MaxPermSize被XX:MetaSpaceSize 和 -XX:MaxMetaspaceSize代替。</p> </li>    </ul>    <p> </p>    <p>来自:https://blog.souche.com/java8-xin-te-xing-xue-xi-bi-ji/</p>    <p> </p>