栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Lambda表达式

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Lambda表达式

1.概念
  • JDK8出现的
  • 函数式接口(Functional Interface)
    任何接口,如果只有一个显式声明的抽象方法,那么就是函数式接口
    一般都会用@FunctionalInterface注解表示
  • 对于函数式接口,可以通过Lambda表达式来创建该接口的对象
  • 举例如下:
@FunctionalInterface
public interface Runnable { void run(); }

public interface Callable { V call() throws Exception; }      

public interface ActionListener { void actionPerformed(ActionEvent e); }  

public interface Comparator { int compare(T o1, T o2); boolean equals(Object obj); } 
  • Lambda表达式演化过程

2.与Comparator接口有关的Lambda表达式
  • 先给出结论:Comparator接口是函数式接口
  • Comparator接口的源码:
public interface Comparator {
	int compare(T o1, T o2);
	boolean equals(Object obj);
	default Comparator reversed() {
       return Collections.reverseOrder(this);
	}
	public static  Comparator comparing(
			Function keyExtractor,
			Comparator keyComparator)
	{
		Objects.requireNonNull(keyExtractor);
		Objects.requireNonNull(keyComparator);
		return (Comparator & Serializable)
    		(c1, c2) -> keyComparator.compare(keyExtractor.apply(c1),
                                            keyExtractor.apply(c2));
	}
	...
}
  • 疑问:Comparator接口中有两个抽象方法和若干个带default关键字的方法,为什么仍是函数式接口呢?
    1、default关键字可以让接口中的方法可以有默认的函数体,当一个类实现这个接口时,可以不用去实现这个方法。由于默认方法已经有了实现,所以它们不是抽象方法。
    2、函数式接口中可以有静态方法,一个或者多个静态方法不会影响接口成为函数式接口。
    3、重写了超类Object类中任意一个public方法的方法并不算接口中的抽象方法。

3.与创建线程有关的Lambda表达式

1、一个λ表达式只有在转型成一个函数式接口后才能被当做Object使用

//可以用一个λ表达式为一个函数式接口赋值,再赋值给一个Object
Runnable r1 = () -> {
	System.out.println("Hello Lambda!");
};
Object obj= r1;

//ERROR! Object is not a functional interface!
Object obj = () -> {
	System.out.println("Hello Lambda!");
}; 

//correct
//必须显式的转型成一个函数式接口
Object o = (Runnable) () -> { 
	System.out.println("hi"); 
};

2、为什么可以直接这样定义一个线程?

//匿名内部类形式
Thread oldSchool = new Thread( new Runnable () { 
	@Override
	public void run() { 
		System.out.println("This is from an anonymous class.");
	}
});


Thread thread = new Thread(() -> { 
	System.out.println("This is from an anonymous method (lambda exp).");
});

4.与集合有关的Lambda表达式
  • 回顾一下集合中的遍历方式

1、for循环

public class For {
    public static void main(String[] args) {
        ArrayList list = new ArrayList<>();
        list.add("aa");
        list.add("bb");
        list.add("cc");

        for (int i = 0; i < list.size(); i++) {
            String s = list.get(i);
            System.out.println(s);
        }
    }
}

2、iterator

public class IteratorTest {
    public static void main(String[] args) {
        ArrayList list = new ArrayList<>();
        list.add("aa");
        list.add("bb");
        list.add("cc");

        Iterator iterator = list.iterator();
        while (iterator.hasNext()) {
            String s = iterator.next();
            System.out.println(s);
        }
    }
}

3、增强for循环

public class IteratorTest {
    public static void main(String[] args) {
        ArrayList list = new ArrayList<>();
        list.add("aa");
        list.add("bb");
        list.add("cc");

        for (String s : list) {
            System.out.println(s);
        }
    }
}

4、增强for循环+Lambda表达式

  • 为什么可以用Lambda表达式?

1、JDK1.8中更新了Lambda表达式,查询Iterable接口源码可得:

public interface Iterable {
	Iterator iterator();
	default void forEach(Consumer action) {
      Objects.requireNonNull(action);
      for (T t : this) {
          action.accept(t);
      }
   }
}

2、对于默认方法forEach,形式参数类型Consumer,查询其源码可得:

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

发现Consumer接口是一个函数式接口,所以我们可以用Lambda表达式传入一个函数式接口对象!

public class IteratorTest {
    public static void main(String[] args) {
        ArrayList list = new ArrayList<>();
        list.add("aa");
        list.add("bb");
        list.add("cc");

        list.forEach(s -> System.out.println(s));
    }
}

还有一个对其改进的方法

public class IteratorTest {
    public static void main(String[] args) {
        ArrayList list = new ArrayList<>();
        list.add("aa");
        list.add("bb");
        list.add("cc");

		
        list.forEach(System.out::println);
    }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/821311.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号