写给大忙人看的 Java SE 8 第一章练习 答案 <函数式编程>

本文通过多个示例展示了Java 8中Lambda表达式的应用,包括文件操作、线程处理及集合操作等,帮助读者理解如何利用Lambda提高代码效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前几年就开始接触Java的lambda 表达式,一开始觉得难懂,研究一段时间之后,发现确实能带来很多好处,不仅性能提升了,而且代码也变得简洁了很多。

当你走进函数式编程的世界以后,发现编程的思维都改变了,简化了很多中间代码,让你高效的完成你想做的事情。

今天翻了一下 《写给大忙人看的 JavaSE 8》 这本书,发现习题有点意思,网上简单找了一下,没找到答案,就自己做了一下。如果你有更好的实现,欢迎评论。下面是代码,就是一个 Junit 测试类(方法前缀表明了 第几章的第几题)

package com.ph.daily.java8;

import org.junit.Test;

import java.io.File;
import java.io.FilenameFilter;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * Created by Kano on 2017/5/24.
 */
public class TestC1 {
    /**
     * 比较器 的线程 和 调用 sort 的线程
     * 是同一个 线程
     */
    @Test
    public void _01_01_sortThread() {
        String[] strings = {"aaa", "b", "cc"};
        System.out.println(Thread.currentThread().getName());
        Arrays.sort(strings, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                System.out.println(Thread.currentThread().getName());
                return Integer.compare(o1.length(), o2.length());
            }
        });
    }

    /**
     * 找出某个 文件夹下 所有子文件夹
     * Java 6 的写法
     */
    @Test
    public void _01_02_subDir_6() {
        String dir = "Y:\\";
        String[] list = new File(dir).list(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                return new File(dir, name).isDirectory();
            }
        });
        Arrays.stream(list).forEach(System.out::println);
    }

    /**
     * 找出某个 文件夹下 所有子文件夹
     * lambda 的写法
     */
    @Test
    public void _01_02_subDir_lambda() {
        String dir = "Y:\\";
        String[] list = new File(dir).list((dir1, name) -> new File(dir1, name).isDirectory());
        Arrays.stream(list).forEach(System.out::println);
    }

    /**
     * 找出某个 文件夹下 所有子文件夹
     * 方法引用 的写法
     * (这个我感觉比较别扭)
     */
    @Test
    public void _01_02_subDir_method() {
        String dir = "Y:\\";
        List<String> list = Arrays.stream(new File(dir).list())
                .map(name -> new File(dir, name))
                .filter(File::isDirectory)
                .map(File::getName)
                .collect(Collectors.toList());
        list.stream().forEach(System.out::println);
    }

    /**
     * 返回某个目录下 指定扩展名 的文件
     * Java 6 的写法
     */
    @Test
    public void _01_03_listFiles() {
        String dir = "H:\\";
        String ext = "msi";
        File[] list = new File(dir).listFiles(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                return name.endsWith(ext);
            }
        });
        Arrays.stream(list).map(file -> file.getName()).forEach(System.out::println);
    }

    /**
     * 返回某个目录下 指定扩展名 的文件
     * lambda 的写法
     * (会捕获薄荷作用域中的 ext 变量)
     */
    @Test
    public void _01_03_listFiles_lambda() {
        String dir = "H:\\";
        String ext = "msi";
        File[] list = new File(dir).listFiles((dir1, name) -> name.endsWith(ext));
        Arrays.stream(list).map(file -> file.getName()).forEach(System.out::println);
    }

    /**
     * 给定的 file 数组 进行排序,规则是
     *  首先按照目录排序,如果目录相同,则按照文件的路径排序
     *
     * lambda 实现
     */
    @Test
    public void _01_04_file_sort() {
        File[] files = new File[5];
        files[0] = new File("C:\\Windows\\addins\\FXSEXT.ecf");
        files[1] = new File("C:\\Windows\\Cnxt\\setup5776297E157xyz\\FXSEXT.ecf");
        files[2] = new File("C:\\Windows\\AppPatch\\pcamain.sdb");
        files[3] = new File("C:\\Windows\\Cnxt\\setup5776297E157xyz\\DtsHpxInit64.dll");
        files[4] = new File("C:\\Windows\\AppPatch\\frxmain.sdb");

        Arrays.sort(files, (File o1, File o2) ->
                o1.getParent().equals(o2.getParent()) ?
                        o1.getPath().compareTo(o2.getPath()) : o1.getParent().compareTo(o2.getParent())
        );
        Arrays.stream(files).map(File::getAbsolutePath).forEach(System.out::println);

    }


    /**
     * 用 lambda 实现 Runnable
     */
    @Test
    public void _01_05_thread() {
        new Thread(() -> {
            System.out.println(Thread.currentThread().getName());
        });
    }


    /**
     *  改造 Runnable 结构,让其可以抛出异常
     *  (需要定义一个 接口)
     */
    @Test
    public void _01_06_thread_uncheck() {
        new Thread(RunnableEx.uncheck(() -> {
            System.out.println("sdfsd");
            Thread.sleep(100); //不用 捕获异常
        })).start();
    }

    interface RunnableEx {
        void run() throws Exception;

        static Runnable uncheck (RunnableEx runner){
            return () -> {
                try {
                    runner.run();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            };
        }
    }

    /**
     *  写一个 andThen 方法,传递两个 Runnable 实例
     *  返回一个 分别运行这两个实例的 Runnable 实例
     */
    @Test
    public void _01_07_andThen() {
        Runnable then = andThen(
                () -> System.out.println("12"),
                () -> System.out.println("34")
        );

        new Thread(then).start();
    }

    private static Runnable andThen(Runnable r1,Runnable r2){
        return ()->{
            new Thread(r1).start();
            new Thread(r2).start();
        };
    }

    /**
     *  这样写没问题
     */
    @Test
    public void _01_08_for() {
        String[] names={"zhangsan","lisi","wangwu"};
        List<Runnable> runners=new ArrayList<>();
        for (String name : names) {
            runners.add(()-> System.out.println(name));
        }
        runners.stream().map(Thread::new).forEach(Thread::start);
    }

    /**
     * 这样写  有问题
     */
    @Test
    public void _01_08_fori() {
        String[] names={"zhangsan","lisi","wangwu"};
        List<Runnable> runners=new ArrayList<>();
        for (int i = 0; i < names.length; i++) {
            // 这么写就会有问题,因为 lambda 表达式 只能捕获 不能变化的 值,而i 在变化
//            runners.add(()-> System.out.println(names[i]));
        }
        runners.stream().map(Thread::new).forEach(Thread::start);
    }



    @Test
    public void _01_09_Collection2() {
        AList2<String> strings = new AList2<>();
        strings.add("asdfg");
        strings.add("qqq");
        strings.add("rtypo12");
        // 如果 字符串的 长度 大于5 .就输出
        strings.forEachIf(System.out::println,s->s.length()>5);
    }


    /**
     * 这个 接口 并不难写,写完之后要怎么用呢?
     * 现在这个接口没有实现类,所以无法使用,需要写一个 实现类,在下面 AList2
     * @param <T>
     */
    interface Collection2<T> extends Collection<T> {
        default void forEachIf(Consumer<T> action, Predicate<T> filter){
            //多么优雅的代码 , 不用写 if else 了,以前十几行代码,现在只需要一行,而且可读性更强
            this.stream().filter(filter::test).forEach(action::accept);
        }
    }

    class AList2<E> extends ArrayList<E> implements Collection2<E>{

    }
}
目录 第1章 lambda表达式 0 1.1 为什么要使用lambda表达式 2 1.2 lambda表达式的语法 4 1.3 函数式接口 6 1.4 方法引用 8 1.5 构造器引用 10 1.6 变量作用域 10 1.7 默认方法 14 1.8 接口中的静态方法 17 练习 18 第2章 Stream API 20 2.1 从迭代器到Stream操作 22 2.2 创建Stream 23 2.3 filter、map和flatMap方法 25 2.4 提取子流和组合流 26 2.5 有状态的转换 27 2.6 简单的聚合方法 28 2.7 Optional类型 29 2.7.1 使用Optional值 29 2.7.2 创建可选值 30 2.7.3 使用flatMap来组合可选值函数 31 2.8 聚合操作 32 2.9 收集结果 33 2.10 将结果收集到Map中 35 2.11 分组和分片 37 2.12 原始类型流 40 2.13 并行流 42 2.14 函数式接口 44 练习 45 第3章使用lambda编程 48 3.1 延迟执行 50 3.2 lambda表达式的参数 51 3.3 选择一个函数式接口 52 3.4 返回函数 55 3.5 组合 56 3.6 延迟 58 3.7 并行操作 59 3.8 处理异常 60 3.9 lambda表达式和泛型 63 3.10 一元操作 65 练习 67 第4章 JavaFX 72 4.1 Java GUI编程简史 74 4.2 你好,JavaFX! 75 4.3 事件处理 76 4.4 JavaFX属性 77 4.5 绑定 80 4.6 布局 85 4.7 FXML 91 4.8 CSS 95 4.9 动画和特殊效果 97 4.10 不寻常的控件 100 练习 103 第5章新的日期和时间API 106 5.1 时间线 108 5.2 本地日期 110 5.3 日期校正器 113 5.4 本地时间 114 5.5 带时区的时间 115 5.6 格式化和解析 119 5.7 与遗留代码互操作 122 练习 123 第6章并发增强 126 6.1 原子值 128 6.2 ConcurrentHashMap改进 131 6.2.1 更新值 132 6.2.2 批量数据操作 134 6.2.3 Set视图 136 6.3 并行数组操作 137 6.4 可完成的Future 138 6.4.1 Future 138 6.4.2 编写Future 139 6.4.3 Future流水线 139 6.4.4 编写异步操作 141 练习 143 第7章 JavaScript引擎——Nashorn 146 7.1 从命令行运行Nashorn 148 7.2 从Java运行Nashorn 149 7.3 调用方法 150 7.4 构造对象 151 7.5 字符串 153 7.6 数字 153 7.7 使用数组 154 7.8 列表和映射 155 7.9 lambda表达式 156 7.10 继承Java类及实现Java接口 157 7.11 异常 158 7.12 Shell脚本 159 7.12.1 执行Shell命令 159 7.12.2 字符串插值 160 7.12.3 脚本输入 161 7.13 Nashorn和JavaFX 162 练习 164 第8章杂项改进 166 8.1 字符串 168 8.2 数字类 168 8.3 新的数学函数 169 8.4 集合 170 8.4.1 集合类中添加的方法 170 8.4.2 比较器 171 8.4.3 Collections类 173 8.5 使用文件 173 8.5.1 读取文件行的流 173 8.5.2 遍历目录项的流 175 8.5.3 Base64编码 176 8.6 注解 177 8.6.1 可重复的注解 177 8.6.2 可用于类型的注解 179 8.6.3 方法参数反射 181 8.7 其他一些细微的改进 182 8.7.1 Null检查 182 8.7.2 延迟消息 182 8.7.3 正则表达式 183 8.7.4 语言环境 183 8.7.5 JDBC 185 练习 185 第9章你可能错过的Java 7特性 188 9.1 异常处理改进 190 9.1.1 try-with-resources语句 190 9.1.2 忽略异常 191 9.1.3 捕获多个异常 192 9.1.4 更简单地处理反射方法的异常 193 9.2 使用文件 193 9.2.1 Path 194 9.2.2 读取和写入文件 196 9.2.3 创建文件和目录 197 9.2.4
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值