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

前几年就开始接触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>{

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值