JDK8新特性_JDK8面试题

2022-09-21 08:27:42 浏览数 (1)

大家好,又见面了,我是你们的朋友全栈君。

JDK8新特性

lambda表达式

要求:接口必须是函数式接口,一个接口如果只有一个抽象方法,那他就是函数式接口,我们可以在一个接口上使用__Functionallnterface__注解

代码语言:javascript复制
package com.atguigu.java;

import java.util.Comparator;

public class LambaTest { 
   
    public static void main(String[] args) { 
   
        Runnable r1 = new Runnable() { 
   
            @Override
            public void run() { 
   
                System.out.println("我爱北京天安门");
            }
        };
        r1.run();
        System.out.println("------------------------");
        Runnable r2 = () -> System.out.println("我爱北京故宫");
        r2.run();


        Comparator<Integer>com1 = new Comparator<Integer>() { 
   
            @Override
            public int compare(Integer o1, Integer o2) { 
   
                return Integer.compare(o1,o2);
            }
        };
        System.out.println("-------------------------");
        //lambda表达式
        Comparator<Integer>com2 = (o1, o2) ->  Integer.compare(o1,o2);

        System.out.println("-------------------------");
        //方法引用
        Comparator<Integer>com3 = Integer::compare;
        
    }
}

java中的lambda本质是接口的实例

lambda表达式6种类型

代码语言:javascript复制
package com.atguigu.java;

import java.util.Comparator;
import java.util.function.Consumer;

public class LambaTest { 
   
    public static void main(String[] args) { 
   
        //1.无参数 无返回值
        Runnable runnable = () -> System.out.println("我爱中国");

        //2.lambda需要一个参数,没有返回值
        Consumer<String> consumer = (String s) -> { 
   System.out.println(s);};

        //3.数据类型可以省略,因为可由编译器推断得出,称为"类型推断"
        Consumer<String> consumer1 = (s) -> { 
   System.out.println(s);};

        //4.Lambda若只有一个参数 参数的小括号可以省略
        Consumer<String> consumer2 = s -> { 
   System.out.println(s);};

        //5.lambda需要两个或以上的参数,多条执行语句,并且可以有返回值
        Comparator<Integer> con1 = (o1,o2) -> { 
   
            System.out.println(o1);
            System.out.println(o2);
            return o1.compareTo(o2);
        };

        //6.lambda只有一条语句的时候,return与大括号若都有,均可省略
        Comparator<Integer> con2 = (o1,o2) -> o1.compareTo(o2);
        
    }
}

java内置4大核心函数式接口

  1. 消费型接口 Consumer void accept(T t)
  2. 供给型接口 Supplier T get()
  3. 函数式接口 Function<T,R>R apply(T t)
  4. 断定型接口 Predicateboolean test(T t)
代码语言:javascript复制
package com.atguigu.java;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

public class LambaTest { 
   
    public static void main(String[] args) { 
   
        List<String> list = Arrays.asList("北京","南京","天津","东京","西京","普京");
        List<String> filters = filterString(list,s -> s.contains("京"));
        System.out.println(filters);
    }
    static public List<String> filterString(List<String> list, Predicate<String> pre){ 
   
        ArrayList<String>filterList = new ArrayList<>();
        for(String s : list){ 
   
            if(pre.test(s)){ 
   
                filterList.add(s);
            }
        }
        return filterList;
    }
}

方法引用

函数引用就是lambda表达式,是lambda表达式更深层次的表达。 使用场景:当要传递给lambda体的操作,已经有实现的方法了,可以使用方法引用! 格式主要有以下三种:

  1. 对象 :: 非静态方法
  2. 类 :: 静态方法
  3. 类 :: 非静态方法 使用要求:要求接口中的抽象方法的形参列表和返回值类型与方法引用的方法的形参列表和返回值类型相同(适用于情况1和2)
代码语言:javascript复制
public static void main(String[] args) { 
   
        //BiPredicate中的Boolean test(T t1,T t2);
        //String中的boolean t1.equals(t2);
        BiPredicate<String,String>pre1 = (s1 , s2) -> s1.equals(s2);
        System.out.println(pre1.test("abc","abc"));
        System.out.println("*********************");
        BiPredicate<String,String>pre2 = String::equals;


        //Comparator中的int compare(T t1,T t2)
        //String中的int t1.compareTo(t2)
        Comparator<String>com1 = (s1, s2) -> s1.compareTo(s2);
        System.out.println(com1.compare("abc","bcd"));
        System.out.println("********************");
        Comparator<String> com2 = String::compareTo;
        
    }

构造器引用

代码语言:javascript复制
public static void main(String[] args) { 
   
        //构造器引用
        Supplier<String> stringSupplier = new Supplier<String>() { 
   
            @Override
            public String get() { 
   
                return new String();
            }
        };
        System.out.println("****************");
        Supplier<String> stringSupplier1 = () -> new String();
        System.out.println("****************");
        Supplier<String> stringSupplier2 = String::new;


        //数组引用
        Function<Integer,String[]>func1 = length -> new String[length];
        System.out.println("****************");
        Function<Integer,String[]>func2 = String[]::new;
        
    }

Stream API

  1. Stream关注的是对数据的运算,与CPU打交道,集合关注的是数据,与内存打交道
  2. Stream自己不会存储内存。不会改变源对象,返回一个Stream对象。操作是延迟执行的,等到需要的结果的时候才会执行
  3. Stream执行流程:1.Stream实例化2.一系列中间操作3.终止操作

说明:

  1. 一个中间操作链,对数据源的数据进行处理
  2. 一旦执行终止操作,就执行中间操作链,之后,不会再被重写

Stream创建3种方式

代码语言:javascript复制
public static void main(String[] args) { 
   
        //1.
        List<String>list = null;
        Stream<String> stream = list.stream();
        //2.
        int arr[] = { 
   1,2,3};
        IntStream stream1 = Arrays.stream(arr);
        //3.
        Stream<Integer> integerStream = Stream.of(1, 2, 3, 4);
    
    }

Stream的中间操作

  1. 筛选与切片
代码语言:javascript复制
public static void main(String[] args) { 
   
        List<Employee> list = Employee.getEmployees();
        Stream<Employee> stream = list.stream();
        //filter(Predicate p)--接收 Lambda,从流中排除某些元素
        stream.filter(e -> e.getSalary() > 70000).forEach(System.out::println);
        System.out.println();

        //limit(n)截断流,使其元素不超过给定数量
        list.stream().limit(3).forEach(System.out::println);
        System.out.println();

        //skip(n)--跳过元素,返回一个扔掉前n个元素的流,若流中元素不足n个,则返回一个空流
        list.stream().skip(3).forEach(System.out::println);

        //distinct()--筛选,通过流所生成元素的hashCode()和equals去除重复元素
        list.stream().distinct().forEach(System.out::println);
        
    }
  1. 映射
代码语言:javascript复制
public static void main(String[] args) { 
   
        //map(Function f)--接收一个函数作为参数,将元素转换成其他形式提取信息,该函数会被应用到每个元素上,
        //并将其映射成一个新的元素
        List<String>list = Arrays.asList("aa","bb","cc","dd");
        list.stream().map(str -> str.toUpperCase()).forEach(System.out::println);
        //练习1:获取员工姓名长度大于3的员工姓名

        List<Employee>employees = Employee.getEmployees();
        Stream<String> stringStream = employees.stream().map(Employee::getName);
        stringStream.filter(name -> name.length() > 3).forEach(System.out::println);


        //flatMap(Fcuntion f)--接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有的流换成另一个流
        //map方式
        Stream<Stream<Character>> streamStream = list.stream().map(LambaTest::fromStringToStream);
        streamStream.forEach(s -> { 
   
            s.forEach(System.out::println);
        });
        //flatmap方式
        Stream<Character>characterStream = list.stream().flatMap(LambaTest::fromStringToStream);

    }
    public static Stream<Character> fromStringToStream(String str){ 
   
        ArrayList<Character> strings = new ArrayList<>();
        for (Character c : str.toCharArray()){ 
   
            strings.add(c);
        }
        return strings.stream();
    }
  1. 排序
代码语言:javascript复制
    public static void main(String[] args) { 
   
        //sorted自然排序
        List<Integer> list = Arrays.asList(12, 43, 65, 34, 84, 0, -98, 7);
        list.stream().sorted().forEach(System.out::println);

        //sorted(Comparator)
        List<Employee> employees = Employee.getEmployees();
        employees.stream().sorted((e1,e2) -> { 
   
            boolean b = e1.getSalary() > e2.getSalary();
            return b;
        }).forEach(System.out::println);
    }
  1. 匹配与查找
代码语言:javascript复制
public static void main(String[] args) { 
   
        //allMatch(Predicate e)检查是否匹配所有的元素
        List<Employee> employees = Employee.getEmployees();
        boolean b = employees.stream().allMatch(e -> e.getSalary() > 1000);
        System.out.println(b);
        //allMatch(Predicate e)检查是否匹配所有的元素
        boolean b1 = employees.stream().anyMatch(e -> e.getSalary() > 10000);
        System.out.println(b1);

        //noneMatch(Predicate e)检查是否没有匹配的元素
        //findfirst()查找第一个元素
        Optional<Employee> first = employees.stream().findFirst();
        System.out.println(first);
        //findAny()返回当中流的任意一个元素
        //count()求个数
        long count = employees.stream().filter(e -> e.getSalary() > 50000).count();
        System.out.println(count);

        //max(Comparator c)
        Stream<Integer> integerStream = employees.stream().map(e -> e.getSalary());
        Optional<Integer> max = integerStream.max(Integer::compareTo);
        System.out.println(max);
        //min(Comparator c)
        Optional<Employee> min = employees.stream().min((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
        System.out.println(min);

        //foreach(Consumer c)
        employees.stream().forEach(System.out::println);
    }
  1. 规约
代码语言:javascript复制
// reduce(T identity, BinaryOperator) 可以将流中的元素反复结合起来,得到一个值,返回一个T
// 练习:计算1-10自然数的和
        List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
        Integer reduce = list.stream().reduce(0, Integer::sum);
        System.out.println(reduce);

        //reduce(BinaryOperator)--可以将流中元素反复结合起来,得到一个值,返回Optimal<T>
        List<Employee> employees = Employee.getEmployees();
        Stream<Integer> integerStream = employees.stream().map(Employee::getSalary);
        Optional<Integer> reduce1 = integerStream.reduce(Integer::sum);
        System.out.println(reduce1);
    }
  1. 收集
代码语言:javascript复制
public static void main(String[] args) { 
   
        //收集
        //collect(Collector c)将流转换为其他形式,接收一个Collector接口的实现,用于给Stream中元素做汇总的方法
        //Collector接口中方法的实现决定了如何对流执行收集的操作(如收集到List,Set,Map)
        //另外,Collectors实用类提供了很多静态方法,可以方便地创建常见收集器实例
// 练习:超照工资大于6000的员工,结果返回为一个list或set
        List<Employee> employees = Employee.getEmployees();
        Stream<Employee> employeeStream = employees.stream().filter(e -> e.getSalary() > 6000);
        List<Employee> collect = employeeStream.collect(Collectors.toList());
        employees.forEach(System.out::println);
    }

Optimal类

空指针异常是导致java应用程序失败的最常见的原因。为了解决空指针异常,开发出了Optimal类. 目的:为了避免空指针

代码语言:javascript复制
package com.atguigu.java;

import java.util.Optional;

public class LambaTest { 
   
    public static void main(String[] args) { 
   

    }
}

class Boy{ 
   
    private Girl girl;

    @Override
    public String toString() { 
   
        return "Boy{"  
                "girl="   girl  
                '}';
    }

    public Boy(Girl girl) { 
   
        this.girl = girl;
    }

    public void setGirl(Girl girl) { 
   
        this.girl = girl;
    }

    public Girl getGirl() { 
   
        return girl;
    }

    public static void main(String[] args) { 
   
        //Optimal.of(T t)创建一个Optimal实例,t必须非空
        //Optimal.empty()创建一个空的Optimal实例
        //Optimal.ofNullable(T t)t 可以为null
        //orElse()
        Boy boy = null;
        Optional<Boy> boy1 = Optional.ofNullable(boy);
        Boy boy2 = boy1.orElse(new Boy(new Girl("迪丽热吧")));
        Girl girl = boy2.getGirl();
        Optional<Girl> girl1 = Optional.ofNullable(girl);
        Girl girl2 = girl1.orElse(new Girl("古力娜扎"));
        System.out.println(girl2);
    }
}

class Girl{ 
   
    private String name;

    public void setName(String name) { 
   
        this.name = name;
    }

    public Girl() { 
   
    }

    public String getName() { 
   
        return name;
    }

    public Girl(String name) { 
   
        this.name = name;
    }
}

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/168824.html原文链接:https://javaforall.cn

0 人点赞