扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
Java8中Lambda的特性是什么,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。
创新互联公司是一家集网站设计、成都做网站、网站页面设计、网站优化SEO优化为一体的专业网络公司,已为成都等多地近百家企业提供网站建设服务。追求良好的浏览体验,以探求精品塑造与理念升华,设计最适合用户的网站页面。 合作只是第一步,服务才是根本,我们始终坚持讲诚信,负责任的原则,为您进行细心、贴心、认真的服务,与众多客户在蓬勃发展的市场环境中,互促共生。
入门最快就是看demo啦,现在有个需求,让你在众多苹果中挑选出红色的苹果
苹果类
public class Apple { String color; int weight; //省略构造函数,get方法 }
public static ListfilterGreenAppleWithNormal(List apples) { List res = new ArrayList<>(); for (Apple apple : apples) { if ("red".equals(apple.getColor())) { res.add(apple); } } return res; } //调用 List normal = filterGreenAppleWithNormal(apples);
如果再有一个需求说挑选出绿色的苹果呢,按照这种写法就需要创建一个新的类,然后仅仅把"red"
修改成"green"
其它都不变,这明显是不显示的。所以可以把颜色当成参数传进去
public static ListfilterGreenAppleWithArg(List apples, String color) { List res = new ArrayList<>(); for (Apple apple : apples) { if (color.equals(apple.getColor())) { res.add(apple); } } return res; } //调用 List arg = filterGreenAppleWithArg(apples, "red");
此时再有一个需求,需要筛选出一定重量或者某个颜色的苹果,需要怎么办呢,按照上述想法是把能想到的属性都堆到方法的参数中。
public static ListfilterWeightOrColorWithArg(List apples, String color, int weight, boolean flag) { List res = new ArrayList<>(); for (Apple apple : apples) { if (flag && color.equals(apple.getColor()) || !flag && apple.getWeight() > weight) { res.add(apple); } } return res; } //调用 List weightOrColor = filterWeightOrColorWithArg(apples, "", 500, false);
可以这样写吗,当然可以解决问题,但是如果有5个属性呢,6个属性呢,还有,参数中的flag是什么意思呢。
仔细一想,筛选颜色,筛选重量,这些的本质是在筛选,是一个行为(后面更专业称谓语),可以把行为抽象成一个接口。
行为接口
public interface AppleFilter { boolean filter(Apple apple); }
首先需要实现这个接口来具体化行为
筛选红色苹果实现类
public class RedFilter implements AppleFilter { @Override public boolean filter(Apple apple) { return "red".equals(apple.getColor()); } }
回到使用
public static ListfilterApples(List apples, AppleFilter filter) { List res = new ArrayList<>(); for (Apple apple : apples) { if (filter.filter(apple)) { res.add(apple); } } return res; } //调用 List behavior = filterApples(apples, new GreenFilter());
这样看就舒服多了,当有新需求的时候,只需要再添加一个类,比如需求是筛选出重量超200g的苹果,只需要新建一个筛选类实现上述接口即可。
public class WeightGt200Filter implements AppleFilter { @Override public boolean filter(Apple apple) { return apple.getWeight() > 200; } }
还能怎样精简代码呢?熟悉Java的小伙伴到这里应该就想到了匿名内部类
ListinnerClass = filterApples(apples, new AppleFilter() { @Override public boolean filter(Apple apple) { return "green".equals(apple.getColor()); } });
一般到这一步,比较不错的IDE就会开始提醒建议了
这就到了我们今天的重点,lambda表达式
Listlambda = filterApples(apples, apple -> apple.getWeight() > 500);
没错,就是这么精简,不过filterApples
这个方法是不能省略的,但是扩展性相较1,2,简洁性相较3,4都好了很多
可以把Lamdba表达式理解为简洁地表示可传递的匿名函数的一种形式:它没有名称,但它有参数列表、函数主题、返回类型,可能还有一个可以抛出的异常列表
书写格式:(参数) -> {主体}
正如上面写法5一样(apple) -> {apple.getWeight() > 500;}
lambda表达式对参数能够自动推断类型,当然也可以显示书写类型
没有return语句,应为已经有隐含了return
lambda中可以有多行语句
使用案例:
() -> {}
() -> "java"
() -> {return "java";}
(int a, int b) -> a * b
() -> {System.out.println("hello"); System.out.println("java");}
使用函数式接口的时候才能使用lambda表达式
所谓函数式接口就是仅仅定义了一个抽象方法,比如一开始把行为抽象成一个AppleFilter
接口,该接口只有一个filter()
方法。注意是只有一个抽象方法,并不是只有一个方法,通俗来说是继承该接口的类只需要实现一个方法。
最常见的两个接口是Comparator
和Runnable
后来为了更方便地区分函数式接口,Java新的API中多了一个@FuntionalInterface
,该注解仅仅是表明该类是函数式接口(并不是必须的),如果有该注解的同时声明了两个抽象方法,那么将会报错
java.util.function
下主要有4个常用的函数式接口,Function
,Predicate
,Consumer
,Predicate
,随便截取其中的一个源码片段来看,其实也没啥好看的
对这些函数式接口也是得看接口是如何声明的,这里就拿Predicate
举例,该接口主要是对传进来的对象进行一个处理,然后返回boolean
值。是不是有点熟悉,没错,就是和筛选苹果一样
predicateDemo
public static ListpredicateDemo(List apples, Predicate predicate) { List res = new ArrayList<>(); for (Apple apple : apples) { if (predicate.test(apple)) { res.add(apple); } } return res; } //调用 List predicate = predicateDemo(apples, apple -> "green".equals(apple.getColor()));
其他的也是同理,上才艺
functionDemo
public static ListfunctionDemo(List nums, Function function) { List res = new ArrayList<>(); for (int num : nums) { res.add(function.apply(num)); } return res; } //调用 List function = functionDemo(Arrays.asList(1, 8, 7, 3, 9, 2), (num) -> num * 2);
consumerDemo
public static void consumerDemo(Listlist, Consumer consumer) { for (int num : list) { consumer.accept(num); } } //调用 consumerDemo(Arrays.asList(1, 5, 6), (num) -> System.out.println(num)); consumerDemo(Arrays.asList(1, 5, 6), System.out::println);
supplierDemo
public static void supplierDemo(Listnums, Supplier supplier) { StringBuilder sb = new StringBuilder(); for (int num : nums) { sb.append(num).append(supplier.get()); } System.out.println(sb); } //调用 supplierDemo(Arrays.asList(1, 5, 6), ()->"java");
上面的lambda写法是最精简的吗,不,不是的,还有最最最精简的写法,那就是利用方法引用
方法引用主要有3类:
指向静态方法的方法引用
ComparatornormalComparator = (a, b) -> a.compareTo(b); Comparator referenceComparator = Integer::compareTo;
指向任一类型实例方法的方法引用
FunctionnormalFunction = (str) -> str.length(); Function referenceFunction = String::length; BiPredicate , String> normalPredicate = (strings, str) -> strings.contains(str); BiPredicate
, String> referencePredicate = List::contains;
指向现有对象的实例方法引用
Apple apple = new Apple(); Suppliernormal = () -> apple.getWeight(); Supplier reference = apple::getWeight;
当然也可以用于构造函数
SuppliernormalSupplier = () -> new Apple(); Supplier referenceSupplier = Apple::new;
看完上述内容,你们掌握Java8中Lambda的特性是什么的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注创新互联行业资讯频道,感谢各位的阅读!
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流