Java 8 新特性 ☞ Lambda

Lambda 介绍

什么是Lambda?

Lambda 表达式是Java 8 重要的新功能之一。使用Lambda 表达式可以替代只有一个抽象函数的接口实现,告别匿名内部类,代码看起来更简洁易懂。Lambda 表达式还提升了对集合、框架的迭代、遍历、过滤数据的操作。

特点

  1. 函数式编程;
  2. 参数类型自动推断;
  3. 代码量少,简洁。
	List<String> list = Arrays.asList("java", "javascript", "python", "scala", "nodejs");
    // 方式一(jdk 8之前):
    Collections.sort(list, new Comparator<String>() {
    	@Override
    	public int compare(String s, String t1) {
	        return s.length() - t1.length();
     	}
    });
    for (String str : list){
    	System.out.println(str);
    }

    // 方式二(jdk 8):
    Collections.sort(list, (a, b) -> a.length() - b.length());
    list.forEach(System.out::println);

应用场景

任何有函数式接口的地方。

什么是函数式接口?

只有一个抽象方法(Object 类中的方法除外)的接口是函数式接口。

引入函数式编程的目的:

  1. 函数式编程写出的代码简洁且意图明确;
  2. 多核友好。

常用的函数式接口

Java 中提供了一系列函数式接口,用来接收后续传入的逻辑,但是对输入和输出有要求。

  1. Supplier 代表一个输出;
  2. Consumer 代表一个输入;
  3. BigConsumer 代表两个输入;
  4. Function 代表一个输入,一个输出;(一般输入和输出是不同类型)
  5. UnaryOperator 代表一个输入,一个输出;(输入和输出是相同类型)
  6. BiFunction 代表两个输入,一个输出;(一般输入和输出是不同类型)
  7. BinaryOperator 代表两个输入、一个输出。(输入和输出是相同类型)
 //1. Supplier 代表一个输出
Supplier<String> s1 = ()->{return "hello world!";};
Supplier<String> s2 = ()->"hello world!";
System.out.println(s1.get());
System.out.println(s2.get());

 //2. Consumer 一个输入
Consumer<String> consumer = (s)-> System.out.println(s);
consumer.accept("hello world!");
输出结果:
hello world!

//5. Function:一个输入一个输出,输入输出是不同类型
Function<String, Integer> f1 = (s)->{return s.length();};
System.out.println(f1.apply("hello world!"));
输出结果:
12
-------------------------------------------------------------
@Test
public void test01(){
	/*
	 * get() 和exec() 会在Runnable 的run() 方法中执行
	 * run() 方法是没有返回值的,run() 方法并没有处理get() 的返回值
	 */
	Runnable r1 = ()->get();
	Runnable r2 = ()->exec();
	//run() 方法是没有返回值的,这点指定了返回值是100,所以会报错!
	// Runnable r3 = ()->100;
	
	r1.run();
	r2.run();
}
static int get(){
    return 1;
}
static void exec(){
    System.out.println("hello world!");
}
输出结果:
hello world!

方法的引用

直接访问类或者实例已经存在的方法或者构造函数方法,方法引用提供了一种引用而不执行方法的方式,如果抽象方法的实现恰好可以使用调用另外一个方法来实现,就有可能可以使用使用方法引用。

方法引用的分类
  1. 静态方法引用  类名::staticMethod
                           (args)->类名.staticMethod(args)
  2. 实例方法引用  inst::instMethod
                           (args)->instMethod(args)
  3. 对象方法引用(很少使用)  类名::instMethod
                           (inst.args)->类名.instMethod(args)
  4. 构造方法引用  类名::new
                           (args)->new 类名(args)
@Test
public void test01(){
     //1. Supplier 代表一个输出;
     Supplier supplier = ()->BidSectionTransServiceTest.put();
     System.out.println(supplier.get());
     
     //2. 静态方法引用
     Supplier<String> supplier1 = BidSectionTransServiceTest::put;
     System.out.println(supplier1.get());

 }
 static String put(){
     System.out.println("put......");
     return "put";
 }
输出结果:
put......
put
  1. 静态方法的引用:函数式接口的实现恰好可以通过调用一个静态方法来实现
@Test
public void test01(){
	BiFunction<String, String, Integer> bf1 = (a, b)-> a.length()+b.length();
	BiFunction<String, String, Integer> bf2 = BidSectionTransServiceTest::getLength;

	System.out.println(bf1.apply("abc","def"));
	System.out.println(bf2.apply("abc","def"));
}

static Integer getLength(String str1, String str2){
	return str1.length() + str2.length();
}
  1. 实例方法的引用:函数式接口恰可以通过调用一个实例的实例方法来实现
@Test
public void test01(){
    Consumer<Integer> c1 = (size)->new BidSectionTransServiceTest().getLength(size);
    Consumer<Integer> c2 = new BidSectionTransServiceTest()::getLength;

    c1.accept(12);
    c2.accept(12);
}

void getLength(Integer size){
    System.out.println("size: " + size);
}
输出结果:
size: 12
size: 12
  1. 对象方法引用(用得比较少):抽象方法的第一个参数类型刚好是实例方法的类型,抽象方法剩余的参数恰好可以当做实例方法的参数。如果函数式接口的实现能由上面说的实例方法调用来实现的话,那么就可以使用对象方法引用。
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {Launcher.class})// 指定启动类
@Slf4j
public class BidSectionTransServiceTest {
    @Test
    public void test01(){
        Consumer<Too1> c1 = (Too1 t1)->new Too1().foo();
        c1.accept(new Too1());

        Consumer<Too1> c2 = (Too1 t1)->new Too2().foo();
        c2.accept(new Too1());

        Consumer<Too1> c3 = Too1::foo;
        c3.accept(new Too1());
    }

}
class Too1{
    public Integer fun(String str){
        return 1;
    }
    public void foo() {
        System.out.println("foo1");
    }
}
class Too2{
    public Integer fun(String str){
        return 1;
    }
    public void foo() {
        System.out.println("Too2 =========== foo");
    }
    public void show(String str){

    }
}

输出结果:
foo1
Too2 =========== foo
foo1
  1. 构造方法的引用:如果函数式接口的实现恰好可以通过调用一个类的构造方法来实现,那么就可以使用构造方法引用
@Test
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {Launcher.class})// 指定启动类
@Slf4j
public class BidSectionTransServiceTest {
   public void test01(){
       Supplier<Student> s1 = ()->new Student();
       s1.get();
       Supplier<Student> s2 = Student::new;
       s2.get();

       Supplier<List> s3 = LinkedList::new;
       Supplier<Set> s4 = LinkedHashSet::new;
       Supplier<Thread> s5 = Thread::new;
       Supplier<String> s6 = String::new;
   }
}

class Student{
    public Student(){
        System.out.println("student 的无参构造方法!");
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值