java基础:java8新特性lambda表达式&::

简介: java基础:java8新特性lambda表达式&::

一、lambda表达式

1、lambda定义

Lambda表达式需要函数式接口的支持,格式:()→ {}

常见格式

格式1:无参无返回值
//使用Lambda替代runnable接口中无参无返回的run方法
@Test
public void demoOne(){
Runnable r =()->System.out.println("==========");
r.run();
}
格式2:一参无返回值
//使用Lambda替代Consumer接口中有一个参数无返回值的accept方法
@Test
public void demoOne() {
Consumer<String> c = (e) -> System.out.println(e);
c.accept("============");
}
当然对已一个参数的情况,箭头操作符右边的括号可以省略,等价的代码
@Test
public void demoOne() {
Consumer<String> c = e -> System.out.println(e);
c.accept("============");
}
格式3:多个参数有返回值
//使用Lambda替代比较器接口有两个参数并且返回值的
@Test
public void demoOne() {
Comparator<Integer> comparator = (x,y)->{
return Integer.compare(x, y);
};
}
当然当Lambda体只有一条语句,可以省略右边的大括号以及return,等级代码
@Test
public void demoOne() {
Comparator<Integer> comparator = (x, y) -> Integer.compare(x, y);
}
格式4:多个参数有返回值,并且Lambda体多条语句
@Test
public void demoOne() {
Comparator<Integer> comparator = (x, y) -> {
System.out.println("=============");
return Integer.compare(x, y);
};
}
格式5:参数列表的数据类型可写可不写。Lambda会通过上下文进行类型推断,建议没必要写
@Test
public void demoOne() {
Comparator<Integer> comparator = (Integer x, Integer y) -> {
System.out.println("=============");
return Integer.compare(x, y);
};
}

2、lambda改写函数式接口三种使用场景

2.1、作为参数传递 Lambda 表达式

foreach语法就是函数式接口作为参数

2.2、函数式接口作为方法返回值

public class ComparatorDemo {
    public static void main(String[] args) {
        ArrayList<String> array = new ArrayList<>();
        array.add("a");
        array.add("ccccc");
        array.add("bb");
        array.add("ddd");
        System.out.println("排序前" + array);

        Collections.sort(array, getComparator());

        System.out.println("排序后" + array);

    }

    private static Comparator<String> getComparator() {
        /*  使用匿名内部类
        Comparator<String> comp = new Comparator<String>() {
            @Override
            public int compare(String s1, String s2) {
                return s1.length()-s2.length();
            }
        };
        return comp;
         */

        //使用lambda表达式
        return (s1, s2) -> s1.length() - s2.length();
    }
}

2.3、函数式接口作为匿名内部类

Runnable r = ()->{System.out.println("My Runnable")};

二、Java中双冒号(::)运算操作符

1、定义

双冒号运算操作符是类方法的句柄,lambda表达式的一种简写,这种简写的学名叫eta-conversion或者叫η-conversion。

英文格式双冒号::,读:double colon,双冒号(::)运算符在Java 8中被用作方法引用(method reference),方法引用是与lambda表达式相关的一个重要特性。它提供了一种执行方法的方法,为此,方法引用需要由兼容的函数式接口组成的目标类型上下文。

使用lambda表达式会创建匿名函数, 但有时候需要使用一个lambda表达式只调用一个已经存在的方法(不做其它), 所以这才有了方法引用!

2、使用场景

2.1、引用静态方法

import org.junit.Test;
import java.util.Arrays;
import java.util.List;
 
public class Colon{
    @Test
    public void test(){
        List<String> list = Arrays.asList("a","b","c");
        //静态方法引用  ClassName::methodName
        list.forEach(Colon::print);
        //上一行等价于
        //list.forEach((x)->Colon.print(x));
    }
    //静态方法
    public static void print(String s){
        System.out.println(s);
    }
}

2.2、引用特定对象实例方法

import org.junit.Test;
import java.util.Arrays;
import java.util.List;
 
public class Colon{
    @Test
    public void test(){
        List<String> list = Arrays.asList("a","b","c");
        //实例方法引用  instanceRef::methodName
        list.forEach(new Colon()::print);
        //上一行等价于
        //list.forEach((x)->new Colon().print(x));
    }
    //实例方法
    public void print(String s){
        System.out.println(s);
    }
}

2.3、引用特定类型的任意对象的实例方法

import org.junit.Test;
import java.util.Arrays;
 
public class Colon{
    @Test
    public void test(){
        String[] arr = { "Barbara", "James", "Mary", "John",
                "Patricia", "Robert", "Michael", "Linda" };
        //引用String类型的任意对象的compareToIgnoreCase方法实现忽略大小写排序
        Arrays.sort(arr, String::compareToIgnoreCase);
        //上一行等价于
        //Arrays.sort(arr, (a,b)->a.compareToIgnoreCase(b));
        //输出
        for(String s:arr){
            System.out.println(s);
        }
    }
}

2.4、引用超类(父类)实例方法

import org.junit.Test;
import java.util.Arrays;
import java.util.List;
 
public class Colon extends BaseColon{
    @Test
    public void test(){
        List<String> list = Arrays.asList("a","b","c");
        //实例方法引用  instanceRef::methodName
        list.forEach(super::print);
    }
}
class BaseColon{
    //实例方法
    public void print(String s){
        System.out.println(s);
    }
}

2.5、引用类构造方法

一般我们需要声明接口,该接口作为对象的生成器,通过 类名::new 的方式来实例化对象,然后调用方法返回对象。

//注意:该类无需实现接口
public class Colon{
    private String name;
    private int age;
    //无参构造
    public Colon() {
    }
    //有参构造
    public Colon(String name, int age) {
        this.name = name;
        this.age = age;
    }
 
    public static void main(String[] args) {
        //无参构造引用
        ColonNoParam cnp = Colon::new;
        Colon c1 = cnp.createColon();
        System.out.println(c1);
        //有参构造引用
        ColonWithParam cwp = Colon::new;
        Colon c2 = cwp.createColon("小明",20);
        System.out.println(c2);
    }
 
    //生成toString方法打印查看
    @Override
    public String toString() {
        return "Colon{" +
                "name='" + name + ''' +
                ", age=" + age +
                '}';
    }
}
interface ColonNoParam{
    //无参方法提供对象
    Colon createColon();
}
interface ColonWithParam{
    //有参方法提供对象(数据类型要与Colon有参构造函数对应)
    Colon createColon(String s,int i);
}

2.6、引用数组构造方法

我们可以借助jdk自带的java.util.function.Function类实现对数组构造函数的引用。

import java.util.function.Function;
 
public class Colon{
 
    public static void main(String[] args) {
        Function<Integer,Colon[]> function = Colon[]::new;
        //调用apply方法创建数组,这里的5是数组的长度
        Colon[] arr = function.apply(5);
        //循环输出-初始都为null
        for(Colon c:arr){
            System.out.println(c);
        }
    }
}


相关文章
|
4天前
|
Java API
Java 8新特性之Lambda表达式与Stream API
【5月更文挑战第17天】本文将介绍Java 8中的两个重要特性:Lambda表达式和Stream API。Lambda表达式是一种新的编程语法,它允许我们将函数作为参数传递给其他方法,从而使代码更加简洁。Stream API是一种用于处理集合的新工具,它提供了一种高效且易于使用的方式来处理数据。通过结合使用这两个特性,我们可以编写出更加简洁、高效的Java代码。
13 0
|
4天前
|
存储 安全 Java
Java中的这些String特性可能需要了解下
Java中的String特性你知道哪些?虽然String很常见,通过源码可以看到String的值传递、字符串表和不可变性。本文基于JDK17说明。
10 1
|
1天前
|
Java API
Java 8新特性之Lambda表达式
【5月更文挑战第20天】本文将介绍Java 8中的一个重要特性——Lambda表达式。Lambda表达式是Java 8引入的一种新的编程语法,它允许我们将函数作为参数传递给方法,从而实现更加简洁、灵活的代码。本文将从Lambda表达式的基本概念、语法、使用方法以及优缺点等方面进行详细介绍,帮助读者更好地理解和应用Lambda表达式。
|
4天前
|
Java 测试技术
Java多线程的一些基本例子
【5月更文挑战第17天】Java多线程允许并发执行任务。示例1展示创建并启动两个`MyThread`对象,各自独立打印&quot;Hello World&quot;。示例2的`CounterExample`中,两个线程(IncrementThread和DecrementThread)同步地增加和减少共享计数器,确保最终计数为零。这些例子展示了Java线程的基本用法,包括线程同步,还有如Executor框架和线程池等更复杂的用例。
11 0
|
5天前
|
缓存 安全 Java
7张图带你轻松理解Java 线程安全,java缓存机制面试
7张图带你轻松理解Java 线程安全,java缓存机制面试
|
2天前
|
Java
Java一分钟之-并发编程:线程间通信(Phaser, CyclicBarrier, Semaphore)
【5月更文挑战第19天】Java并发编程中,Phaser、CyclicBarrier和Semaphore是三种强大的同步工具。Phaser用于阶段性任务协调,支持动态注册;CyclicBarrier允许线程同步执行,适合循环任务;Semaphore控制资源访问线程数,常用于限流和资源池管理。了解其使用场景、常见问题及避免策略,结合代码示例,能有效提升并发程序效率。注意异常处理和资源管理,以防止并发问题。
25 2
|
2天前
|
安全 Java 容器
Java一分钟之-并发编程:线程安全的集合类
【5月更文挑战第19天】Java提供线程安全集合类以解决并发环境中的数据一致性问题。例如,Vector是线程安全但效率低;可以使用Collections.synchronizedXxx将ArrayList或HashMap同步;ConcurrentHashMap是高效线程安全的映射;CopyOnWriteArrayList和CopyOnWriteArraySet适合读多写少场景;LinkedBlockingQueue是生产者-消费者模型中的线程安全队列。注意,过度同步可能影响性能,应尽量减少共享状态并利用并发工具类。
17 2
|
2天前
|
Java 程序员 调度
Java中的多线程编程:基础知识与实践
【5月更文挑战第19天】多线程编程是Java中的一个重要概念,它允许程序员在同一时间执行多个任务。本文将介绍Java多线程的基础知识,包括线程的创建、启动和管理,以及如何通过多线程提高程序的性能和响应性。
|
3天前
|
Java
深入理解Java并发编程:线程池的应用与优化
【5月更文挑战第18天】本文将深入探讨Java并发编程中的重要概念——线程池。我们将了解线程池的基本概念,应用场景,以及如何优化线程池的性能。通过实例分析,我们将看到线程池如何提高系统性能,减少资源消耗,并提高系统的响应速度。
13 5
|
3天前
|
消息中间件 安全 Java
理解Java中的多线程编程
【5月更文挑战第18天】本文介绍了Java中的多线程编程,包括线程和多线程的基本概念。Java通过继承Thread类或实现Runnable接口来创建线程,此外还支持使用线程池(如ExecutorService和Executors)进行更高效的管理。多线程编程需要注意线程安全、性能优化和线程间通信,以避免数据竞争、死锁等问题,并确保程序高效运行。