zoukankan      html  css  js  c++  java
  • [书]java8函数式编程(1)

    一:Learning

    package testLambda;
    
    import java.awt.Button;
    import java.awt.event.ActionEvent;
    import java.util.EventListener;
    import java.util.function.BinaryOperator;
    import org.junit.Test;
    
    /**
     * @author zhangdi
     * @description Lambda
     */
    public class LambdaChapter1and2 {
        public static void main(String[] args) {
    
        }
    
        /**
         * 2.1 辨别Lambda表达式
         */
        @SuppressWarnings("unused")
        @Test
        public static void recognizeLambda() {
            // 1.不包含参数,使用()表示,没有参数,该Lamdba表达式实现了Runnable接口,该接口也只有一个run方法,没有参数,返回类型为void
            Runnable NoArguments = () -> System.out.println("hello world");
            // 2.该Lamdba表达式包含且只包含一个参数可省略参数的括号
            ActionListener oneArgument = (event) -> System.out.println("button clicked");
            ActionListener oneArgument2 = event -> System.out.println("button clicked");
            // 3.可以使用{}将lamdba表达式的主体括起来;只有一行代码的lambda的表达式也可以使用大括号;用来明确表达式的开始与结束
            Runnable multistatement = () -> {
                System.out.println("hello");
                System.out.println("world");
            };
            // 4.lambda表达式也可以是包含多个参数的方法;
            BinaryOperator<Long> add = (x, y) -> x + y;
            BinaryOperator<Long> addExplicit = (Long x, Long y) -> x + y;
    
        }
    
        /**
         * 2.2 函数接口是只有一个抽象方法的接口,用作lambda表达式的类型
         */
        public static void 函数接口() {
    
        }
    
        /**
         * 2.3 引用值,而不是变量
         * 既成事实上的 final 是指只能给该变量赋值一次。 换句话说, Lambda 表达式引用的是值,而不是变量
         * Lambda 表达式中引用既成事实上的 final 变量  -->Lambda 表达式都是静态类型
         */
        public static void valueReference() {
            Button button = new Button();
            String name = getUserName();
            button.addActionListener(event -> System.out.println("hi " + name));
        }
        private static String getUserName() {
            // TODO Auto-generated method stub
            return "test";
        }
    
    
        /**
         * 2.4 ActionListener 接口: 接受 ActionEvent 类型的参数, 返回空
         * 
         *         ActionListener 只有一个抽象方法: actionPerformed, 被用来表示行为: 接受一个参数, 返回空。
         *         记住, 由于 actionPerformed 定义在一个接口里, 因此 abstract 关键字不是必需 的。
         *         该接口也继承自一个不具有任何方法的父接口: EventListener。
         */
        public interface ActionListener extends EventListener {
            public void actionPerformed(ActionEvent event);
        }
    
        /**
         *java中重要的函数接口
         * 接口                   参数          返回类型        示例
         * Predicate<T>         T       boolean     这张唱片已经发行了吗
         * Consumer<T>          T       void        输出一个值
         * Function<T,R>        T       R           获得 Artist 对象的名字
         * Supplier<T>          None    T           工厂方法 
         * UnaryOperator<T>     T       T           逻辑非( !)
         * BinaryOperator<T>    (T, T)  T           求两个数的乘积( *)
         * 
         *  2.5类型推断
         *  Predicate 用来判断真假的函数接口
         */
        public static void 类型推断() {
            Predicate<Integer> atLeast5 = x -> x > 5;
    
        }
        //Predicate 接口的源码, 接受一个对象, 返回一个布尔值
        public interface Predicate<T> {
            boolean test(T t);
        }
        //略显复杂的类型推断 :类型推断系统相当智能, 但若信息不够, 类型推断系统也无能为力。 类型系统不会漫无边
        //际地瞎猜, 而会中止操作并报告编译错误, 寻求帮助 ,如去掉Long,代码不会通过编译
        BinaryOperator<Long> addLongs = (x, y) -> x + y;
        //没有泛型, 代码则通不过编译
    
    
    
    
    }
    
    
    

    java中重要的函数接口:
    这里写图片描述
    总结:
    * Lambda 表达式是一个匿名方法, 将行为像数据一样进行传递。
    * Lambda 表达式的常见结构: BinaryOperator add = (x, y) → x + y。
    * Lambda表达式里引用的到的变量是final的,本质是值,不是变量。
    * Lambda表达式的类型是个函数接口,即仅有一个抽象方法的接口。( 函数接口指仅具有单个抽象方法的接口, 用来表示 Lambda 表达式的类型。)

    二: 练习
    1. 请看例 2-15 中的 Function 函数接口并回答下列问题。
    例 2-15 Function 函数接口

        public interface Function<T, R> {
            R apply(T t);
        }
    a. 请画出该函数接口的图示。
    b. 若要编写一个计算器程序, 你会使用该接口表示什么样的 Lambda 表达式?
    c. 下列哪些 Lambda 表达式有效实现了 Function<Long,Long> ?
    
        x -> x + 1;
        (x, y) -> x + 1;
        x -> x == 1;
    2. ThreadLocal Lambda 表达式。 Java 有一个 ThreadLocal 类, 作为容器保存了当前线程里
    局部变量的值。 Java 8 为该类新加了一个工厂方法, 接受一个 Lambda 表达式, 并产生
    一个新的 ThreadLocal 对象, 而不用使用继承, 语法上更加简洁。
    a. 在 Javadoc 或集成开发环境( IDE) 里找出该方法。
    b. DateFormatter 类是非线程安全的。 使用构造函数创建一个线程安全的 DateFormatter
    对象, 并输出日期, 如“ 01-Jan-1970”。
    
    3. 类型推断规则。 下面是将 Lambda 表达式作为参数传递给函数的一些例子。 javac 能正
    确推断出 Lambda 表达式中参数的类型吗? 换句话说, 程序能编译吗?
    a. Runnable helloWorld = () -> System.out.println("hello world");
    b. 使用 Lambda 表达式实现 ActionListener 接口:
    
        JButton button = new JButton();
        button.addActionListener(event ->
        System.out.println(event.getActionCommand()));
    c. 以如下方式重载 check 方法后, 还能正确推断出 check(x -> x > 5) 的类型吗?
    
        interface IntPred {
        boolean test(Integer value); 
        }
        boolean check(Predicate<Integer> predicate);
        boolean check(IntPred predicate);

    练习答案:

    
    public class Chapter1And2_practice {
    
        public static class Question1 {
            //x -> x + 1;
        }
    
        public static class Question3 {
            //a.yes
            //b.yes
            //c.no
        }
    
        /**
         * @author NSNP736
         * @description Question2
         */
        public static class Question2 {
            //lamada-by richard
            public final static ThreadLocal<DateFormatter> formatter = ThreadLocal.withInitial(() -> new DateFormatter(new SimpleDateFormat("dd-MMM-yyyy")));
            //Anonymous Inner Class -byzhangdi
            public final static ThreadLocal<DateFormatter> formatter2 = ThreadLocal.withInitial( new Supplier<DateFormatter>(){
    
                @Override
                public DateFormatter get() {
                    DateFormatter dateFormatter = new DateFormatter(new SimpleDateFormat("dd-MMM-yyyy"));
                    return dateFormatter;
                }});
        }
        @Test
        public void exampleInB() {
            Calendar cal = Calendar.getInstance();
            cal.set(Calendar.YEAR, 1970);
            cal.set(Calendar.MONTH, Calendar.JANUARY);
            cal.set(Calendar.DAY_OF_MONTH, 1);
            //formatter
            String format1 = Question2.formatter.get().getFormat().format(cal.getTime());
            //formatter2
            ThreadLocal<DateFormatter> formatter = Question2.formatter;
            DateFormatter dateFormatter = formatter.get();
            Format format = dateFormatter.getFormat();
            String format2 = format.format(cal.getTime());
    
            assertEquals("01-一月-1970", format1);
            assertEquals("01-一月-1970", format2);
        }
    }
  • 相关阅读:
    asp.net保存远程图片
    JS中的转义字符
    SQL_统计某列的和
    SQL Server 出错自动回滚
    SQL中的循环语句_类似FOR循环
    转 C# 控制IE
    抓取html 写正则
    正则截取内容
    用于测试的字符串
    C#关闭IE相应的窗口 .
  • 原文地址:https://www.cnblogs.com/DiZhang/p/12545014.html
Copyright © 2011-2022 走看看