• Java8新特性


    Lambda表达式详见https://www.cnblogs.com/zys2019/p/13778194.html

    1.Stream API

    1.1概述

    Stream 是Java8中处理集合的关键抽象概念,它可以对集合进行非常复杂的操作。

    1.2Stream的操作步骤

    1)创建Stream:从一个数据源中获取流。
    
    2)中间操作:对数据源的数据进行操作。
    
    3)终止操作:执行中间操作链,并产生结果。
    

    1.3创建流的方式

    1)通过Collection集合提供的stream()或parallelStream()创建

    List<Integer> list=new ArrayList<>();
    Stream<Integer> stream = list.stream();

    2)通过Arrays中的静态方法stream()获取数组流创建

    String[] arr = {"java", "python", "c++"};
    Stream<String> stream1 = Arrays.stream(arr);

    3)通过Stream类的静态方法of创建

    Stream<Integer> stream = Stream.of(1, 5, 7, 9, 20, 1);

    4)无限流

    Stream.generate(()->Math.random()).forEach(System.out::println);

    System.out::println就是方法的引用,当此接口有返回值是才能使用。

    1.4中间操作

    多个中间操作会连接成一个流水线,只有触发终止操作时才会去真正的处理操作得到结果,否则不会进行任何的处理。

    1.4.1筛选和切片

    1)filter:接收Lambda,从流中排除某些操作

    案例:过滤集合中所有的偶数

    List<Integer> list = Arrays.asList(10, 30, 10, 35, 75, 21, 54, 99, 100);
    list.stream().filter(e -> e % 2 == 0).forEach(System.out::println);

    2)distinct:筛选,通过流所生成元素的hashCode()和equals()去除重复元素。

    案例:去除集合中的重复元素

    List<Integer> list = Arrays.asList(10, 30, 10, 35, 75, 21, 54, 99, 100);
    list.stream().distinct().forEach(System.out::println);

    需要注意的是,使用此方法,必须对集合中存储的数据类对象重新hashCode()和equals()方法。这里使用的是Integer类型,它已经重写了,如果是自定义的类型,则必须手动重写,下图就是对自定义的User类重写:

    3)limit:截断流,使其元素不超过给定对象

    案例:只获取集合中的前5个元素

    List<Integer> list = Arrays.asList(10, 30, 10, 35, 75, 21, 54, 99, 100);
    list.stream().limit(5).forEach(System.out::println);

    4)skip(n):跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个空流,与limit(n)互补

    案例:只获取集合中第6个以后的元素

    List<Integer> list = Arrays.asList(10, 30, 10, 35, 75, 21, 54, 99, 100);
    list.stream().skip(6).forEach(System.out::println);

    1.4.2映射

    1)map:接收Lambda,将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。map在接收到流后,直接将Stream放入到一个Stream中,最终整体返回一个包含了多个Stream的Stream。

    案例:遍历集合中的每一个元素,将其转为大写

    List<String> list = Arrays.asList("abc","bbb","cbd","ddd");
    list.stream().map(e->e.toUpperCase()).forEach(System.out::println);

    2)flatMap:接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。flatMap在接收到Stream后,会将接收到的Stream中的每个元素取出来放入一个Stream中,最后将一个包含多个元素的Stream返回。

    案例:对上述的集合元素取出每一个元素的每一个内容

      public static Stream<Character> getCharacterByString(String str) {
            List<Character> characterList = new ArrayList<>();
            for (Character character : str.toCharArray()) {
                characterList.add(character);
            }
            return characterList.stream();
        }
    
        @Test
        public void test() {
            List<String> list = Arrays.asList("abc","bbb","cbd","ddd");
            //MyTest是类名
        list.stream().flatMap(MyTest::getCharacterByString).forEach(System.out::print);
        }

    打印结果是abcbbbcbdddd。

    1.4.3排序

    1)sorted():自然排序(Comparable)

    案例:使用默认从小到大排序

    List<Integer> list = Arrays.asList(10, 30, 10, 35, 75, 21, 54, 99, 100);
    //使用默认的排序方法,从小到大
    list.stream().sorted().forEach(System.out::println);

    2)sorted(Comparator com):定制排序(Comparator)

    案例:自定义从大到小排序

    List<Integer> list = Arrays.asList(10, 30, 10, 35, 75, 21, 54, 99, 100);
    //使用自定义的排序方法,从大到小
    list.stream().sorted((e1,e2)-> e2-e1).forEach(System.out::println);

    案例:使用stream与不使用stream的对比

            List<String> list = new ArrayList<>();
            for (int i = 0; i < 999999; i++) {
                list.add("测试效率" + i);
            }
    
            //开始时间戳
            Long startTime = System.currentTimeMillis();
            list.forEach(item -> {
    
            });
            //开始时间戳
            Long endTime = System.currentTimeMillis();
            System.out.println("遍历的时间:" + (endTime - startTime));//45
    
            //开始时间戳
            Long startTime2 = System.currentTimeMillis();
            list.stream().forEach(item -> {
    
            });
            //开始时间戳
            Long endTime2 = System.currentTimeMillis();
            System.out.println("遍历的时间2:" + (endTime2 - startTime2));//10

    通过它们执行的时间的对比,可以发现使用stream的效率远高于不使用stream,对代码的运行速度有很大的提高。

    1.5终止操作

    1.5.1查找和匹配

    1)allMatch:检查是否匹配所有元素。都符合条件返回true,否则返回false

    案例:判断集合中的元素是否都大于50

    List<Integer> list = Arrays.asList(10, 30, 10, 35, 75, 21, 54, 99, 100);
    boolean b = list.stream().allMatch(e -> e > 50);
    System.out.println(b);

    2)anyMatch:检查是否至少匹配一个元素。只要有一个符合就返回true,否则返回false

    3)noneMatch:检查是否没有匹配所有元素

    4)findFirst:返回第一个元素。返回值是Optional类型,再使用get方法获取内容。

    案例:获取集合的第一个元素

    List<Integer> list = Arrays.asList(10, 30, 10, 35, 75, 21, 54, 99, 100);
    Optional<Integer> first = list.stream().findFirst();
    System.out.println(first.get());

    5)findAny:返回当前流中的任意元素。返回值是Optional类型

    6)count:返回流中元素的总个数

    7)max:返回流中最大值。返回值是Optional类型

    案例:获取集合中的最大值

    List<Integer> list = Arrays.asList(10, 30, 10, 35, 75, 21, 54, 99, 100);
    Optional<Integer> max = list.stream().max((o1, o2) -> o1 - o2);
    System.out.println(max.get());

    8)min:返回流中最小值。返回值是Optional类型

    1.5.2归约

    将流中元素反复结合起来,得到一个值。方法是reduce

    案例:把1-100放到集合中并求和

            List<Integer> integerList = new ArrayList<>(100);
            for (int i = 1; i <= 100; i++) {
                integerList.add(i);
            }
            final Integer reduce = integerList.stream().reduce(0, (x, y) -> x + y);
            System.out.println("结果为:" + reduce);//5050

    1.5.3收集

    将流转换为其他形式,接收一个Collector接口实现 ,用于给Stream中汇总的方法。方法是collect

     案例:计算平均值

    List<Integer> list = Arrays.asList(10, 30, 10, 35, 75, 21, 54, 99, 100);
    Double collect = list.stream().collect(Collectors.averagingInt(p -> p));
    System.out.println(collect);

    2.Optional类

    2.1概述

    Optional类是一个容器类,代表一个值存在或不存在,主要解决的问题是空指针异常。

    2.2常用方法

    先创建一个实体类,供下面使用:

    public class User {
        private String name;
        private Integer age;
        //set和get,toString方法在此略,请自行加入
    }

    1)Optional.of(T t):创建一个实例,返回值是Optional

    当返回值是Optional时,要获取里面的内容,再使用get方法即可。当是空实例时,使用get方法就会抛出异常

    User user = new User();
    Optional<User> opt = Optional.of(user);
    System.out.println(opt.get());//User{name='null', age=null}

    2)Optional.empty(T t):创建一个空的实例,返回值是Optional

    获取抛出异常:

    Optional<User> opt = Optional.empty();
    System.out.println(opt.get());//No value present

    3)Optional.ofNullable(T t):若T不为null则创建一个实例,否则创建一个空实例,返回值是Optional

    User user = new User();
    Optional<User> opt = Optional.ofNullable(user);
    System.out.println(opt.get());//User{name='null', age=null}
    Optional<User> opt2 = Optional.ofNullable(null);
    System.out.println(opt2.get());//No value present

    4)isPresent():判断是否包含值,包含值返回true,,否则返回false

    有了这个方法,就可以对第二个方法进行改写,就不会出现异常。

    Optional<User> opt = Optional.empty();
    if (opt.isPresent()) {
         System.out.println(opt.get());//No value present
    }else{
         System.out.println("opt不包含值");
    }
     //opt不包含值

    5)orElse(T t):如果调用对象包含值就返回该值,否则返回t,必须和ofNullable结合使用。

    String nullValue = null;
    String notNullValue = "嘿嘿嘿";
    String replaceValue = "哈哈哈";
    
    String optional = Optional.ofNullable(nullValue).orElse(replaceValue);
    System.out.println(optional);//哈哈哈
    
    String nonNullOptional = Optional.ofNullable(notNullValue).orElse(replaceValue);
    System.out.println(nonNullOptional);//嘿嘿嘿

    6)orElseGet(Supplier s):如果调用对象包含值就返回该值,否则返回s,必须和ofNullable结合使用。

    String nullValue = null;
    String notNullValue = "嘿嘿嘿";
    String replaceValue = "哈哈哈";
    
    String optionalGet = Optional.ofNullable(nullValue).orElseGet(() -> replaceValue);
    System.out.println(optionalGet);//哈哈哈
            
    String nonNullOptionalGet = Optional.ofNullable(notNullValue).orElseGet(() -> replaceValue);
    System.out.println(nonNullOptionalGet);//嘿嘿嘿

    orElseGet和orElse达到的效果是一样的,只是他们的参数不同。

    7)map(Function f):如果有值对其处理,就返回处理后的Optional,否则返回空实例

    public class MyTest {
        @Test
        public void testMap() {
            C c = null;
            Optional<Optional<String>> s1 = Optional.ofNullable(c).map(MyTest::getOrderNumber);
            System.out.println(s1);//Optional.empty
    
            c = new C("hello");
            Optional<Optional<String>> s2 = Optional.ofNullable(c).map(MyTest::getOrderNumber);
            System.out.println(s2.get().get());//hello
        }
    
        private static Optional<String> getOrderNumber(C c) {
            return Optional.ofNullable(c).map(f -> f.getOrderNumber());
        }
    
    
    }
    
    class C {
        private String orderNumber;
    
        public String getOrderNumber() {
            return orderNumber;
        }
    
        public C(String orderNumber) {
            this.orderNumber = orderNumber;
        }
    
    }

    3.接口的方法新特性

    在jdk1.8中,在接口中除了能定义抽象的方法外,还可以定义默认的方法和静态的方法。

    3.1接口中的默认方法

    默认方法使用default修饰,并且需要些方法体,当一个类实现它时,子类会继承父类的这个方法,可以对这个方法进行重写。

    1)接口的定义

    public interface A {
    
        default int sum(int a,int b){
            return a+b;
        }
    
    }

    2)实现类

    public class A1 implements A {
    
    }

    3)调用

    @Test
    public void test10() {
            A a = new A1();
            int sum = a.sum(10, 20);
            System.out.println(sum);
    }

    执行结果是30。

    有这样一种情况,当子类不仅有实现,还有继承时,如果接口的被继承的类中方法名相同时,那么子类会使用哪个类的方法呢?实际上有类优先的原则,即会先使用类的方法。原因很简单,当继承一个类时,类中的方法必须被重写,自然而然调用的方法就是这个被重写的方法。

    3.2接口中的静态方法

     静态方法使用static修饰,并通过类名.方法名调用:

    1)接口定义

    public interface A {
    
        static int sum(int a,int b){
            return a+b;
        }
    
    }

    2)调用

    @Test
    public void test10() {
            int sum = A.sum(20, 12);
            System.out.println(sum);
    }

     .

  • 相关阅读:
    f5版本升级
    f5申请并激活License
    f5时间设置
    f5 SNMP配置
    f5 Syslog管理
    f5单台安装配置
    f5负载均衡算法
    f5 Seldom used
    f5售后查询
    f5基本介绍
  • 原文地址:https://www.cnblogs.com/zys2019/p/13834046.html
Copyright © 2020-2023  润新知