前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >lambda表达式(二)

lambda表达式(二)

作者头像
java后端指南
发布2021-05-13 16:52:24
2390
发布2021-05-13 16:52:24
举报
文章被收录于专栏:java后端java后端

今日主题:lambda表达式(二)

简介

lambda表达式是什么呢?是JDK8的一个新特性,他的优势有很多,可以简化很多操作,我们现在来讲讲吧!

环境

  • JDK8

lambda表达式语法精简

代码语言:javascript
复制
public class Syntax2 {
 public static void main(String[] args) {
  //语法精简
  //1.参数
  //由于在接口的抽象方法中,已经定义了参数的数量和类型,所以在lambda表达式中,参数的类型可以忽略
  //备注:如果需要省略参数类型,则每一个参数类型都要省略
  LambdaNoneReturnMutipleParameter lambda1=(a,b)->{
   System.out.println(a+b);
  };
  lambda1.test(2,3);//5
  
  //2.参数小括号
  //如果参数列表中,参数的数量只有一个,此时小括号可以省略
  LambdaNoneReturnSingleParameter lambda2=a->{
   System.out.println(a);
  };
  lambda2.test(3);//3
  
  //3.方法大括号
  //如果方法体重只有一条语句,那么大括号可以省略
  LambdaNoneReturnSingleParameter lambda3=a->System.out.println(a);
  lambda3.test(4);//4
  
  //4.如果方法体中唯一一条语句是一个返回语句,则在省略大括号的同时,也必须省略return
  LambdaSingleReturnNoneParameter lambda4=()->10;
  System.out.println(lambda4.test());//10
  
  LambdaSingleReturnMultipleParameter lambda5=(a,b)->a+b;
  System.out.println(lambda5.test(2, 3));//5
  
 }
}

lambda语法进阶

普通方法引用

代码语言:javascript
复制
public class Syntax3 {
 public static int change(int a){
  return a*2;
 }
 public static void main(String[] args) {
  //方法引用:
  //可以快速的将一个lambda表达式的实现指向一个已经实现的方法
  //语法:方法的隶属者::方法名
  
  //注意:
  //1.参数数量和类型一定要和接口中定义的方法一致
  //2.返回值的类型一定要和接口中定义的类型一致
  LambdaSingleReturnSingleParameter lambda1=a->change(a);
  System.out.println(lambda1.test(1));//2
  
  //方法引用:引用了change方法实现
  LambdaSingleReturnSingleParameter lambda2=Syntax3::change;
  System.out.println(lambda2.test(3));//6
  

 }
}

构造方法引用

代码语言:javascript
复制
public class Person {
 public String name;
 public int age;

 public Person() {
  super();
  System.out.println("无参方法执行了");
 }

 public Person(String name, int age) {
  super();
  this.name = name;
  this.age = age;
  System.out.println("有参方法执行了");
 }

}
代码语言:javascript
复制
//需求:
interface PersonCreate{
 Person getPerson();
}
interface PersonCreate2{
 Person getPerson(String name,int age);
}
public class Syntax4 {
 public static void main(String[] args) {
  PersonCreate create1=()->{
   return new Person();
  };
  //可以再次精简
  PersonCreate create2=()->new Person();
  
  //构造方法的引用
  PersonCreate create3=Person::new;
  Person a=create3.getPerson();//无参方法执行了
  
  PersonCreate2 create4=Person::new;
  Person b=create4.getPerson("king", 12);//有参方法执行了
  
 }
}

案例

集合排序

代码语言:javascript
复制
public class Exercise1 {
 //集合排序
 //ArrayList<>
 public static void main(String[] args) {
  //需求:已知在一个ArrayList中有若干个person对象,将这些person对象按照年龄进行降序排序
  ArrayList<Person> list=new ArrayList<Person>();
  
  list.add(new Person("aa",12));
  list.add(new Person("bb",44));
  list.add(new Person("cc",52));
  
  //降序排序
  list.sort((o1,o2)->o2.age-o1.age);
  System.out.println(list);
  //[Person [name=cc, age=52], Person [name=bb, age=44], Person [name=aa, age=12]]
 }
}

TreeSet

代码语言:javascript
复制
public class Exercise2 {
 public static void main(String[] args) {
  //使用lambda表达式实现comparator接口,并实例化对象 
  //实现降序
  TreeSet<Person> set=new TreeSet<>((o1,o2)->o2.age-o1.age);
  
  set.add(new Person("aa",12));
  set.add(new Person("bb",44));
  set.add(new Person("cc",52));
 }
}

forEach

代码语言:javascript
复制
public class Exercise3 {
 public static void main(String[] args) {
  //集合遍历
  ArrayList<Integer> list=new ArrayList<>();
  
  Collections.addAll(list, 1,2,3,4,5,6);
  
  //将集合中的每一个元素都带入到方法accept中
  list.forEach(System.out::println);
  
  /*输出:
   * 1
   * 2
   * 3
   * 4
   * 5
   * 6
   */
  //输出集合中所有的偶数
  list.forEach(a->{
   if(a%2==0)
    System.out.println(a);
  });
  
 }
}

removeif

代码语言:javascript
复制
public class Exercise4 {
 public static void main(String[] args) {
  //需求:删除集合中满足条件的元素
  ArrayList<Person> list=new ArrayList<Person>();
  
  list.add(new Person("aa",12));
  list.add(new Person("bb",44));
  list.add(new Person("cc",52));
  
  //删除年龄>45岁的人
  //lambda表达式实现
  //将集合中的每一个元素都带入到test方法中,如果返回值是true,则删除这个元素
  list.removeIf(a->a.age>45);
  System.out.println(list);
  //[Person [name=aa, age=12], Person [name=bb, age=44]]
 }
}

线程实例化

代码语言:javascript
复制
public class Exercise5 {
 public static void main(String[] args) {
  //需求:开辟一条线程。做一个数字的输出
  Thread t=new Thread(()->{
   for(int i=0;i<10;i++)
    System.out.println(i);
  });
  t.start();
 }
}

系统内置函数式接口

代码语言:javascript
复制
//系统内置的一些函数式接口
  //Predicate<T>:参数了返回值boolean
   //IntPredicate int->boolean
   //LongPredicate long->boolean
   //DoublePredicate double->boolean
  //Consumer<T>:参数T返回值void
   //IntConsumer int->void
   //LongConsumer long->void
   //DoubleConsumer double->void
  //Function<T,R>:参数了返回值R
   //IntFunction<R>int->R
   //LongFunction<R>long->R
   //DoubleFunction<R> double->R//IntTolongFunction int->long
   //IntToDoubleFunction int->double
   //LongToIntFunction long->int
   //LongToDoubleFunction long->double
   //DoubleToIntFunction doublt->int
   //DoubleTolongFunction double->long
  //Supplier<T>:参数无返回值T
  //UnaryOperator<T>:参数了返回值T
  //BinaryOperator<T>:参数T,T返回值T//BiFunction<T,U,R>:参数T,U返回值R
  //BiPredicate<T,U>:参数T,U返回值boolean
  //BiConsumer<T,U>:参数T,U返回值void

  //Predicate<T>、Consumer<T>、Function<T,R>、Supplier<T>,比较常用

常见类型:

注意:在这些内置系统函数中,最多只有两个参数,如果有返回值,最后一个参数是返回值类型,如果入参多于两个,需要通过接口来实现lambda表达式

代码语言:javascript
复制
public class 常用内置函数式接口 {
 static void 例子(){
  //无入参,无返回
  Runnable r=()->System.out.println("11");
  r.run();//11
  //无参,有返回
  Supplier<Float> s=()->200f+300f;
  System.out.println(s.get());//500.0
  
  //1参,无返回
  Consumer<Date> c=(d)->System.out.println("当前时间:"+d.toString());
  c.accept(new Date());//当前时间:Thu Jun 11 14:34:09 CST 2020
  
  //1参,有返回
  Function<StringBuffer,String> f=sb->sb.reverse().toString();
  System.out.println(f.apply(new StringBuffer("abcd")));//dcba
  
  //2参,无返回
  BiConsumer<String,Integer> bc=(str,n)->{
   String ss="";
   for(int i=0;i<n;i++){
    ss+=str;
   }
   System.out.println(ss);
  };
  bc.accept("abc", 3);//abcabcabc
  
  //2参,有返回
  BiFunction<Integer,Integer,String> bif=(i,j)->i+""+j;
  System.out.println(bif.apply(1, 2));//12

 }
 public static void main(String[] args) {
  例子();
 }
}

流式运算

增强java.util下集合框架的功能。装饰者模式的思想(套一个新的接口马甲,功能更强-各种操作、支持链式风格、支持多种内置的lambda函数接口作为对象)。流式算法。视图。

Stream是处理数组和集合的API,Stream具有以下特点:

代码语言:javascript
复制
•	不是数据结构,没有内部存储
•	不支持索引访问
•	延迟计算
•	支持过滤,查找,转换,汇总等操作

首先需要弄清楚lambda的两个操作类型:中间操作终止操作

下面通过一个demo来认识下这个过程。

代码语言:javascript
复制
Stream st=Arrays.asList(1,2,3,4,5).stream().filter(x->{
   		System.out.print(x);
   		return  x>3;
   	});

当我们执行这段代码的时候,发现并没有任何输出,这是因为lambda表达式需要一个终止操作来完成最后的动作。我们修改代码:

代码语言:javascript
复制
 Stream st=Arrays.asList(1,2,3,4,5).stream().filter(x->{
   		System.out.print(x);
   		return  x>3;
   	});
   	
   st.forEach(t-> System.out.print(t));

对应的输出结果是:

代码语言:javascript
复制
1234455

为什么会有这个输出呢?因为在filter函数的时候并没有真正的执行,在forEach的时候才开始执行整个lambda表达式,所以当执行到4的时候,filter输出之后,forEach也执行了,最终结果是1234455


对于Java中的lambda表达式的操作,可以归类和整理如下:

中间操作:链式风格

代码语言:javascript
复制
•	过滤 filter
•	去重 distinct
•	排序 sorted
•	截取 limit、skip
•	转换 map/flatMap
•	其他 peek

终止操作:无法用链式风格继续写。

代码语言:javascript
复制
•	循环 forEach
•	计算 min、max、count、 average
•	匹配 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny
•	汇聚 reduce
•	收集器 toArray collect

举例:

代码语言:javascript
复制
public class Car {
 private String band;
 private float price;
 private float toSpeed;
 public String getBand() {
  return band;
 }
 public void setBand(String band) {
  this.band = band;
 }
 public float getPrice() {
  return price;
 }
 public void setPrice(float price) {
  this.price = price;
 }
 public float getToSpeed() {
  return toSpeed;
 }
 public void setToSpeed(float toSpeed) {
  this.toSpeed = toSpeed;
 }
 public Car(String band, float price, float toSpeed) {
  super();
  this.band = band;
  this.price = price;
  this.toSpeed = toSpeed;
 }
 @Override
 public String toString() {
  return "Car [band=" + band + ", price=" + price + ", toSpeed=" + toSpeed + "]";
 }
 
 
}

代码语言:javascript
复制
public class CarDemo { 
 static void test(Car[] car,HashMap map){
  
  //将数组转成集合
  List<Car> list=Arrays.asList(car);
  //过滤价格和速度为负数的车,并且按照toSpeed逆序排序,提取小集合,去重复
  Stream st=list.stream().filter((ss)->ss.getPrice()>0&&ss.getToSpeed()>0).sorted((o1,o2)->(int)(o2.getToSpeed()-o1.getToSpeed())).map(s->s.getBand()).distinct();
  st.forEach(System.out::println);
  Set<Integer> set=map.keySet();
  Stream st1=set.stream().sorted((o1,o2)->o1-o2).limit(3);
  st1.forEach(s->{
   System.out.println("第"+s+"名:"+map.get(s));
  });
 }
 
}
代码语言:javascript
复制
public class CarTest {
 public static void main(String[] args) {
  HashMap<Integer,Car> map=new HashMap<>();
  Car[] car=new Car[5];
  car[0]=new Car("宝马",230,200);
  car[1]=new Car("奔驰",246,456);
  car[2]=new Car("红旗",300,678);
  car[3]=new Car("丰田",500,987);
  car[4]=new Car("宝马",100,134);
  map.put(2, car[0]);
  map.put(1, car[1]);
  map.put(3, car[2]);
  map.put(4, car[3]);
  map.put(7, car[4]);
  CarDemo.test(car,map);
 }
}

结果:

代码语言:javascript
复制
丰田
红旗
奔驰
宝马
第1名:Car [band=奔驰, price=246.0, toSpeed=456.0]
第2名:Car [band=宝马, price=230.0, toSpeed=200.0]
第3名:Car [band=红旗, price=300.0, toSpeed=678.0]

Lambda第二期结束了,期待与你的第三期!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-12-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 java后端指南 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 今日主题:lambda表达式(二)
    • 简介
      • 环境
        • lambda表达式语法精简
          • lambda语法进阶
            • 普通方法引用
            • 构造方法引用
          • 案例
            • 集合排序
            • TreeSet
            • forEach
            • removeif
            • 线程实例化
          • 系统内置函数式接口
            • 流式运算
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档