java8学习:通过行为参数化传递代码
内容来自《 java8实战 》,本篇文章内容均为非盈利,旨为方便自己查询、总结备份、开源分享。如有侵权请告知,马上删除。
书籍购买地址:java8实战
-
如下一段代码请看
@Test public void test() throws Exception { List<Apple> list = new ArrayList<>(); for (Apple apple : list) { if (apple.getWeight() > 1000){ System.out.println("..."); } } }
- 这段代码再简单不过了,并且完成了该完成的判断条件,但是如果现在并不是想判断重量weight了,而是需要判断color是不是红色的了,那么就只能代码复制然后改条件了,如下
@Test public void test() throws Exception { List<Apple> list = new ArrayList<>(); for (Apple apple : list) { if ("red".equals(apple.getColor())){ System.out.println("..."); } } }
- 此时发现,除了更改了if条件,其他地方是没有动的,但是如果我又需要更改别的条件呢,无奈只好再次变换if条件,针对这一的情况,java8的行为参数化就可以处理频繁的变更
-
行为参数化
- 如上的筛选苹果颜色的代码,这时候我突然想要绿色的或者彩虹色可咋办难道还要拷贝?
public void getAppleByColor(List<Apple> apples,String color){ for (Apple apple : apples) { if (color.equals(apple.getColor())){ System.out.println("..."); } } } //getAppleByColor(lists,"red"); //调用
-
- 上面这段代码就解决了一直变更的颜色的问题,任他来的是透明颜色都没问题,并且调用方法时,也可以清晰的看出来我们需要的是什么苹果
- 苹果大卖钱就多,那么如果按照重量筛选呢?代码已经给出来了,那么就是开篇的第二段代码,仔细想一下虽然解决了我们的问题,但是是不是代码重复的太多了,并且这样的编程风格十分不好,违反了DRY(don't repeat yourself),这时候我们就可能想到了进一步的解决办法来应对重量和颜色的不同选择,那就是立flag,如下
public void getAppleByColor(List<Apple> apples,String color,Integer weight,boolean isColor){ for (Apple apple : apples) { if ((isColor && color.equals(apple.getColor())) || !isColor && weight > apple.getWeight()){ System.out.println("..."); } } } getAppleByColor(lists,"red",0,true); //调用 getAppleByColor(lists,"",123,false); //调用
- 如上,调用简直不能再糟了,如果不让调用者看到方法的方法签名和解释,那么他肯定不会知道true代表啥false代表啥,所以这种方法解决此问题是十分不可取的,那么我们肯定就需要更好的解决方案
- 思路:建立一个接口,那么就有类去实现接口,那么每个实现类不就代表一种行为吗?比如这样改
interface FilterApple{ boolean filter(Apple apple); } class FilterRedApple implements FilterApple{ @Override public boolean filter(Apple apple) { return "red".equals(apple.getColor()); } } class FilterAppleByWeight implements FilterApple{ @Override public boolean filter(Apple apple) { return apple.getWeight() > 1000; } } public class Java8 { @Test public void test() throws Exception { List<Apple> apples = Arrays.asList(); getAppleByColor(apples,new FilterAppleByWeight()); getAppleByColor(apples,new FilterRedApple()); } public void getAppleByColor(List<Apple> apples,FilterApple filter){ for (Apple apple : apples) { if (filter.filter(apple)) { System.out.println("...."); } } } }
- 如上代码有点长但是十分的简单,在上面我们可以看到,我们利用了多态的特性来用不同的实现类来实现不同需求的过滤,如果以后把苹果分男女,那么我们只需要增加一个
FilterAppleByJJ
就可以了
- 引出:如上就是一种行为参数化,让方法接受多种行为作为参数,并在内部使用,来完成不同的行为
- 在上面的例子中,唯一重要的也就是filter的实现,但是我们写的方法只能接受一个FilterApple对象,所以必须把不同的实现代码包裹在此对象中。这就好像你借别人钱还要拿纸包起来,不仅老套而且人家关心的只是钱的问题,纸随便就给扔掉了,在这我们不同实现类中的实现的不同逻辑就是借的钱,就比如下面这样
- 但是对于上面的写法有点太啰里啰嗦的了,实现一个过滤就要实现一个接口?这时候就应该能想到匿名内部类了把~
@Test public void test() throws Exception { List<Apple> apples = Arrays.asList(); getAppleByColor(apples, new FilterApple() { @Override public boolean filter(Apple apple) { return apple.getWeight() > 1000; } }); } public void getAppleByColor(List<Apple> apples,FilterApple filter){ for (Apple apple : apples) { if (filter.filter(apple)) { System.out.println("...."); } } }
- 但是匿名内部类还是存在很多的问题,1.就是样本代码太多,2.那么就是不清楚,比如下面这个,你来看看输出什么,答案在最下面
public class Java8 { private final int value = 4; public void doIt(){ int value = 6; Runnable runnable = new Runnable() { public final int value = 5; @Override public void run() { int value = 10; System.out.println(this.value); } }; runnable.run(); } public static void main(String[] args) { new Java8().doIt(); } }
- 匿名内部类的弊端:在只需要传递一段简单的代码时,还是需要创建一个对象,明确的实现一个方法来定义一个新的行为
-
上面的问题来充实Lambda表达式解决
@Test public void test() throws Exception { List<Apple> apples = Arrays.asList(); getAppleByColor(apples,(apple) -> apple.getWeight() > 1000); } public void getAppleByColor(List<Apple> apples,FilterApple filter){ for (Apple apple : apples) { if (filter.filter(apple)) { System.out.println("...."); } } }
-
- 爽的一批,对于lambda以后会继续说的
- 但是还有个问题,这个只能是过滤Apple把,如果我还有西瓜之类的呢,那么代码就可以引入泛型T
interface Filter<T>{ boolean filter(T t); } public class Java8 { @Test public void test() throws Exception { List<Apple> apples = Arrays.asList(); getAppleByColor(apples,apple -> apple.getWeight() > 1000); } public <T> void getAppleByColor(List<T> ts,Filter<T> filter){ for (T t : ts) { if (filter.filter(t)){ System.out.println("..."); } } } }
- 这时候就想过滤什么就过滤什么了
@Test public void test() throws Exception { List<Apple> apples = Arrays.asList(); apples.sort(Comparator.comparing(Apple::getWeight)); } or @Test public void test() throws Exception { List<Apple> apples = Arrays.asList(); apples.sort((a1,a2) -> a1.getWeight().compareTo(a2.getWeight())); }
- Runnable
@Test public void test() throws Exception { Runnable runnable = ()->{ System.out.println("run"); }; runnable.run(); }
- 好了上面是两个例子仅供参考
- 答案:5
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
java8学习:入门
内容来自《 java8实战 》,本篇文章内容均为非盈利,旨为方便自己查询、总结备份、开源分享。如有侵权请告知,马上删除。书籍购买地址:java8实战 sync的使用成本:多核CPU的每个处理器内核都有独立的告诉缓存,加锁需要这些告诉缓存同步运行,然而这有需要在内核间进行较慢的缓存一致性协议通信 流处理 流是一系列数据项,一次只生成一项。程序可以从输入流中一个个读取数据项,然后以 相同的方式将数据项写入输出流 拿Linux的管道命令来演示流过程 如上熟悉linux都清楚cat file1 file2会创建两个文件的输出流,如果加上>那么就会生成一个合并了File1和file2的新文件,cat产生的数据流会通过管道传送给tr进行内容过滤,符合条件的又会传入下一个sort方法进行排序,最后sort排序完成的结果集交给tail -3取三行,至此流算是结束了。这些的流处理行为是高效的,因为cat的数据读一条就会传给tr过滤,tr后传入sort,sort就能在cat或tr完成前先处理几行 基于上面的思想,java8引入了Stream,这样的好处是并行能力得到了极大的提升,并且站在了更高的抽象...
- 下一篇
java8学习:lambda表达式(1)
内容来自《 java8实战 》,本篇文章内容均为非盈利,旨为方便自己查询、总结备份、开源分享。如有侵权请告知,马上删除。书籍购买地址:java8实战 上一篇内容解释了行为参数化的概念并用实例演示了如何是行为参数化,文末提到了lambda表达式,那么本文将讲解lambda表达式 如平常的使用方法如下 Comparator<Apple> comparator = new Comparator<Apple>() { @Override public int compare(Apple o1, Apple o2) { return Integer.compare(o1.getWeight(),o2.getWeight()); } }; lambda:Comparator<Apple> comparator = (Apple a1,Apple a2) -> Integer.compare(a1.getWeight(),a2.getWeight()); 对照上面的普通使用方法和lambda,lambda没有名称,但是一样有参数列表,函数主体以及返回值,还可...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
-
Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8编译安装MySQL8.0.19
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
推荐阅读
最新文章
- SpringBoot2全家桶,快速入门学习开发网站教程
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- MySQL8.0.19开启GTID主从同步CentOS8
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2整合Redis,开启缓存,提高访问速度
- Windows10,CentOS7,CentOS8安装Nodejs环境
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果