• Java基础教程——Lambda表达式


    Lambda表达式

    Java8引入Lambda表达式,可以使代码更简洁。

    格式:参数,箭头,代码

    (参数名)->{代码}
    

    Lambda表达式体现了“函数式编程思想”——

    面向对象的思想:找一个能解决问题的对象,调用对象完成事情。
    函数式编程思想:只要结果,不管过程,不在乎是谁做、怎么做。


    Lambda表达式的前提——函数式接口。

    函数式接口,且只有一个未实现方法,可用注解@FunctionalInterface进行限定。
    接口有且只有一个未实现方法,Lambda才能进行推导。
    可以有其它非抽象方法,比如默认方法。


    lambda表达式可推导、可省略:

    • 参数类型可以不写
    • 参数只有一个的话,类型和()都可以省略
    • 如果{}中的代码只有一行,可以省略{}、return、分号
    package ah;
    import java.util.*;
    public class TestLambda {
    	public static void main(String[] args) {
    		System.out.println("---- 1.线程(无参数)");
    		// |--(1.1)匿名内部类写法
    		Thread t = new Thread(new Runnable() {
    			@Override
    			public void run() {
    				System.out.println(Thread.currentThread());
    			}
    		});
    		t.start();
    		// |--(1.2)Lambda表达式写法
    		Thread t2 = new Thread(() -> {
    			System.out.println(Thread.currentThread());
    		});
    		t2.start();
    		System.out.println("---- 2.集合排序(带参数)");
    		List<Phone> lst = new ArrayList<>();
    		lst.add(new Phone(1000, 300));
    		lst.add(new Phone(2000, 200));
    		lst.add(new Phone(3000, 100));
    		// |--(2.1)匿名内部类写法
    		Collections.sort(lst, new Comparator<Phone>() {
    			@Override
    			public int compare(Phone o1, Phone o2) {
    				return (int) (o2.price - o1.price);
    			}
    		});
    		System.out.println(lst);
    		// |--(2.2)Lambda表达式写法
    		Collections.sort(lst, (Phone o1, Phone o2) -> {
    			return o2.hot - o1.hot;
    		});
    		System.out.println(lst);
    		// |--(2.3)Lambda表达式省略写法(参数类型省略,{}、return、分号省略)
    		Collections.sort(lst, (o1, o2) -> o1.hot - o2.hot);
    		System.out.println(lst);
    		System.out.println("---- 3.一个参数的场合:参数括号能省略");
    		// |--(3.1)输出集合内容
    		lst.forEach(s -> System.out.println(s));
    		// |--(3.2)自定义接口和方法,参数使用接口
    		testArgIsInterface(s -> System.out.println(s), 100);
    	}
    	static void testArgIsInterface(IoneArg arg, int n) {
    		arg.m(n);
    	}
    }
    class Phone {
    	double price;
    	int hot;
    	public Phone(double price, int hot) {
    		this.price = price;
    		this.hot = hot;
    	}
    	@Override
    	public String toString() {
    		return "Phone [price=" + price + ", hot=" + hot + "]";
    	}
    }
    @FunctionalInterface
    interface IoneArg {
    	void m(int n);
    }
    
    ---- 1.线程(无参数)
    Thread[Thread-0,5,main]
    ---- 2.集合排序(带参数)
    Thread[Thread-1,5,main]
    [Phone [price=3000.0, hot=100], Phone [price=2000.0, hot=200], Phone [price=1000.0, hot=300]]
    [Phone [price=1000.0, hot=300], Phone [price=2000.0, hot=200], Phone [price=3000.0, hot=100]]
    [Phone [price=3000.0, hot=100], Phone [price=2000.0, hot=200], Phone [price=1000.0, hot=300]]
    ---- 3.一个参数的场合:参数括号能省略
    Phone [price=3000.0, hot=100]
    Phone [price=2000.0, hot=200]
    Phone [price=1000.0, hot=300]
    100
    

    Supplier接口

    java.util.function 包下有很多函数式接口,比如:

    @FunctionalInterface
    public interface Supplier<T> {
        T get();
    }
    

    Supplier接口称为“生产型接口”,指定接口的泛型,get方法会产生相应类型的数据。

    使用示例:

    import java.util.function.Supplier;
    public class TestSupplier {
    	// 将Supplier类型作为参数,以便Lambda知道接口类型
    	// 要实现的功能:获取数组的最大值
    	static int getMax(Supplier<Integer> sup) {
    		return sup.get();
    	}
    	public static void main(String[] args) {
    		int arr[] = { 5, 3, 2, -5, 99, 76 };
    		int maxOfArr = getMax(() -> {
    			int max = arr[0];
    			for (int n : arr) {
    				max = max < n ? n : max;
    			}
    			return max;
    		});
    		System.out.println(maxOfArr);
    	}
    }
    
    99
    

    Consumer接口

    和Supplier接口相对,用于“消费”,接受参数用于处理。addThen方法用于连续处理。

    @FunctionalInterface
    public interface Consumer<T> {
        void accept(T t);
    
        default Consumer<T> andThen(Consumer<? super T> after) {
            Objects.requireNonNull(after);
            return (T t) -> { accept(t); after.accept(t); };
        }
    }
    

    Consumer示例:

    import java.util.function.Consumer;
    public class TestConsumer {
    	public static void main(String[] args) {
    		testAccept((str) -> {
    			System.out.println(str);
    		}, "孙行者");
    		testAndThen((str) -> System.out.println("A" + str),
    				(str) -> System.out.println(str + "Z"), "猪悟能");
    	}
    	static void testAccept(Consumer<String> c, String s) {
    		// accept接受数据:可以使用数据(相当于消费)
    		c.accept(s);
    	}
    	static void testAndThen(Consumer<String> c1, Consumer<String> c2, String s) {
    		c1.accept(s);
    		c2.accept(s);
    		System.out.println("---default andThen:相当于把两个Consumer连起来使用");
    		c1.andThen(c2).accept(s);
    		System.out.println("---连接分先后,参数为后");
    		c2.andThen(c1).accept(s);
    	}
    }
    

    孙行者
    A猪悟能
    猪悟能Z
    ---default andThen:相当于把两个Consumer连起来使用
    A猪悟能
    猪悟能Z
    ---连接分先后,参数为后
    猪悟能Z
    A猪悟能

    Predicate接口

    predicate:谓词。指boolean-valued,主要有ADD,OR,NOT

    源码:

    @FunctionalInterface
    public interface Predicate<T> {
        boolean test(T t);
        default Predicate<T> and(Predicate<? super T> other) {
            Objects.requireNonNull(other);
            return (t) -> test(t) && other.test(t);
        }
        default Predicate<T> negate() {
            return (t) -> !test(t);
        }
        default Predicate<T> or(Predicate<? super T> other) {
            Objects.requireNonNull(other);
            return (t) -> test(t) || other.test(t);
        }
        static <T> Predicate<T> isEqual(Object targetRef) {
            return (null == targetRef)
                    ? Objects::isNull
                    : object -> targetRef.equals(object);
        }
    }
    

    示例:对字符串进行判断

    import java.util.function.Predicate;
    public class TestPredicate {
    	static void testTest(Predicate<String> p, String s) {
    		System.out.println(p.test(s));
    	}
    	static void testAnd(Predicate<String> p1, Predicate<String> p2, String s) {
    		System.out.println(p1.and(p2).test(s));
    	}
    	public static void main(String[] args) {
    		testTest((s) -> s == null, "A");
    		// 判断字符串不为null,同时长度>5
    		testAnd(
    		// 参数1:判断不为null
    		(s) -> s != null,
    		// 参数2:判断长度>5
    				(s) -> s.length() > 5,
    				// 参数3:
    				"123456");
    	}
    }
    
    false
    true
    

    示例:

    import java.util.*;
    import java.util.function.Predicate;
    public class TestPredicate2 {
    	// 对数组进行过滤,把符合条件的放入集合中
    	static List<String> filter(Predicate<String> p1, Predicate<String> p2,
    			String[] arr) {
    		List<String> lst = new ArrayList<>();
    		for (String str : arr) {
    			if (p1.and(p2).test(str)) {
    				lst.add(str);
    			}
    		}
    		return lst;
    	}
    	public static void main(String[] args) {
    		String[] s = { "关羽,蜀,武", "张飞,蜀,武", "典韦,魏,武", "诸葛亮,蜀,文" };
    		// 将蜀国的文官放入列表
    		List<String> lst = filter(
    		// 参数1:一种操作
    				(name) -> {
    					String[] split = name.split(",");
    					String nation = split[1];
    					if ("蜀".equals(nation)) {
    						return true;
    					} else {
    						return false;
    					}
    				},
    				// 参数2:另一种操作
    				(name) -> name.split(",")[2].equals("文"),
    				// 参数3:被操作的字符串
    				s);
    		System.out.println(lst);
    	}
    }
    
    [诸葛亮,蜀,文]
    

    Function接口

    根据一个类型的数据(前置条件)得到另一个类型的数据(后置条件)。

    package java.util.function;
    import java.util.Objects;
    @FunctionalInterface
    public interface Function<T, R> {
        
        R apply(T t);
    
        default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
            Objects.requireNonNull(before);
            return (V v) -> apply(before.apply(v));
        }
    
        default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
            Objects.requireNonNull(after);
            return (T t) -> after.apply(apply(t));
        }
    
        static <T> Function<T, T> identity() {
            return t -> t;
        }
    }
    

    示例:

    import java.util.function.Function;
    public class TestFunction {
    	static void testApply(Function<String, Integer> f, String s) {
    		Integer n = f.apply(s);
    		System.out.println(n);
    	}
    	static void testAddThen(Function<String, String> f1,
    			Function<String, String> f2, Function<String, String> f3, String s) {
    		// compose:组合,先做
    		// addThen:后做
    		String ret = f1.compose(f2).andThen(f3).apply(s);
    		System.out.println(ret);
    	}
    	public static void main(String[] args) {
    		String str = ">>1234";
    		testApply(
    		// 参数1:把字符串转换为整数
    				s -> {
    					s = s.substring(2);
    					return Integer.parseInt(s);
    				},
    				// 参数2:要处理的字符串
    				str);
    		testAddThen(
    		// 参数1
    				s -> s + "【齐天大圣】",
    				// 参数2:做了compose的参数(先做)
    				s -> s + "【弼马温】",
    				// 参数3:做了andThen参数(后做)
    				s -> s + "【斗战胜佛】",
    				// 参数四:字符串
    				"孙悟空");
    	}
    }
    
    1234
    孙悟空【弼马温】【齐天大圣】【斗战胜佛】
    

    延迟执行

    有些场景下,代码执行后,结果不一定被使用,这将造成浪费。Lambda表达式是“延迟执行”的,正好作为解决方案,提升性能。

    比如:

    public class TestLambdaLazy {
    	// 非Lambda参数,会产生字符串
    	public static void log(int level, String msg) {
    		if (level == 1) {
    			System.out.println(msg);
    		}
    	}
    	// Lambda表达式写法:参数改为函数式接口
    	// 参数虽然传递(对象),但是不使用的时候不执行
    	public static void log(int level, Message msg) {
    		if (level == 1) {
    			System.out.println(msg.setMsg());
    		}
    	}
    	public static void main(String[] args) {
    		int sum = 100;
    		log(2, "总计:" + sum);// 其实没有打印,字符串徒劳拼接
    		log(2, () -> {
    			System.out.println("Lambda执行");
    			return "总计:" + sum;
    		});
    	}
    }
    // Lambda用的函数式接口
    interface Message {
    	String setMsg();
    }
    
  • 相关阅读:
    Spring-Boot:多种配置注入方式
    Spring-Boot:Profile简单示例
    Spring-Boot:拦截器注解范例
    Docker:镜像的迁移
    YARN的内存和CPU配置
    Spark On YARN内存分配
    Spark配置参数
    linux_密钥
    分布式架构高可用架构篇_04_Keepalived+Nginx实现高可用Web负载均衡
    PythonDay01
  • 原文地址:https://www.cnblogs.com/tigerlion/p/11182859.html
Copyright © 2020-2023  润新知