摘要:自带类库使用表达式实际上中很多自带的类库已经可以使用表达式来调用了,就和我们上面的代码一样。匿名类使用方式表达式同理线程也是可以这样进行改造匿名方法表达式
前面 Java 8之方法引用和Lambda表达式这篇文章讲了方法引用和Lambda表达式的大致原理和使用方法,但是光有理论是不够的,现在这篇文章会讲到它们的实际应用,从最开始的需求一步步的优化代码,直到最后使用Lambda表达式。筛选苹果:
我们现在有个Apple类,它有weight和color属性分别代表它的重量和属性,我们创建多个苹果放入List中,这样就有了很多不同的苹果。
public class Apple { private String color; private Integer weight; public Apple(String color, Integer weight) { this.color = color; this.weight = weight; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public Integer getWeight() { return weight; } public void setWeight(Integer weight) { this.weight = weight; } @Override public String toString() { return "Apple{" + "color="" + color + """ + ", weight=" + weight + "}"; } } public static void main(String[] args) { Listapples = new ArrayList (); Apple apple1 = new Apple("red", 100); Apple apple2 = new Apple("green", 200); Apple apple3 = new Apple("red", 300); Apple apple4 = new Apple("red", 150); apples.add(apple1); apples.add(apple2); apples.add(apple3); apples.add(apple4); }
假设我们现在有个Apple类,它有weight和color属性,现在有个需求,把红色的苹果挑出来,我们就写出了下列的代码。下面这段代码再常见不过了,把未分类的集合传进来,新建一个集合把筛选出来的元素放进去再返回,但是如果需求说要把绿色的都筛选出来呢?难道复制一个吗?那也太傻了,所以我们需要对代码进行改进。
public static ListfilterGreenApples(List apples) { List result = new ArrayList (); for (Apple apple : apples) { if ("green".equals(apple.getColor())) { result.add(apple); } } return result; }
经过我们的改进,把要筛选的颜色也当作参数传进来方法,这样想选什么样颜色就选什么颜色,但是需求永远都是会变得,如果说除了颜色还要再加上重量作为筛选呢?所以我们又对代码进行了改进。
public static ListfilterApplesByColor(List apples, String color) { List result = new ArrayList (); for (Apple apple : apples) { if (apple.getColor().equals(color)) { result.add(apple); } } return result; }
既然要加多重量作为筛选条件,那干脆把重量也当作参数传进去,这个时候我们发现这段代码开始变得很恶心了,在项目很赶的时候很多人会写出类似这种代码,需求是实现了,但是几乎没有什么阅读性可言,而且最多过一个星期,连你自己都可能看不懂自己写的什么东西,而且如果代码没有BUG也就算了,有了隐藏BUG在中途被发现再改的话是越改越乱,所以肯定不能用这样的代码,我们得再改进代码。
public static ListfilterApples(List apples, String color, int weight, boolean flag) { List result = new ArrayList (); for (Apple apple : apples) { if ((flag && apple.getColor().equals(color)) || (!flag && apple.getWeight() > weight)) { result.add(apple); } } return result; }
现在封装方法的方式已经没办法很好的解决问题了,所以我们决定使用设计模式中的策略模式解决这个问题,我们新建一个接口,里面定义一个方法接受Apple参数,然后我们只要实现这个接口重写这个方法,就可以在这个方法里面自定义我们的筛选代码了,我们可以直接用匿名类省去创建类的步骤,这也是最常用的方法,比如新建线程传入Runnable接口就是这样的做法
public interface ApplePredicate { boolean test(Apple apple); } public class AppleHeavyWeightPredicate implements ApplePredicate { public boolean test(Apple apple) { return apple.getWeight() > 150; } } public static ListfilterApples(List apples, ApplePredicate p) { List result = new ArrayList (); for (Apple apple : apples) { if (p.test(apple)) { result.add(apple); } } return result; } //使用匿名类 List redApples = filterApples(apples, new ApplePredicate() { public boolean test(Apple apple) { return "red".equals(apple.getColor()); } });
到现在其实我们的代码已经优化的很好了,实际上Java 8以前很多类库也都是这样实现的,但是这样的做法也有它的问题,那就是一长串的模板代码,阅读性也不怎么好,所以现在要轮到我们的主角上场了,使用Lambda表达式来优化。
Listresult = filterApples(apples, (Apple apple) -> "red".equals(apple.getColor()));
到这里我们其实我们的目的已经实现了,但是我们还可以再改进代码,使这个方法不局限与Apple这个里,只需要加入泛型,就可以成为一个公用的筛选方法了,筛选任意的类型数据。我们把接口接受的参数类型改成泛型,返回的类型也改成泛型,接受的需要筛选的目标集合也改成泛型,这样就是一个可以筛选任何类型的公用方法了。
public interface PredicateJava自带类库使用Lambda表达式:{ boolean test(T t); } public static List filter(List list, Predicate p) { List result = new ArrayList<>(); for (T e : list) { if (p.test(e)) { result.add(e); } } return result; }
实际上Java 8中很多自带的类库已经可以使用Lambda表达式来调用了,就和我们上面的代码一样。
在Java 8中List自带了一个sort方法,接受Comparator(排序)类型参数,按照原来的方式就是是用匿名类,现在我们直接用Lambda表达式。
public interface Comparator{ public int compare(T o1, T o2); } //匿名类使用方式 apples.sort(new Comparator () { public int compare(Apple a1, Apple a2){ return a1.getWeight().compareTo(a2.getWeight()); } }); //Lambda表达式 apples.sort((Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight()));
同理线程也是可以这样进行改造
public interface Runnable{ public void run(); } //匿名方法 Thread t = new Thread(new Runnable() { public void run(){ System.out.println("Hello world"); } }); //Lambda表达式 Thread t = new Thread(() -> System.out.println("Hello world"));
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/71432.html
摘要:方法引用在之前只能进行值传递,方法是不能传递的。首先方法接受了一个类型的对象,方法是获取所有的文件,是用来存储筛选之后的元素,循环所有获得到的文件数组,然后调用中的方法来进行条件筛选,放入后返回。 方法引用: 在Java 8之前只能进行值传递,方法是不能传递的。如果你想调用一个方法你必须先获取到它所在的类的实例,然后再通过实例去调用这个方法,但是Java 8新增了方法引用这个新特性可以...
摘要:表达式简介表达式是一个匿名函数对于而言并不很准确,但这里我们不纠结这个问题。如果表达式的正文有一条以上的语句必须包含在大括号代码块中,且表达式的返回值类型要与匿名函数的返回类型相同。 版权声明:本文由吴仙杰创作整理,转载请注明出处:https://segmentfault.com/a/1190000009186509 1. 引言 在 Java 8 以前,若我们想要把某些功能传递给某些方...
摘要:大家好,上一篇小乐给大家讲述了乐字节核心特性表达式,点击回顾。接下来继续核心特性之函数式接口。感谢大家欣赏小乐带来的核心特性之函数式接口,接下来还会更多核心技术讲解,请关注乐字节如需要视频课程,请搜索乐字节腾讯课堂 大家好,上一篇小乐给大家讲述了《乐字节-Java8核心特性-Lambda表达式》,点击回顾。接下来继续:Java8核心特性之函数式接口。 什么时候可以使用Lambda?通常...
摘要:我们的目标是建立对每一种语言的认识,它们是如何进化的,未来将走向何方。有点的味道是坚持使用动态类型,但唯一还收到合理拥泵的编程语言,然而一些在企业的大型团队中工作的开发者择认为这会是的一个缺陷。 为什么我们需要如此多的JVM语言? 在2013年你可以有50中JVM语言的选择来用于你的下一个项目。尽管你可以说出一大打的名字,你会准备为你的下一个项目选择一种新的JVM语言么? 如今借助来自...
摘要:使用表达式,使得应用变得简洁而紧凑。很多语言等从设计之初就支持表达式。表达式的参数与函数式接口内方法的参数,返回值类型相互对应。更多教程和资料请上腾讯课堂乐字节 showImg(https://segmentfault.com/img/bVbtotg?w=935&h=345); Java8 引入Lambda表达式,允许开发者将函数当成参数传递给某个方法,或者把代码本身当作数据进行处理。...
阅读 1358·2019-08-30 12:54
阅读 1837·2019-08-30 11:16
阅读 1570·2019-08-30 10:50
阅读 2401·2019-08-29 16:17
阅读 1238·2019-08-26 12:17
阅读 1353·2019-08-26 10:15
阅读 2363·2019-08-23 18:38
阅读 756·2019-08-23 17:50