Lambda表达式总结

版权声明:本文为博主原创文章,未经博主允许不得转载https://blog.csdn.net/qq_37146354/article/details/97131038

Lambda表达式:

1.匿名内部类创建

创建一个Communication通讯接口,里面仅且只有callBack方法,可以加入函数式接口注解

/**
 * FunctionalInterface:定义这个接口是函数式接口,只能有一个抽象方法
 */
@FunctionalInterface
public interface Communication {

    void callback();
}

在Person类中,使用这个通讯接口,因为是一个接口,所以要进行匿名内部类的创建。

// 创建实例,重写callback方法
Communication communication = ()->{System.out.println("callback:123");};
// 调用
communication.callback();

在Person类中写一个test方法,接收这个通讯接口

/**
* 测试方法
* @param name 普通参数
* @param communication 通讯接口 
*/
public void test(String name, Communication communication){
    System.out.println("name:" + name);
    communication.callback();
}

在调用这个方法时候,传入通讯接口时,要进行匿名内部类的创建,使用Lambda方式,因为通讯接口中只有一个方法,所以会自动适配这个方法,重写这个方法里面的参数,传入到test方法中。

new Person().test("123",()->{System.out.println("callback:123");});

当重写通讯方法时候只有一行代码,可以省略里面的大括号

// 简化方式
Communication communication2 = () -> System.out.println("callback:123");
// 调用
communication2.callback();

如果重写的代码只有一个输出语句,输出的数据是传入的数据,则 ()-> 都可以省略

// 重写Consumer中的accept,只输出传入的值
Consumer consumer = System.out::println;
// 入参后调用打印的方法
consumer.accept("123");

// 输出 123

如果这个方法有返回值时,大括号和return都可以省略

/**
 * FunctionalInterface:定义这个接口是函数式接口,只能有一个抽象方法
 */
@FunctionalInterface
public interface Communication3 {

    // 接收两个int值且有返回值
    int callback(int a ,int b);
}

int a = 1 ;
int b = 2 ;
// 实例化匿名内部类 , x 和 y 是 callback 的 a 和 b , -> 后面 x + y  是重写 callback 方法体里面的代码
Communication3 communication3 = (x,y)-> x + y;
// 调用 callback 方法
int ret = communication3.callback(1,2);
System.out.println(ret);

// 输出3

2.接口方法的定义

  • 在1.8以前类实现接口,一定要重写接口里面的方法,如果不想重写接口的方法,只能有抽象类来过渡。
  • 在1.8以后类实现接口可以不用都重写接口里面的方法,在接口中用default关键字描述的方法,在其他实现类中,可以重写它,也可以不管它。
public interface Communication {

    void callback();

    /**
     * 接口的默认方法,在其他实现类中,可以重写它,也可以不管它
     */
    default void callback1(){

    }
}

// Person1实现接口只重写callback方法,不会报错
public class Person1 implements Communication{

    @Override
    public void callback() {

    }
}

// Person2实现接口重写callback和callback1两个方法
public class Person2 implements Communication{

    @Override
    public void callback() {

    }

    @Override
    public void callback1() {

    }
}

  • 在接口中可以定义静态方法,但是只能由接口进行调用
public interface Communication {
    /**
     * 接口的静态方法,只能由此接口使用,它的实现类不能使用
     */
    static void callbackStatic(){

    }
}

public static void main(String[] args) {
    // 接口静态方法
    Communication.callbackStatic();
}

3.Optionnal运用

说明:优雅的操作数据

(1)构造Optional对象

// 创建一个Optional对象,value不能为空
Optional optional = Optional.of("123");
System.out.println(optional.get());

// 创建一个Optional对象,value可以传空
String a = null;
Optional<String> ret = Optional.ofNullable(a);

// 创建一个Optional空对象
Optional<Object> empty = Optional.empty();
System.out.println(empty);

(2)其他方法

1)isPresent

isPresent() :判断Optional中的value是否有值,有值返回true,没有值返回false。

// 判断optional是否存在值
String a = "123";
Optional optional = Optional.of(a);
boolean result = optional.isPresent();
System.out.println(result);
// true

String b = null;
Optional<String> optionalS = Optional.ofNullable(b);
boolean ret = optionalS.isPresent();
System.out.println(ret);
// false

2)ifPresent

ifPresent(Consumer<? super T> consumer) :如果consumer不为null ,则执行consumer。

// 实例化Consumer对象
Consumer consumer = System.out::println;
consumer.accept("123");
// 如果optional中value中不为空,执行consumer的accept,如果String C = null,则不会执行consumer.accept方法
String c = "456";
Optional<String> optionalS1 = Optional.ofNullable(c);
optionalS1.ifPresent(consumer);

3)get

get():获取optional中的value值。

Optional optional = Optional.of("123");
// 获取123
System.out.println(optional.get());

4)orElse

orElse() :optional 如果是null ,则返回other,否则返回optional里面的value值。

// optional 如果是null ,则返回other
Optional optionalS2 = Optional.ofNullable(null);
Object o1 = optionalS2.orElse("789");
System.out.println(o1);

// optional 有值,则返回optional中的value
String d = "123";
Optional optionalS3 = Optional.ofNullable(d);
Object o2 = optionalS2.orElse("789");
System.out.println(o2);

5)orElseGet

orElseGet():optional 如果是null ,则调用supplier.get()方法,否则返回optional里面的value值。

// 创建Supplier实例
Supplier<Integer> supplier = () -> { return 1+2;};
Optional optionalS4 = Optional.ofNullable(null);
// 如果optional.value=null,则执行Supplier的get方法
Object o3 = optionalS4.orElseGet(supplier);
System.out.println(o3);

// 简化代码
Object o3 =  Optional.ofNullable(null).orElseGet(() -> {return 1+2;});
System.out.println(o3);

6)orElseThrow

orElseThrow(Supplier<? extends X> exceptionSupplier) :如果optional没有值则执行exceptionSupplier并且抛出异常。

// optional中的value如果不为null,返回value中的值
String a = Optional.ofNullable("abc").orElseThrow(() -> new NullPointerException());
System.out.println(a);
// 输出abc

// optional中的value如果为null,抛后面的异常
Optional.ofNullable(null).orElseThrow(() -> new RuntimeException());

7)map

map(Function<? super T, ? extends U> mapper):映射,返回映射规则后的值,自动由Optional包装,map后面还可以使用optional中的api。

// 创建person类,设置参数
Person person = new Person();
person.setName("张三");
person.setAge(30);
person.setHigh(180);

// 当optional中的值不为null,执行map中的映射规则,返回person.getName的值。如果optional中的值是null,则执行orElse后面的值
String personResult = Optional.ofNullable(person).map(son -> son.getName()).orElse(null);
System.out.println(personResult);

简化写法

// map中使用类名::参数名获取参数值返回
String personResult2 = Optional.ofNullable(person).map(Person::getName).orElse(null);
System.out.println(personResult2);

8)flatmap

flatMap(Function<? super T, Optional< U > > mapper) :同map类似,但是flatMap返回值和传入的参数类型保持不变,但是入参必须是Optional类型

// 创建person类,设置参数
Person person = new Person();
person.setName("张三");
person.setAge(30);
person.setHigh(180);

// 因为传入的是Optional对象,所以返回值要封装成Optional对象
String personResult1 = Optional.ofNullable(person).flatMap(son -> Optional.of(son.getName())).orElse(null);
System.out.println(personResult1);

9)filter

filter(Predicate<? super T> predicate) :过滤,按规则进行过滤,不符合规则则返回empty,可以继续使用Optional的Api。

Person person = new Person();
person.setName("张三");
person.setAge(30);
person.setHigh(180);

// 过滤名字为李四的,如果实体的名字为张三则返回这个实体,如果不为张三,则返回empty
Optional<Person> nameOptional = Optional.ofNullable(person).filter(son -> son.getName().equals("张三"));
System.out.println(nameOptional.get().getName());


4.stream运用

(1) 构造流的方式

// 个别流构造,以String为例
Stream<String> stringStream = Stream.of("a","b","c");

// Arrays构造
String [] stringArray = {"1","2","3","4","5","6"};
Stream<String> stringStream1 = Stream.of(stringArray);
Stream<String> stringStream2 = Arrays.stream(stringArray);

// 集合构造
List<String> list = new ArrayList<String>();
Stream<String> stringStream3 = list.stream();

// 数值流的构造,只提供了三个类(IntStream , LongStream , DoubleStream)
IntStream intStream = IntStream.of(new int[]{1, 2, 3, 4, 5, 6});
LongStream longStream = LongStream.of(new long[]{1L, 2L, 3L, 4L});
DoubleStream doubleStream = DoubleStream.of(new double[]{12.33, 12.11});

(2)中间操作 [Intermediate]

1)map

map(Function<? super T, ? extends R> mapper):一对一的把 input Stream的每一个元素,映射成 output Stream 的另外一个元素。

// 准备参数
Person person1 = new Person();
person1.setName("张三");
person1.setAge(30);
person1.setHigh(180);

Person person2 = new Person();
person2.setName("李四");
person2.setAge(30);
person2.setHigh(180);

List<Person> list = new ArrayList<Person>();
list.add(person1);
list.add(person2);

// 收集Person类的名称形成新的List
List<String> ret = list.stream().map(Person::getName).collect(Collectors.toList());
System.out.println(ret);
// 输出:[张三, 李四]

// 转换小写字母变成大写字母
List<String> stringList = new ArrayList<String>();
stringList.add("a");
stringList.add("b");
List<String> collect = stringList.stream().map(String::toUpperCase).collect(Collectors.toList());
System.out.println(collect);
// 输出:[A, B]

// 对List值进行计算
List<Integer> number = new ArrayList<Integer>();
number.add(1);
number.add(2);
List<Integer> numList = number.stream().map(num -> num * 5).collect(Collectors.toList());
System.out.println(numList);
// 输出:[5, 10]

2)flatmap

flatmap(Function<? super T, ? extends Stream<? extends R>> mapper):一对多映射关系,将多个流扁平化成为一个流。

// 多个流
List<Integer> integers = Arrays.asList(1);
List<Integer> integers1 = Arrays.asList(2, 3);
List<Integer> integers2 = Arrays.asList(4, 5, 6);
Stream<List<Integer>> inputStream = Stream.of(
    integers,
    integers1,
    integers2
        );
inputStream.forEach(x ->{
    System.out.println(x.toString());
    // 输出:[1]
    //      [2, 3]
    //      [4, 5, 6]
});

Stream<List<Integer>> inputStream2 = Stream.of(
    integers,
    integers1,
    integers2
        );
// 多个流合并成一个流,
List<Integer> collect = inputStream2.flatMap(Collection::stream).collect(Collectors.toList());
System.out.println(collect);
// 输出:[1, 2, 3, 4, 5, 6]

3)filter

filter (Predicate<? super T> predicate):根据规则过滤出需要的元素。

List<String> code = new ArrayList<String>();
code.add("a");
code.add("b");
code.add("c");
code.add("A");
code.add("d");
code.add("B");
code.add("C");

// 过滤出大写的字母形成一个新的流,再收集成List
List<String> collect = code.stream().filter(c -> Character.isUpperCase(c.charAt(0))).collect(Collectors.toList());
System.out.println(collect.toString());
// 输出:[A, B, C]

4)limit

limit (long maxSize):返回前n个元素。

List<String> code = new ArrayList<String>();
code.add("a");
code.add("b");
code.add("c");
code.add("A");
code.add("d");
code.add("B");
code.add("C");

// 返回前三个元素
List<String> collect = code.stream().limit(3).collect(Collectors.toList());
System.out.println(collect);
// 输出 [a, b, c]

5)skip

skip(long n):跳过前三个元素。

List<String> code = new ArrayList<String>();
code.add("a");
code.add("b");
code.add("c");
code.add("A");
code.add("d");
code.add("B");
code.add("C");

// 跳过前三个元素
List<String> collect = code.stream().skip(3).collect(Collectors.toList());
System.out.println(collect);
// 输出 [A, d, B, C]

6)distinct

distinct():去除重复项

List<String> code = new ArrayList<String>();
code.add("A");
code.add("B");
code.add("C");
code.add("C");
code.add("C");

// 去除重复项
List<String> collect = code.stream().distinct().collect(Collectors.toList());
System.out.println(collect);
// 输出 [A, B, C]

7)sorted

sorted():无参数排序,以自然序排序一个list。

Eg:排序一个字母List和一个自然数

List<Integer> intList = new ArrayList<Integer>();
intList.add(10);
intList.add(3);
intList.add(15);
intList.add(9);

// 以自然顺序进行排序
List<Integer> collect = intList.stream().sorted().collect(Collectors.toList());
System.out.println(collect);
// 输出:[3, 9, 10, 15]

List<String> code = new ArrayList<String>();
code.add("a");
code.add("b");
code.add("c");
code.add("A");
code.add("d");
code.add("B");
code.add("C");

// 以自然顺序进行排序
List<String> collect = code.stream().sorted().collect(Collectors.toList());
System.out.println(collect);
// 输出:[A, B, C, a, b, c, d]

sorted(Comparator<? super T> comparator):有参数排序,以自己定义的规则排序。

Eg:按照人的年龄从大到小排序

Person person1 = new Person();
person1.setName("张三");
person1.setAge(30L);
person1.setHigh(180);

Person person2 = new Person();
person2.setName("李四");
person2.setAge(31L);
person2.setHigh(180);

Person person3 = new Person();
person3.setName("王五");
person3.setAge(32L);
person3.setHigh(180);

Person person4 = new Person();
person4.setName("赵六");
person4.setAge(33L);
person4.setHigh(180);

List<Person> list = new ArrayList<Person>();
list.add(person4);
list.add(person2);
list.add(person3);
list.add(person1);

List<Person> collectPerson = list.stream().sorted((t1,t2)->t2.getAge().compareTo(t1.getAge())).collect(Collectors.toList());
System.out.println(collectPerson.toString());
// 输出:[Person{name='赵六', age=33, high=180}, Person{name='王五', age=32, high=180}, Person{name='李四', age=31, high=180}, Person{name='张三', age=30, high=180}]

使用Comparator 来排序一个list

// 按照人的年龄从小到大排序
List<Person> collectPerson1 = list.stream().sorted(Comparator.comparing(Person::getAge)).collect(Collectors.toList());
System.out.println(collectPerson.toString());
// 输出:[Person{name='张三', age=30, high=180}, Person{name='李四', age=31, high=180}, Person{name='王五', age=32, high=180}, Person{name='赵六', age=33, high=180}]

// 按照人的年龄从大到小排序
List<Person> collectPerson2 = list.stream().sorted(Comparator.comparing(Person::getAge).reversed()).collect(Collectors.toList());
System.out.println(collectPerson.toString());
// 输出:[Person{name='赵六', age=33, high=180}, Person{name='王五', age=32, high=180}, Person{name='李四', age=31, high=180}, Person{name='张三', age=30, high=180}]

注意:

排序时间对比:Collections.sort() < TreeSet < stream.sort(),虽然java8中流的排序效率低过前面两个,但是Java8的流排序可以省去构造冗长的比较器,编写更简洁的代码。

8)min

min():IntStream中min是无参方法,找出集合里面的最小值。

IntStream intStream = IntStream.of(new int[]{1, 2, 3, 4, 5, 6});
int asInt = intStream.min().getAsInt();
System.out.println(asInt);

min(Comparator<? super T> comparator):在stream中要传入Comparator.naturalOrder(),找出最小值。

Integer[] nums = new Integer[]{1, 2, 2, 3, 4, 5, 5, 6};
Integer integer = Arrays.stream(nums).min(Comparator.naturalOrder()).get();
System.out.println(integer);

9)max

max():IntStream中min是无参方法,找出集合里面的最大值。

IntStream intStream = IntStream.of(new int[]{1, 2, 3, 4, 5, 6});
int asInt = intStream.max().getAsInt();
System.out.println(asInt);

max(Comparator<? super T> comparator):在stream中要传入Comparator.naturalOrder(),找出最大值。

Integer[] nums = new Integer[]{1, 2, 2, 3, 4, 5, 5, 6};
Integer integer = Arrays.stream(nums).max(Comparator.naturalOrder()).get();
System.out.println(integer);

10)Match
  • allMatch

    allMatch(Predicate<? super T> predicate):Stream 中全部元素符合规则,则返回 true,否则返回false。

    Person person1 = new Person();
    person1.setName("张三");
    person1.setAge(30L);
    person1.setHigh(180);
    
    Person person2 = new Person();
    person2.setName("李四");
    person2.setAge(31L);
    person2.setHigh(180);
    
    Person person3 = new Person();
    person3.setName("王五");
    person3.setAge(32L);
    person3.setHigh(180);
    
    Person person4 = new Person();
    person4.setName("赵六");
    person4.setAge(33L);
    person4.setHigh(180);
    
    List<Person> list = new ArrayList<Person>();
    list.add(person4);
    list.add(person2);
    list.add(person3);
    list.add(person1);
    
    boolean result = list.stream().allMatch(t -> t.getAge() >= 30L);
    System.out.println("是否所有人都符合年龄大于等于30岁:" + result);
    // 输出true
    
    
  • anyMatch

    anyMatch(Predicate<? super T> predicate):Stream 中只要有一个元素符合规则,返回 true,否则返回false。

    Person person1 = new Person();
    person1.setName("张三");
    person1.setAge(30L);
    person1.setHigh(180);
    
    Person person2 = new Person();
    person2.setName("李四");
    person2.setAge(31L);
    person2.setHigh(180);
    
    Person person3 = new Person();
    person3.setName("王五");
    person3.setAge(32L);
    person3.setHigh(180);
    
    Person person4 = new Person();
    person4.setName("赵六");
    person4.setAge(33L);
    person4.setHigh(180);
    
    List<Person> list = new ArrayList<Person>();
    list.add(person4);
    list.add(person2);
    list.add(person3);
    list.add(person1);
    
    boolean result = list.stream().anyMatch(t -> t.getAge() >= 33L);
    System.out.println("是否有一个人符合年龄大于等于33岁:" + result);
    // 输出true
    
    
  • noneMarch

    noneMarch(Predicate<? super T> predicate):Stream 中没有一个元素符合规则,返回 true,否则返回false。

    Person person1 = new Person();
    person1.setName("张三");
    person1.setAge(30L);
    person1.setHigh(180);
    
    Person person2 = new Person();
    person2.setName("李四");
    person2.setAge(31L);
    person2.setHigh(180);
    
    Person person3 = new Person();
    person3.setName("王五");
    person3.setAge(32L);
    person3.setHigh(180);
    
    Person person4 = new Person();
    person4.setName("赵六");
    person4.setAge(33L);
    person4.setHigh(180);
    
    List<Person> list = new ArrayList<Person>();
    list.add(person4);
    list.add(person2);
    list.add(person3);
    list.add(person1);
    
    boolean result = list.stream().noneMatch(t -> t.getAge() >= 60L);
    System.out.println("是否没有一个人符合年龄大于等于60岁:" + result);
    // 输出true
    
    
11)groupingBy

groupingBy(Function<? super T, ? extends K> classifier):对stream按照规则分组。

Eg:对订单的货币进行分组,相同的货币分成一个组。

Order order1 = new Order();
order1.setOrderId(1L);
order1.setOrderName("订单1");
order1.setCurrency("CNY");

Order order2 = new Order();
order2.setOrderId(2L);
order2.setOrderName("订单2");
order2.setCurrency("CNY");

Order order3 = new Order();
order3.setOrderId(3L);
order3.setOrderName("订单3");
order3.setCurrency("USD");

Order order4 = new Order();
order4.setOrderId(4L);
order4.setOrderName("订单4");
order4.setCurrency("USD");

List<Order> list = new ArrayList<Order>();
list.add(order1);
list.add(order2);
list.add(order3);
list.add(order4);

list.stream().collect(Collectors.groupingBy(Order::getCurrency)).forEach((currency,order)->{
    System.out.println("货币:"+currency+",订单列表:" + order.toString());
});

// 输出:
// 货币:USD,订单列表:[Order{orderId=3, currency='USD', orderName='订单3'}, Order{orderId=4, currency='USD', orderName='订单4'}]
// 货币:CNY,订单列表:[Order{orderId=1, currency='CNY', orderName='订单1'}, Order{orderId=2, currency='CNY', orderName='订单2'}]

12 )partitioningBy

partitioningBy(Predicate<? super T> predicate):对区间进行分组,返回一个Map,key是boolean代表是否在这个区间,value是分组后的List列表。

Eg:对订单金额分为两个区间,一个是大于1000区间,一个是小于等于1000区间。

Order order1 = new Order();
order1.setOrderId(1L);
order1.setOrderName("订单1");
order1.setCurrency("CNY");
order1.setMoney(100);

Order order2 = new Order();
order2.setOrderId(2L);
order2.setOrderName("订单2");
order2.setCurrency("CNY");
order2.setMoney(1000);

Order order3 = new Order();
order3.setOrderId(3L);
order3.setOrderName("订单3");
order3.setCurrency("USD");
order3.setMoney(2000);

Order order4 = new Order();
order4.setOrderId(4L);
order4.setOrderName("订单4");
order4.setCurrency("USD");
order4.setMoney(300);

List<Order> list = new ArrayList<Order>();
list.add(order1);
list.add(order2);
list.add(order3);
list.add(order4);

list.stream().collect(Collectors.partitioningBy(order -> order.getMoney() >= 1000 )).forEach((money,order)->{
    System.out.println("货币金额:"+money+",订单列表:" + order.toString());
});

// 输出:
// 货币金额:false,订单列表:[Order{orderId=1, currency='CNY', orderName='订单1', money=100}, Order{orderId=4, currency='USD', orderName='订单4', money=300}]
// 货币金额:true,订单列表:[Order{orderId=2, currency='CNY', orderName='订单2', money=1000}, Order{orderId=3, currency='USD', orderName='订单3', money=2000}]

(3)终止操作 [terminal]

1)forEach

forEach(Consumer<? super T> action):遍历数据流。

Person person1 = new Person();
person1.setName("张三");
person1.setAge(30);
person1.setHigh(180);

Person person2 = new Person();
person2.setName("李四");
person2.setAge(30);
person2.setHigh(180);

List<Person> list = new ArrayList<Person>();
list.add(person1);
list.add(person2);

// 遍历list中的每个值,打印名称
list.stream().forEach(son ->{
    System.out.println(son.getName());
});

注意:在遍历中不能修改本地变量,可以修改List中的属性值,但是List不能为空。

// 修改List中的每个类名称
list.stream().forEach(son ->{
    son.setName("王五");
    System.out.println(son.getName());
});

// 打印列表中的每个类名称
list.stream().forEach(son ->{
    System.out.println(son.getName());
});

// 输出:
// 王五
// 王五

int a = 1;
list.stream().forEach(son ->{
    // 报错不能修改
    a = 2;
    son.setName("王五");
    System.out.println(son.getName());
});

List<Person> list1 = null;
// 空指针
list1.stream().forEach(son ->{
    System.out.println(son.getName());
});

注意:

在少数据时效率为:for > foreach > stream foreach,在大数据时,三个性能差不多。但是java8的stream编写更简洁的代码。

2)reduce

reduce(BinaryOperator accumulator):根据一定的规则将Stream中的元素进行计算后返回一个唯一的值。

Eg:假设有一个数组从1加到10。

Integer[] nums = new Integer[]{1,2,3,4,5,6};
Integer sum = Arrays.stream(nums).reduce((integer, integer2) -> integer + integer2).get();
System.out.println("总数:"+sum);
// 输出:21

从0开始相加

Integer[] nums2 = new Integer[]{1,2,3,4,5,6};
Integer sum2 = Arrays.stream(nums2).reduce(0,(integer, integer2) -> integer + integer2);
System.out.println("总数:"+sum);
// 输出:21

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值