Java8新特性(1)Lambda

主要内容

目录

1.Lambda表达式

2.函数式接口

3.方法引用与构造器引用

4.Stream API

5.接口中的默认方式与静态方法

6.新时间日期API

7.其他新特性


优点:1.速度更快(对底层的数据结构做了一定的更新和改动,对内存结构也做了一定的改变) 2.代码更少(Lambda)3.强大的Stream API 4.便于并行 5.最大化减少空指针异常

Java8对于HashMap的改变

JDK1.8之前HashMap:数组-链表

JDK1.8之后HashMap:数组-链表-红黑树(当碰撞个数大于8时,并且HashMap总容量大于64,链表变红黑树)-->红黑树除添加操作,其他操作的效率都变高

注意:负载因子为0.75最好

Lambda表达式

Lambda是一种匿名函数

匿名类 比较 Lambda表达式(1)

         //匿名类
         Comparator<Integer> com=new Comparator<Integer>(){
             @Override
             public int compare(Integer o1, Integer o2) {
                 return Integer.compare(o1,o2);
             }             
         };
         //Lambda表达式
         Comparator<Integer> com1=(o1,o2)->Integer.compare(01, 02);
         
         TreeSet<Integer> ts=new TreeSet<>(com);
         TreeSet<Integer> ts2=new TreeSet<>(com);

 匿名类 比较 Lambda表达式(2)

public interface Mypredicate <T>{
    abstract boolean Filter(Employee employee);
}
    public List<Employee> filterEmployee(List<Employee> list, Mypredicate<Employee> mp) {
        List<Employee> employees = new ArrayList<>();
        for (Employee employee : list) {
            if (mp.Filter(employee)) {
                employees.add(employee);
            }
        }
        return employees;
    }


    @Test
    public void test1() {
        List<Employee> employees = Arrays.asList(
                new Employee("张三", 18, 999),
                new Employee("李四", 19, 929),
                new Employee("王五", 20, 123));

        //匿名内部类
        List<Employee> list = filterEmployee(employees, new Mypredicate<Employee>() {
            @Override
            public boolean Filter(Employee employee) {
                return employee.getAge() < 20;
            }
        });

        for (Employee employee : list) {
            System.out.println(employee);
        }

        //Lambda表达式
        List<Employee> list1=filterEmployee(employees,(e)->e.getAge()<20);
        list1.forEach(System.out::println);

        //Stream API
        employees.stream().filter(employee -> employee.getAge()<20).forEach(System.out::println);

    }

其中区别Filter和filter,filter是Stream的方法,Filter是自定义的方法 

Lambda表达式基础语法

Java8中引入了一个新的操作符" ->",该操作符成为箭头操作符或者Lambda操作符,将Lambda表达式拆分为两位部分:左侧和右侧。

左侧:Lambda表达式的参数列表

右侧:Lambda表达式中所需执行的功能,即Lambda体

语法格式一:无参数,无返回值:

()->System.out.println("Hello Lambda");

    @Test
    public void test2(){
        Runnable r=new Runnable() {
            @Override
            public void run() {
                System.out.println("hello world!");
            }
        };
        r.run();
        //Lambda表达式
        Runnable r1=()-> System.out.println("hello world1!");
        r1.run();
    }

语法格式二:有一个参数,并且无返回值

(x)-> System.out.println(x);

@FunctionalInterface
public interface Consumer<T> {

    /**
     * Performs this operation on the given argument.
     *
     * @param t the input argument
     */
    void accept(T t);
}
@Test
public void test3(){
     Consumer<String> consumer=(x)-> System.out.println(x);
     consumer.accept("中国计量大学牛逼!");
}

其中(x)-> System.out.println(x)是对accept方法的实现 

若Lambda只有一个参数,小括号可以不写

x-> System.out.println(x)

语法格式三:有两个以上的参数,有返回值,并且Lambda体中有多条语句,必须使用大括号

Comparator<T>中有int compare(T o1, T o2)方法

    @Test
    public void test4(){
        Comparator<Integer> comparable=(x, y)->{
            System.out.println("函数式接口");
            return Integer.compare(x,y);
        };
    }

 格式语法四:若Lambda体中只有一条语句,return和大括号都可以不写

    @Test
    public void test5(){
        Comparator<Integer> comparable=(x, y)->Integer.compare(x,y);
    }

语法格式五:Lambda表达式的参数列表的数据类型可以写(但都要加),也可以省略,因为JVM编译器通过上下文推断出数据类型,即“类型推断

 @Test
    public void test5(){
        //不省略数据类型
        Comparator<Integer> comparator=(Integer x, Integer y)->Integer.compare(x,y);
        Comparator<Integer> comparable1=(x, y)->Integer.compare(x,y);
        
    }

总结:Lambda表达式的实现需要“函数式接口”的支持。函数式接口就是只有一个抽象方法的接口。函数式接口可以使用@FunctionalInterface修饰,该注解可以检查是否是函数式接口。Comparator中虽然有很多方法,但只有一个抽象方法,所以也是函数式接口。

应用

@FunctionalInterface
public interface MyFunction {
    String getValue(String str);
}
    public String strHandler(String str, MyFunction mf){
        return mf.getValue(str);
    }
   

    @Test
    public void test7(){
        String trim=strHandler("\t\t\t 中国计量大学   ", str->str.trim());
        System.out.println(trim);
        
        String newStr=strHandler("sahjdhaskj",str -> str.toUpperCase());
        System.out.println(newStr);
    }

Java8内置的四大核心函数式接口

Comsumer<T>: 消费型接口
void accept(T t);

Supplier<T>:供给型接口
T get();

Function<T,R>:函数型接口
R apply(T t);

Predicate<T>:断言型接口
boolean test(T t);

例如

    //消费
    public void happy(double money,Consumer<Double> con){
        con.accept(money);
    }

    @Test
    public void test8(){
        happy(100,x-> System.out.println(x));
    }

    //供给
    public List<Integer> provide(int num,Supplier<Integer> supplier){
        List<Integer> list=new ArrayList<>();
        for(int i=0;i<num;i++){
            Integer integer = supplier.get();
            list.add(integer);
        }
        return list;
    }

    @Test
    public void test9(){
        List<Integer> provide = provide(3, () -> (int)(Math.random()* 100));
        System.out.println(provide);
    }

    //函数
    public int Length(String str,Function<String,Integer> function){
        return function.apply(str);
    }

    @Test
    public void test10(){
        int length = Length("213432", x -> x.length());
        System.out.println(length);
    }
    
    //断言
    public Boolean Check(int age,Predicate<Integer> fun){
        return fun.test(age);
    }

    @Test
    public void test11(){
        Boolean flag=Check(20,x->x>10);
        System.out.println(flag);
    }

方法引用

若Lambda体中的内容有方法已经实现了,我们可以使用“方法引用”。(可以理解为方法引用是Lambda表达式的另外一种表现形式)

使用前提注意:

1.Lambda体中调用方法的参数列表与返回值类型,要与函数式接口中抽象方法的参数列表和返回值类型一致!

2.若Lambda参数列表中 第一个参数为实例方法的调用者,第二个参数为实例方法的参数时,这时就可以使用 类::实例方法。

语法格式一 : 对象::实例方法名

    @Test
    public void test1(){
        //println属于实例方法
        Consumer<String> con=(x)-> System.out.println(x);

        PrintStream ps1=System.out;
        Consumer<String> con1=(x)-> ps1.println(x);
        
        //Lambda体中的特定功能已经有特定方法(一般只有一行代码)可以完成时,就可以选择另外一种表现形式
        //函数型接口抽象方法的入参和出参,要与引用方法的入参和出参一致。
        Consumer<String> con2=ps1::println;
        //等价于Consumer<String> con1= System.out::println(x);
        con2.accept("123");
    }

原因:System.out的public void println(String x)方法和Consumer<String>的void accept(String t)方法的入参和出参一致,且accept方法属于实例方法,所以可以使用 对象::实例方法名

    @Test
    public void test2(){
        Employee employee=new Employee("小王",12,231);
        //Lambda表达式
        Supplier<String> sup=()->employee.getName();
        //方法引用
        Supplier<String> sup1=employee::getName;

        String s = sup1.get();
        System.out.println(s);

    }

原因:employee的public String getName()方法和Suppliers<String>的T get()方法的入参和出参一致,且get方法属于实例方法,所以可以使用 对象::实例方法名。。 

语法格式二: 类::静态方法名

    @Test
    public void test3(){
        //Lambda表达式
        Comparator<Integer> com=(x,y)->Integer.compare(x,y);
        
        //方法引用,compare为静态方法
        Comparator<Integer> com1=Integer::compare;
    }

 原因:Comparator<Integer>的int compare(T o1, T o2);方法和Integer的public static int compare(int x, int y)方法的入参和出参一致,且compare方法为静态方法,所以可以使用 类:: 静态方法名。 

语法格式三: 类::实例方法名

第一个参数为这个实例方法的调用者,第二个参数为这个实例方法的参数时,就可以使用 类::实例方法。

    @Test
    public void test4(){
        BiPredicate<String,String> biPredicate=(x,y)->x.equals(y);
        //第一个参数为这个方法的调用者,第二个参数为这个方法的参数时,这时就可以使用 类::实例方法
        BiPredicate<String,String> biPredicate1=String::equals;
    }

构造器引用 

注意:需要调用的构造器参数列表要与函数式接口中的抽象方法参数列表保持一致

语法格式: 类::new

    public Employee() {
    }

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

    public Employee(String name, int age) {
        this.name = name;
        this.age = age;
    }
    @Test
    public void test5(){

        //Lambda表达式
        Supplier<Employee> supplier=()->new Employee();
        //类::new  (无参构造器)
        Supplier<Employee> supplier1=Employee::new;

        //不能使用Supplier是因为Supplier中的get方法是无参的,若使用(x)->new Employee()则报错
        Function<String,Employee>function=(x)->new Employee(x);
        //类::new   (调用的是有一个参数为String的构造函数)
        Function<String,Employee>function1=Employee::new;

        BiFunction<String,Integer,Employee> biFunction=(x,y)->new Employee(x,y);
        //类::new   (调用的是有一个参数为String,另一个参数为Integer的构造函数)
        BiFunction<String,Integer,Employee> biFunction1=Employee::new;

        //本质:new的构造类型取决于函数式接口抽象方法的参数列表

    }

 数组引用

语法格式:Type[] :: new;

    @Test
    public void test6(){
        Function<Integer,String[]> function=(x)->new String[x];

        Function<Integer,String[]> function1=String[]::new;
    }

Junit 

主要用来程序员测试,即所谓的白盒测试(单元测试),例如加@Test注解需要Junit

<dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
       <version>4.13.2</version>
       <scope>test</scope>
</dependency>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值