• Home
  • Archives
  • 随笔
所有文章 友链 关于我

  • Home
  • Archives
  • 随笔

JDK8特性学习附案例

发布于: 2022-02-13
更新于: 2023-07-09

JDK8

Lambda

Lambda expression ennable u to treat functionality as method argument, or code as data.
将 function 作为方法参数,或将代码视为数据

参考文档:^1

package com.tyrantqiao.algorithms.lambda;

import java.util.List;

/**
 * @author tyrantqiao
 * @ClassName PersonBusiness
 * @date 2022/2/13 15:41
 * @version 1.0
 * @Description 个人业务的报表查询
 */
public class PersonBusiness {
    public static String filterPersonsWithinAgeRange(List<Person> personList, int low, int high){
        StringBuilder stringBuilder=new StringBuilder();
        for(Person person:personList){
            if(person.getAge()>=low && person.getAge()<=high){
                stringBuilder.append(person.getName()).append("|");
            }
        }
        return stringBuilder.toString();
    }
}

        System.out.println(PersonBusiness.filterPersonsWithinAgeRange(personList, 0, 100));

像以前就是来一份业务写一份 static 以及涉及到的业务代码,方法等都要写死

但根据抽象时,我们可以发现这部分代码要实现的逻辑都是过滤

if(filterBoolean(personList)){
    stringBuilder.append(xxx);
}

由于 Java 不支持将 function 作为参数传递,所以此处我们需要将 filterBoolean 转为 interface 接口


    interface FilterPerson {
        boolean filter(Person person);
    }

    public static String filterPersonsWithinAgeRange(List<Person> personList, FilterPerson filterPerson) {
        StringBuilder stringBuilder = new StringBuilder();
        for (Person person : personList) {
            if (filterPerson.filter(person)) {
                stringBuilder.append(person.getName()).append("|");
            }
        }
        return stringBuilder.toString();
    }


    @Test
    void testFilterPersonsWithinAgeRange() {
        System.out.println(PersonBusiness.filterPersonsWithinAgeRange(personList, new PersonBusiness.FilterPerson() {
            @Override
            public boolean filter(Person person) {
                if (person.getAge() >= 5 && person.getAge() <= 100) {
                    return true;
                }
                return false;
            }
        }));
    }

可以将上面的匿名接口类抽出来实现类再操作,但这样子的代码就显得十分臃肿了


    @Test
    void testFilterPersonsWithinAgeRangeByLambda() {
        System.out.println(
                PersonBusiness.filterPersonsWithinAgeRange(personList,
                        person -> person.getAge() >= 5 && person.getAge() <= 100
                )
        );
    }

JDK 针对以上的这些场景也设计了一些基本业务场景的@FunctionInterface

@FunctionalInterface
public interface Predicate<T> {

    /**
     * Evaluates this predicate on the given argument.
     *
     * @param t the input argument
     * @return {@code true} if the input argument matches the predicate,
     * otherwise {@code false}
     */
    boolean test(T t);

    /**
     * Returns a composed predicate that represents a short-circuiting logical
     * AND of this predicate and another.  When evaluating the composed
     * predicate, if this predicate is {@code false}, then the {@code other}
     * predicate is not evaluated.
     *
     * <p>Any exceptions thrown during evaluation of either predicate are relayed
     * to the caller; if evaluation of this predicate throws an exception, the
     * {@code other} predicate will not be evaluated.
     *
     * @param other a predicate that will be logically-ANDed with this
     *              predicate
     * @return a composed predicate that represents the short-circuiting logical
     * AND of this predicate and the {@code other} predicate
     * @throws NullPointerException if other is null
     */
    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }

Predicate 起到断言,test 获得 true、false 的内容

在看刚刚的代码,我们也可以发现对于过滤后的对象操作,也属于一件过滤后加工的行为,也可以进行一个抽象,这里用到的是Consumer<T> block.accept(t)


    public static void filterPersonsWithinAgeRangeByLambda(List<Person> personList, Predicate<Person> filterPerson,
                                                           Consumer<Person> consumer) {
        for (Person person : personList) {
            if (filterPerson.test(person)) {
                consumer.accept(person);
            }
        }
    }


    @Test
    void filterPersonsWithinAgeRangeByLambda() {
        PersonBusiness.filterPersonsWithinAgeRangeByLambda(personList,
                person -> person.getAge()>=5,
                person-> System.out.println(person.getName()));
    }

在处理对象时,我们可以看到是通过 person.getName()进行打印名字,假如说我们需要打印年龄,又会需要再写一个方法进行调用,像这种需要对对象进行操作,来获得一个值的操作可以使用Function<T,R> mapper.apply(t);



    public static void filterPersonsWithinAgeRangeByFunction(List<Person> personList,
                                                             Predicate<Person> filterPerson,
                                                             Function<Person, String> functionPerson,
                                                             Consumer<String> consumer) {
        for (Person person : personList) {
            if (filterPerson.test(person)) {
                consumer.accept(functionPerson.apply(person));
            }
        }
    }


    @Test
    void filterPersonsWithinAgeRangeByFunction() {
        PersonBusiness.filterPersonsWithinAgeRangeByFunction(personList,
                person -> person.getAge() >= 5,
                person -> String.valueOf(person.getAge()),
                msg -> System.out.println(msg));
    }

总结来说:这段代码实现的内容为

  1. 获取Collection数据源,实现了 List 和 Iteration 的接口
  2. 通过 Predicate 进行过滤
  3. 通过 Maps 对过滤后对象进行映射为想要的值
  4. 对于映射后的值做相应 Consumer 的处理操作
personList.stream()
    .filter(p->p.getAge()>=5)
    .map(p->p.getName())
    .forEach(name->System.out.print(name));

interface

default 默认方法

由于接口一定要实现方法,但是有时需要增加一些默认方法,但不需要所有实现接口的方法都实现一次时,可以通过默认方法进行补充实现

interface FilterPerson{
    boolean filter(Person person);

    default boolean filterPersonByAge(Person person){
        return person.getAge()>=5;
    }
}
@FunctionalInterface
public interface Consumer<T> {

    /**
     * Performs this operation on the given argument.
     *
     * @param t the input argument
     */
    void accept(T t);

    /**
     * Returns a composed {@code Consumer} that performs, in sequence, this
     * operation followed by the {@code after} operation. If performing either
     * operation throws an exception, it is relayed to the caller of the
     * composed operation.  If performing this operation throws an exception,
     * the {@code after} operation will not be performed.
     *
     * @param after the operation to perform after this operation
     * @return a composed {@code Consumer} that performs in sequence this
     * operation followed by the {@code after} operation
     * @throws NullPointerException if {@code after} is null
     */
    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

在实现了两个接口,含有同名方法时,需要 override,不然无法执行对应的函数

package com.tyrantqiao.algorithms.interview;

import com.tyrantqiao.algorithms.lambda.Person;

/**
 * @author tyrantqiao
 * @ClassName JDK8InterfaceMethod
 * @date 2022/2/13 17:15
 * @Version 1.0
 * @Description jdk8 interface 的默认方法和静态方法
 */
public class JDK8InterfaceMethod {
    interface House {
        void live(Person person);

        default void log(Person person) {
            System.out.println("live person:" + person.getName());
        }
    }

    interface Car {
        void drive(Person person);

        default void log(Person person) {
            System.out.println("drive car:" + person.getName());
        }
    }

    class NewJob implements House, Car {

        @Override
        public void live(Person person) {

        }

        /**
         * 因为实现的两个接口都有default的同名方法,所以需要override方法,实现自己独有的内容
         *
         * @param person person
         */
        @Override
        public void log(Person person) {
            System.out.println("new job contains house and car," + person.getName());
        }

        @Override
        public void drive(Person person) {

        }
    }
}

静态方法

静态方法其实和默认方法差不多,不同就是来自于 static 的差异了,可以通过类进行执行,实现方法不能进行 override,保证了方法可以作为应用的统一类型接口

        static boolean isNull(Person person) {
            return Objects.isNull(person);
        }

比如像 Comparator 的比较方法,作为比较的基类方法进行提供,同时有抽象的能力,这样子实现的接口不用再实现自己的逻辑,避免这个方法受到污染。

    public static <T, U> Comparator<T> comparing(
            Function<? super T, ? extends U> keyExtractor,
            Comparator<? super U> keyComparator)
    {
        Objects.requireNonNull(keyExtractor);
        Objects.requireNonNull(keyComparator);
        return (Comparator<T> & Serializable)
            (c1, c2) -> keyComparator.compare(keyExtractor.apply(c1),
                                              keyExtractor.apply(c2));
    }
JDK8特性学习附案例
/archives/b97b30cf/
作者
tyrantqiao
发布于
2022-02-13
更新于
2023-07-09
许可协议
CC BY-NC-SA 4.0
赏

蟹蟹大佬的打赏,大家一起进步

支付宝
微信
  • Java
  • jdk

扫一扫,分享到微信

微信分享二维码
2023规划
程序员思考之道
© 2024 tyrantqiao 本站总访问量次 本站访客数人次 载入天数...载入时分秒...
  • 所有文章
  • 友链
  • 关于我

tag:

  • 复盘
  • 我
  • 规划
  • java
  • 面试
  • 源码
  • 架构
  • Hadoop
  • HTTP
  • TCP
  • 学习笔记
  • IDEA
  • maven
  • idea
  • Java
  • jdk
  • 面经
  • linux
  • 爱情
  • mysql
  • 性能
  • sql
  • Mysql
  • JAVA
  • 技术
  • Redis
  • MQ
  • Spring
  • 数据库
  • TIDB
  • spring
  • unity
  • chatgpt
  • 经验分享
  • 前端
  • redis
  • vue
  • git
  • shadowsocks
  • hexo
  • blog
  • bug
  • 开发
  • 业务
  • jvm
  • 算法
  • MySQL
  • nginx
  • Linux
  • mq
  • db
  • springCloud
  • ssh
  • python
  • 爬虫
  • test
  • vim
  • 影视剧
  • 中间件
  • 事务
  • 性格
  • 音乐
  • 程序员
  • 随笔
  • mybatis
  • 演讲
  • 域名
  • 猫咪
  • 她
  • github
  • 计划
  • 旅游
  • 软件
  • 心理
  • 情商
  • 幽默
  • 才艺
  • 穿搭
  • 编程
  • 排序
  • 查找
  • 缓存
  • 网络
  • 设计模式
  • c
  • 课程设计
  • centos
  • 数学
  • 本网站主题yilia设计者的主页
如果有问题或者想讨论的可以联系[email protected]或者[email protected]