java8学习:通过行为参数化传递代码

简介: 内容来自《 java8实战 》,本篇文章内容均为非盈利,旨为方便自己查询、总结备份、开源分享。如有侵权请告知,马上删除。书籍购买地址:[java8实战] 如下一段代码请看 @Test public void test() throws Exception { List li.

内容来自《 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对象,所以必须把不同的实现代码包裹在此对象中。这就好像你借别人钱还要拿纸包起来,不仅老套而且人家关心的只是钱的问题,纸随便就给扔掉了,在这我们不同实现类中的实现的不同逻辑就是借的钱,就比如下面这样

markdown_img_paste_20181106090528506

  • 但是对于上面的写法有点太啰里啰嗦的了,实现一个过滤就要实现一个接口?这时候就应该能想到匿名内部类了把~
@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("...");
                }
            }
        }
}
  • 这时候就想过滤什么就过滤什么了
Comparator排序
@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
目录
相关文章
|
23小时前
|
Java Apache
Java代码使用POI导出的单元格加上边框和背景色
【5月更文挑战第3天】Java代码使用POI导出的单元格加上边框和背景色
13 0
|
23小时前
|
Java Apache
Java代码使用POI导出的单元格的字体加粗设置
【5月更文挑战第3天】Java代码使用POI导出的单元格的字体加粗设置
13 1
|
4天前
|
Java
如何解决使用若依前后端分离打包部署到服务器上后主包无法找到从包中的文件的问题?如何在 Java 代码中访问 jar 包中的资源文件?
如何解决使用若依前后端分离打包部署到服务器上后主包无法找到从包中的文件的问题?如何在 Java 代码中访问 jar 包中的资源文件?
22 0
|
6天前
|
Java Spring
Java 效率编码 必备插件 Lombok 让代码更优雅
该内容是一个关于Lombok插件的教程摘要:介绍了Lombok用于减少Java开发中的模板代码,提升效率;讲解了如何在IntelliJ IDEA中安装Lombok插件,以及在pom.xml中添加依赖;并提到了@Data注解能自动生成getter/setter、equals、hashCode和toString方法,@Slf4j注解自动处理日志,@Builder用于构建对象,以及@AllArgsConstructor和@NoArgsConstructor注解生成构造函数。还鼓励探索更多Lombok的注解用法。
|
6天前
|
Java 关系型数据库 测试技术
Java代码一键生成数据库文档(案例详解)
Screw是一个自动化数据库文档生成工具,能根据数据库表结构快速生成简洁、多格式(HTML、Word、Markdown)的文档,支持MySQL、MariaDB等多数据库。它使用Freemarker模板,允许用户自定义样式。依赖包括HikariCP数据库连接池和对应JDBC驱动。通过在Java代码或Maven插件中配置,可方便生成文档。示例代码展示了如何在测试用例中使用Screw。文档效果依赖于数据库中的表和字段注释。
|
6天前
|
NoSQL Java API
java一行代码实现RESTFul接口
Spring Data REST是构建在Spring Data之上的库,可自动将repository转换为REST服务,支持JPA、MongoDB、Neo4j、GemFire和Cassandra。无需手动创建Service和Controller层。要开始,需配置JPA数据源,创建实体类和Repository接口。快速实现REST接口,只需引入spring-boot-starter-data-rest Maven依赖,并在Repository接口上添加@RepositoryRestResource注解。
|
7天前
|
算法 Java 大数据
Java从入门到精通学习报告
Java从入门到精通学习报告
14 1
|
1天前
|
Java
Java中的多线程编程:基础知识与实践
【5月更文挑战第5天】在现代软件开发中,多线程编程是一个重要的概念,尤其是在Java这样的多平台、高性能的编程语言中。通过多线程,我们可以实现并行处理,提高程序的运行效率。本文将介绍Java中多线程编程的基础知识,包括线程的概念、创建和控制方法,以及一些常见的多线程问题和解决方案。
|
4天前
|
存储 缓存 前端开发
Java串口通信技术探究3:RXTX库线程 优化系统性能的SerialPortEventListener类
Java串口通信技术探究3:RXTX库线程 优化系统性能的SerialPortEventListener类
20 3
|
4天前
|
Java
JAVA难点包括异常处理、多线程、泛型和反射,以及复杂的分布式系统知识
JAVA难点包括异常处理、多线程、泛型和反射,以及复杂的分布式系统知识。入坑JAVA因它的面向对象特性、平台无关性、强大的标准库和活跃的社区支持。
19 2