lambda初试

Lambda 表达式

java8新增特性函数式编程初探

##Lambda初级形态

package lambda;

public class Student {
	private String name;
	private int age;
	
	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "name="+name+";age="+age;
	}

}

根据年龄对学生进行从小到大排序

	public static void main(String[] args) {
		List<Student> list = new ArrayList<Student>();
		list.add(new Student("大明",6));
		list.add(new Student("李梅",3));
		list.add(new Student("莉莉",10));
		list.add(new Student("山姆",19));
		list.add(new Student("李雷",15));
		
		Collections.sort(list,new Comparator<Student>() {
			@Override
			public int compare(Student o1, Student o2) {
				return o1.getAge()-o2.getAge();
			}
		});
		System.out.println(list);
	}

通过集合工具类提供的排序方法,传入自定义比较器进行排序,一种中规中矩写法。
下面通过java8新特性做一次

	public static void main(String[] args) {
		List<Student> list = new ArrayList<Student>();
		list.add(new Student("大明",6));
		list.add(new Student("李梅",3));
		list.add(new Student("莉莉",10));
		list.add(new Student("山姆",19));
		list.add(new Student("李雷",15));
		
		Collections.sort(list,(o1,o2)->o1.getAge()-o2.getAge());
		System.out.println(list);
	}

那为什么可以这样写呢?
java8新增一个很重要特性:Lambda表达式,亦作闭包;规定仅包含一个抽象方法的接口为函数式接口,用@FunctionalInterface进行标明,仅仅是告诉编译器该接口是一个函数式接口,当接口不符合函数式接口定义会编译报错,该注解不是必须的。
那么让我们追根溯源去看下Comparator接口

@FunctionalInterface
public interface Comparator<T> {

    int compare(T o1, T o2);

    boolean equals(Object obj);

    default Comparator<T> reversed() {
        return Collections.reverseOrder(this);
    }

    default Comparator<T> thenComparing(Comparator<? super T> other) {
        Objects.requireNonNull(other);
        return (Comparator<T> & Serializable) (c1, c2) -> {
            int res = compare(c1, c2);
            return (res != 0) ? res : other.compare(c1, c2);
        };
    }

    default <U> Comparator<T> thenComparing(
            Function<? super T, ? extends U> keyExtractor,
            Comparator<? super U> keyComparator)
    {
        return thenComparing(comparing(keyExtractor, keyComparator));
    }

    default <U extends Comparable<? super U>> Comparator<T> thenComparing(
            Function<? super T, ? extends U> keyExtractor)
    {
        return thenComparing(comparing(keyExtractor));
    }

    default Comparator<T> thenComparingInt(ToIntFunction<? super T> keyExtractor) {
        return thenComparing(comparingInt(keyExtractor));
    }

    default Comparator<T> thenComparingLong(ToLongFunction<? super T> keyExtractor) {
        return thenComparing(comparingLong(keyExtractor));
    }

    default Comparator<T> thenComparingDouble(ToDoubleFunction<? super T> keyExtractor) {
        return thenComparing(comparingDouble(keyExtractor));
    }

    public static <T extends Comparable<? super T>> Comparator<T> reverseOrder() {
        return Collections.reverseOrder();
    }

    @SuppressWarnings("unchecked")
    public static <T extends Comparable<? super T>> Comparator<T> naturalOrder() {
        return (Comparator<T>) Comparators.NaturalOrderComparator.INSTANCE;
    }

    public static <T> Comparator<T> nullsFirst(Comparator<? super T> comparator) {
        return new Comparators.NullComparator<>(true, comparator);
    }

    public static <T> Comparator<T> nullsLast(Comparator<? super T> comparator) {
        return new Comparators.NullComparator<>(false, 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));
    }

    public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
            Function<? super T, ? extends U> keyExtractor)
    {
        Objects.requireNonNull(keyExtractor);
        return (Comparator<T> & Serializable)
            (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
    }

    public static <T> Comparator<T> comparingInt(ToIntFunction<? super T> keyExtractor) {
        Objects.requireNonNull(keyExtractor);
        return (Comparator<T> & Serializable)
            (c1, c2) -> Integer.compare(keyExtractor.applyAsInt(c1), keyExtractor.applyAsInt(c2));
    }

    public static <T> Comparator<T> comparingLong(ToLongFunction<? super T> keyExtractor) {
        Objects.requireNonNull(keyExtractor);
        return (Comparator<T> & Serializable)
            (c1, c2) -> Long.compare(keyExtractor.applyAsLong(c1), keyExtractor.applyAsLong(c2));
    }

    public static<T> Comparator<T> comparingDouble(ToDoubleFunction<? super T> keyExtractor) {
        Objects.requireNonNull(keyExtractor);
        return (Comparator<T> & Serializable)
            (c1, c2) -> Double.compare(keyExtractor.applyAsDouble(c1), keyExtractor.applyAsDouble(c2));
    }
}

什么鬼???问号脸!!!怎么还有一堆default、static修饰的方法,而且还有一个抽象方法boolean equals(Object obj),难道规则就是用来打破的么?

  • 默认方法
    函数式接口可以包含默认方法,因为默认方法不可以是抽象方法,其有一个默认实现,所以是符合函数式接口定义。
  • 静态方法
    函数式接口可以包含静态方法,因为静态方法不可以是抽象方法,是一个已经实现了的方法,所以是符合函数式接口定义。
  • boolean equals(Object obj)
    可以包含Object里的public方法,这些方法对于函数式接口来说,不被当成是抽象方法(虽然是抽象方法);因为任何一个函数式接口的实现,默认都继承了Object类。

###Lambda语法格式:
(参数) -> {表达式;}
###Lambda语法特征:
可选类型声明:可以不用声明参数类型,编译器可以根据上下文判断参数类型
可选参数圆括号:仅有一个参数无需圆括号
可选大括号:表达式仅包含一个语句,可以不写大括号以及语句末尾的分号
可选返回关键字:表达式仅包含一个语句,可以不写返回关键字return

1.多参数栗子
Collections.sort(list,(o1,o2)->o1.getAge()-o2.getAge());
2.无参数栗子
new Thread(() -> System.out.println("我是线程:"+Thread.currentThread().getName())).start();
3.单个参数栗子	 
public static void main(String[] args) {	
	//Consumer:提供任意一种类型的参数,返回空值。 void accept(T t);
	Consumer con = x -> System.out.println(x);
	con.accept("666");
}

jdk8中新增函数式接口包:java.util.function
Runnable r = () -> System.out.printf(“say hello”); //没有输入参数,也没有输出
Supplier sp = () -> “hello”; //只有输出消息,没有输入参数
Consumer cp = r -> System.out.printf®; //有一个输入参数,没有输出
Function<Integer, String> func = r -> String.valueOf®; //有一个输入参数 有一个输出参数
BiFunction<Integer, Integer, String> biFunc = (a, b) -> String.valueOf(a + b); //有两个输入参数 有一个输出参数
BiConsumer<Integer, Integer> biCp = (a, b) -> System.out.printf(String.valueOf(a + b)); //有两个输入参数 没有输出参数
……

##Lambda高级形态

方法引用
1.静态方法引用:ClassName::methodName
BiFunction<Integer,Integer,Integer> result = Integer::sum;
result.apply(1, 2);
or
BiFunction<Integer, Integer, Integer> con = (a,b)->Integer.sum(a, b);
con.apply(1,2);
2.实例上的实例方法引用:instanceReference::methodName
Set set = new HashSet();
set.add(“666”);
Predicate pr = set::contains;
pr.test(“666”);
pr.test(“233”);
or
Predicate p = ars -> set.contains(args);
p.test(“666”);
p.test(“233”);
3.构造方法引用:Class::new
Function<String, BigDecimal> f = b->new BigDecimal(b);
System.out.println(f.apply(“666”));
or
Function<String,BigDecimal> ff = BigDecimal::new;
System.out.println(ff.apply(“77”));
4.数组构造方法引用:typeName[]::new
IntFunction<int[]> i = int[]::new;
i.apply(5);
System.out.println(i.apply(1)[0]);

另:lambda表达式中可以读取并修改所在类成员变量;可读取所在方法局部变量但无法修改,而且当其读取局部变量时该变量将变为final修饰从而无法被修改。

##总结
1.Lambda表达式使得代码更简洁,思路更清晰。
2.初级用法(参数)->{表达式},有三种用法。
3.高级用法ClassName::methodName,主要有四种用法

###参考资料

  1. https://www.runoob.com/java/java8-lambda-expressions.html
  2. https://www.cnblogs.com/andywithu/p/7357069.html
  3. https://baijiahao.baidu.com/s?id=1614680282522143196&wfr=spider&for=pc
  4. https://shmilyaw-hotmail-com.iteye.com/blog/2251821

微信公众号:Technology Community
在这里插入图片描述在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值