Java8新特性

  • Lambda表达式
  • 入门演示
    • 案例1
      • 如何解决 cannot be cast to java.lang.Comparable问题?
    • 案例2
      • 优化方式一 : 策略设计模式
      • 优化方式二: 策略设计模式+匿名内部实现接口,减少创建实体类的麻烦
      • 优化方式三: lambda表达式
      • 优化方式四: stream流
  • Lambda语法
    • 语法格式一 : 无参数,无返回值
      • 注意: 局部内部类与局部变量
    • 语法格式二: 有一个参数,无返回值
    • 语法格式三: 如果一个参数,那么小括号可以不写
    • 语法格式四:有两个参数,有返回值,lambda体中有多条语句
    • 语法格式五:若lambda体中只有一条语句,那么return和{}都可以省略不写
    • 语法格式六: lambda表达式的参数列表的数据类型可以省略不写,因为JVM编译器可以通过上下文推断出数据类型,即“类型推断”
    • Lambda需要函数式接口的支持
      • 函数式接口: 接口中只有一个抽象方法的接口,称为函数式接口,可以使用@FunctionalIterface修饰,检查当前接口是否式函数式接口
      • 我们可以通过lambda来实现函数式接口里面的唯一的抽象方法
      • 举例一
        • 涉及知识点一: Interage.compareTo()
        • 涉及知识点二: Collections工具类
    • 内置四大核心函数式接口
      • Consumer :消费型接口
      • Supplier:供给型接口
      • Function

Lambda表达式

​ Lambda是一个匿名函数,可以理解为一段可以传递的代码(将代码像数据一样传递);可以写出更简洁、更灵活的代码;作为一种更紧凑的代码风格,是Java语言表达能力得到提升


入门演示

案例1

public class TestMain
{//使用匿名内部类完成比较@Testpublic void test(){//比较器                 匿名内部类,创建该接口的一个实现类Comparator<People> com=new Comparator<People>() {@Overridepublic int compare(People o1, People o2) {return o1.getAge()-o2.getAge();}};//TreeSet的特点是可排序、不重复TreeSet<People> ts=new TreeSet<>(com);ts.add(new People("大忽悠",20));ts.add(new People("小忽悠",18));ts.add(new People("大大大",22));ts.add(new People("小朋友",17));ts.forEach(System.out::println);}//lambda表达式替代匿名内部类@Testpublic void test1(){//比较器Comparator<People> com=(p1,p2)-> p1.getAge()-p2.getAge();//TreeSet的特点是可排序、不重复TreeSet<People> ts=new TreeSet<>(com);ts.add(new People("大忽悠",20));ts.add(new People("小忽悠",18));ts.add(new People("大大大",22));ts.add(new People("小朋友",17));ts.forEach(System.out::println);}
}

如何解决 cannot be cast to java.lang.Comparable问题?

如何解决 cannot be cast to java.lang.Comparable问题?


案例2

要求对下面的代码进行优化:

public class TestMain
{List<People> peopleList= Arrays.asList(new People("1号",18,3000),new People("2号",21,4000),new People("3号",19,5000),new People("4号",20,3500));//获取年龄大于18的public List<People> getAgeOver18(){List<People> list=new ArrayList<>();for (People p:peopleList){if(p.getAge()>18)list.add(p);}return list;}//获取工资大于3000的public List<People> getMoneyOver3000(){List<People> list=new ArrayList<>();for (People p:peopleList){if(p.getMoney()>3000)list.add(p);}return list;}@Testpublic void test(){List<People> ageOver18 = getAgeOver18();ageOver18.forEach(System.out::println);System.out.println("======================================");List<People>  moneyOver3000=getMoneyOver3000();moneyOver3000.forEach(System.out::println);}
}

优化方式一 : 策略设计模式

声明一个接口MyPrediect

public interface MyPrediect<T>
{public boolean test(T t);
}

接口的实现类一FilterPeoAge,负责过滤年龄:

public class FilterPeoAge implements MyPrediect<People>{@Overridepublic boolean test(People people) {return people.getAge()>18;}
}

接口实现类二FilterPeoMoney,负责过滤金钱

public class FilterPeoMoney implements MyPrediect<People>{@Overridepublic boolean test(People people) {return people.getMoney()>3000;}
}

测试演示:

public class TestMain
{List<People> peopleList= Arrays.asList(new People("1号",18,3000),new People("2号",21,4000),new People("3号",19,5000),new People("4号",20,3500));public List<People> FilterPeo(List<People> list,MyPrediect<People> mp){List<People> peopleList=new ArrayList<>();for (People p:list){if(mp.test(p))peopleList.add(p);}return peopleList;}@Testpublic void test(){List<People> peopleList = FilterPeo(this.peopleList, new FilterPeoAge());peopleList.forEach(System.out::println);System.out.println("===========================");List<People> peopleList1 = FilterPeo(peopleList, new FilterPeoMoney());peopleList1.forEach(System.out::println);}
}


当我们还需要安装某个策略进行过滤时,只需要实现接口,完成相应策略过滤逻辑编写即可


优化方式二: 策略设计模式+匿名内部实现接口,减少创建实体类的麻烦

public class TestMain
{List<People> peopleList= Arrays.asList(new People("1号",18,3000),new People("2号",21,4000),new People("3号",19,5000),new People("4号",20,3500));public List<People> FilterPeo(List<People> list,MyPrediect<People> mp){List<People> peopleList=new ArrayList<>();for (People p:list){if(mp.test(p))peopleList.add(p);}return peopleList;}@Testpublic void test(){List<People> peopleList = FilterPeo(this.peopleList, new MyPrediect<People>() {@Overridepublic boolean test(People people) {return people.getAge()>18;}});peopleList.forEach(System.out::println);System.out.println("===========================");List<People> peopleList1 = FilterPeo(peopleList, new MyPrediect<People>() {@Overridepublic boolean test(People people) {return people.getMoney()>3000;}});peopleList1.forEach(System.out::println);}
}


优化方式三: lambda表达式

public class TestMain
{List<People> peopleList= Arrays.asList(new People("1号",18,3000),new People("2号",21,4000),new People("3号",19,5000),new People("4号",20,3500));public List<People> FilterPeo(List<People> list,MyPrediect<People> mp){List<People> peopleList=new ArrayList<>();for (People p:list){if(mp.test(p))peopleList.add(p);}return peopleList;}@Testpublic void test(){List<People> peopleList = FilterPeo(this.peopleList, (people)-> people.getMoney()>4000);peopleList.forEach(System.out::println);}
}


优化方式四: stream流

public class TestMain
{List<People> peopleList= Arrays.asList(new People("1号",18,3000),new People("2号",21,4000),new People("3号",19,5000),new People("4号",20,3500));public List<People> FilterPeo(List<People> list,MyPrediect<People> mp){List<People> peopleList=new ArrayList<>();for (People p:list){if(mp.test(p))peopleList.add(p);}return peopleList;}@Testpublic void test(){peopleList.stream().filter(people -> people.getMoney()>3000).limit(2).forEach(System.out::println);}
}


Lambda语法

- 操作符:->
- 左侧:参数列表
- 右侧:执行代码块 / Lambda 体


即lambda是对接口的抽象方法的实现,可能有人会问,如果接口中抽象方法存在多个,那lambda是对哪个抽象方法的实现呢?

其实lambda需要一个函数式接口的支持,即当前接口只有一个抽象方法


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

    @Testpublic void test(){Runnable runnable = new Runnable() {@Overridepublic void run() {System.out.println("方法执行中.....");}};runnable.run();System.out.println("----------------------");Runnable r1=()-> System.out.println("r1执行中....");r1.run();}


注意: 局部内部类与局部变量

局部内部类在JDK8之前只能使用成员变量和被final修饰的局部变量。JDK8之后,局部内部类如果使用局部变量那么局部变量默认被final修饰,但如果局部变量被重新赋值,那么局部内部类将不能在使用。具体看下例子:

 public void show() {int j = 0;   //jdk1.8后默认被final修饰。1.8之前局部内部类只能访问成员变量,和被final修饰的局部变量class A{public void showA() {System.out.println(i);System.out.println(j);}}
//      j = 2;//如果对局部变量做了修改,则默认会变成不被final修饰。局部内部类不可调用}//注:有静态成员的一定是静态内部类

lambda这里跟匿名内部类用法一致


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

public class TestMain
{@Testpublic void test(){Consumer<String> consumer=(x)-> System.out.println(x);//  void accept(T t); 对该抽象方法进行实现consumer.accept("大忽悠");}
}


语法格式三: 如果一个参数,那么小括号可以不写

      Consumer<String> consumer=x-> System.out.println(x);//  void accept(T t); 对该抽象方法进行实现consumer.accept("大忽悠");

语法格式四:有两个参数,有返回值,lambda体中有多条语句

public class TestMain
{@Testpublic void test(){//   int compare(T o1, T o2);重写该方法Comparator<Integer> com=(x,y)->{System.out.println("函数式接口");return Integer.compare(x,y);};int compare = com.compare(1, 2);System.out.println(compare);}
}


语法格式五:若lambda体中只有一条语句,那么return和{}都可以省略不写

  public void test(){//   int compare(T o1, T o2);重写该方法Comparator<Integer> com=(x,y)->Integer.compare(x,y);int compare = com.compare(1, 2);System.out.println(compare);}

语法格式六: lambda表达式的参数列表的数据类型可以省略不写,因为JVM编译器可以通过上下文推断出数据类型,即“类型推断”


Lambda需要函数式接口的支持

函数式接口: 接口中只有一个抽象方法的接口,称为函数式接口,可以使用@FunctionalIterface修饰,检查当前接口是否式函数式接口

我们可以通过lambda来实现函数式接口里面的唯一的抽象方法


举例一

public class TestMain
{List<People> peopleList= Arrays.asList(new People("1号",18,3000),new People("2号",20,4000),new People("3号",18,5000),new People("4号",20,3500));//先安装年龄升序排序,年龄相同,再安装money降序排序@Testvoid test(){//重写下面这个方法,比较器可以为空//    public static <T> void sort(List<T> list, Comparator<? super T> c) {//        list.sort(c);//    }Collections.sort(peopleList,(p1,p2)->{if(p1.getAge()==p2.getAge())return -p1.getMoney().compareTo(p2.getMoney());elsereturn p1.getAge().compareTo(p2.getAge());});peopleList.forEach(System.out::println);}
}


涉及知识点一: Interage.compareTo()

Integer obj2=100;//比较大小System.out.println(obj2.compareTo(100));System.out.println(obj2.compareTo(102));System.out.println(obj2.compareTo(10));

结果: 0 , -1 , 1 ,即大于返回 1 ,小于返回 -1 ,等于返回 0


涉及知识点二: Collections工具类

详细用法


内置四大核心函数式接口

Consumer<T> :消费型接口void  accept(T t);Supplier<T>:供给型接口T get(T t);Function<T,R>:函数型接口R apply(T t);Predicate<T>:断言型接口boolean test(T t);

Consumer :消费型接口

@FunctionalInterface
public interface Consumer<T> {/*** Performs this operation on the given argument.** @param t the input argument*/void accept(T t);
}

测试:

public class TestMain
{@Testvoid test(){//这里的lambda表达式实现了对应的抽象函数happy(10000,(m)-> System.out.println("我有: "+m));}public void happy(Integer money,Consumer<Integer> com){com.accept(money);}
}


Supplier:供给型接口

@FunctionalInterface
public interface Supplier<T> {/*** Gets a result.** @return a result*/T get();
}

测试:

public class TestMain
{@Testvoid test(){List<String> numList=getNumList(5,()->UUID.randomUUID().toString().substring(0,8));numList.forEach(System.out::println);}//需求: 产生指定个数的随机id,并放入集合中public List<String> getNumList(int num, Supplier<String> supplier){ArrayList<String> integers = new ArrayList<String>();for(int i=0;i<num;i++){integers.add(supplier.get());}return  integers;}
}


Function<T,R>: 函数型接口

public interface Function<T, R>{R apply(T t);}

测试:

public class TestMain
{@Testvoid test(){String str=StrHandler("\t\t\t    大忽悠    \t\t\t",(s)->s.trim());System.out.println(str);}//需求: 处理字符串public String StrHandler(String str, Function<String,String> f){return f.apply(str);//返回被处理过后的字符串}
}

涉及知识点: trim()函数

trim()方法的使用


Predicate:断言型接口

@FunctionalInterface
public interface Predicate<T> {/*** Evaluates this predicate on the given argument.** @param t the input argument* @return {@code true} if the input argument matches the predicate,* otherwise {@code false}*/boolean test(T t);}

测试:

public class TestMain
{@Testvoid test(){StrHandler("大忽悠啊",(str)->str.length()>3);StrHandler("嘿嘿",(str)->str.length()>3);}//需求: 处理字符串public void StrHandler(String str, Predicate<String> predicate){if(predicate.test(str))System.out.println(str);elseSystem.out.println("太短了");}
}


其他常用函数式接口


Java8新特性----Lambda表达式详细探讨相关推荐

  1. java8新特性lambda表达式、函数式编程、方法引用和接口默认方法以及内部类访问外部变量

    一提到java是一种什么语言? 大多数人肯定异口同声的说是一门面向对象的语言,这种观点从我们开始学java就已经根深蒂固了,但是学到java8新特性函数式编程的时候,我才知道java并不是纯面向对象的 ...

  2. java8新特性-lambda表达式入门学习

    定义 jdk8发布新特性中,lambda是一大亮点之一.lambda表达式能够简化我们对数据的操作,减少代码量,大大提升我们的开发效率.Lambda 表达式"(lambda expressi ...

  3. java8新特性lambda表达式概述

    定义 ​ jdk8发布新特性中,lambda是一大亮点之一.lambda表达式能够简化我们对数据的操作,减少代码量,大大提升我们的开发效率.Lambda 表达式"(lambda expres ...

  4. Java8新特性——lambda表达式

    什么是lambda表达式? Lambda 表达式是Java 8 的新特性,是一种新的编程语法.lambda语义简洁明了,性能良好,是Java 8 的一大亮点.废话不多说,我们来看个例子. 从内部类到l ...

  5. java8新特性-lambda表达式和stream API的简单使用

    一.为什么使用lambda Lambda 是一个 匿名函数,我们可以把 Lambda表达式理解为是 一段可以传递的代码(将代码像数据一样进行传递).可以写出更简洁.更灵活的代码.作为一种更紧凑的代码风 ...

  6. java compare 返回值_关于Java你不知道的那些事之Java8新特性[Lambda表达式和函数式接口]...

    前言 为什么要用Lambda表达式? Lambda是一个匿名函数,我们可以把Lambda表达式理解为是一段可以传递的代码,将代码像数据一样传递,这样可以写出更简洁.更灵活的代码,作为一个更紧凑的代码风 ...

  7. 2020.10.20课堂笔记(java8新特性 lambda表达式)

    一.什么是Lambda? 我们知道,对于一个Java变量,我们可以赋给其一个"值". 如果你想把"一块代码"赋给一个Java变量,应该怎么做呢? 比如,我想把右 ...

  8. Java8 新特性 -- Lambda表达式:函数式接口、方法的默认实现和静态方法、方法引用、注解、类型推测、Optional类、Stream类、调用JavaScript、Base64

    文章目录 1. Lambda表达式 1.1 Lambda表达式语法 1.2 Lambda表达式示例 1.3 说明:函数式接口 2. 方法的默认实现和静态方法 3. 方法引用 3.1 方法引用示例 4. ...

  9. Java8 新特性lambda表达式(一)初始

    本篇参考Richard Warburton的 java8 Lambdas :Functional Programming for the Masses 学习lambda表达式之前,需要知道什么是函数式 ...

最新文章

  1. thinkphp $this-display()报错
  2. Linux可以对目录进行硬链接,Linux硬链接与软链接原理及用法解析
  3. 《C和指针》——宏中容易出现的错误
  4. vue 不识别svg_vue配置svg 图标显示不出来
  5. python常用第三方库(转载)
  6. 怎么把打开方式还原计算机程序,打开方式怎么还原【图文】
  7. Linux有问必答:如何在树莓派上安装USB网络摄像头
  8. 常用容器管理器易受危险 exploit 攻击
  9. 了解PHP中$_SERVER变量对路径的解析
  10. java-线程同步问题
  11. Logit模型拟合实战案例(Biogeme)
  12. Windows和Linux平台上实现Word转PDF
  13. 智慧交通综合管理平台建设方案
  14. 华三Track+NQA+静态路由配置实例
  15. g7108 android5,三星G7108V移动4G版一键Root权限获取及USB驱动
  16. 系统设计系列之如何设计一个短链服务
  17. 深度学习大神都推荐入门必须读完这9篇论文
  18. 技术人“结构化思维”训练的一点想法和实践
  19. Android应用权限大全(Manifest.permission)
  20. 8051单片机Proteus仿真与开发实例-ULN2003A驱动步进电机仿真

热门文章

  1. 干了5Android开发还没掌握-binder-机制、驱动核心源码?我劝你早点改行吧
  2. 数据结构——栈的应用
  3. 完整性约束条件:唯一性约束
  4. 光电收发器不匹配造成网络不通
  5. 2022最新网络安全基础知识点汇总
  6. 计算机缺少opencl.dll,opencl.dll损坏,如何修复
  7. 惯导运算中的常值国际单位制惯导中常用单位
  8. Fortran和C/C++混合编程学习笔记(一):编译链接
  9. 如何成为一名架构师,架构师成长之路
  10. HTML语言教程(完整版)