Java8新特性 -- Lambda 表达式、双冒号、stream

一、Lambda 表达式

Lambda 允许把函数作为参数传递进方法中。

不是每个接口都可以缩写成 Lambda 表达式。只有那些函数式接口(Functional Interface)才能缩写成 Lambda 表示式。

所谓函数式接口(Functional Interface)就是只包含一个抽象方法的声明。
只要接口中仅仅包含一个抽象方法,我们就可以将其改写为 Lambda 表达式。为了保证一个接口明确的被定义为一个函数式接口(Functional Interface),我们需要为该接口添加注解:@FunctionalInterface。这样,一旦你添加了第二个抽象方法,编译器会立刻抛出错误提示。

Lambda表达式的重要特征:

  • 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
  • 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
  • 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
  • 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。

变量作用域
  lambda 表达式只能引用标记了 final 的外层局部变量,这就是说不能在 lambda 内部修改定义在域外的局部变量,否则会编译错误。

Lambda表达式的基本语法:

(parameters) -> expression  或  (parameters) ->{ statements; }

Lambda小程序,遍历 List 集合

String[] array = {"a","b","c"};
List<String> list = Arrays.asList(array);
 
System.out.println("方式一:原始方式");
for (int i = 0; i < list.size(); i++) {
    System.out.println(list.get(i));
}
 
System.out.println("方式二:增强 for 循环");
for (String s : list) {
    System.out.println(s);
}
 
System.out.println("方式三:lambda 表达式");
list.forEach( e -> System.out.println(e) );
 
System.out.println("方式四:lambda 表达式");
list.forEach( (e) -> {System.out.println(e);} );
 
System.out.println("方式五:lambda 表达式 之 静态方法引用");
list.forEach(System.out::println);

Lambda 小程序,使用 Lambda 表达式实现匿名内部类

System.out.println("方式一:匿名内部类实现 Runnable接口 run 方法,并使用多线程运行");
new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("Hello world !");
    }
}).start();
 
System.out.println("方式一:Lambda 实现 Runnable接口,并使用多线程运行");
new Thread(() -> System.out.println("Hello world !")).start();
 
System.out.println("方式二:匿名内部类实现 Runnable接口 run 方法");
Runnable r1 = new Runnable() {
    @Override
    public void run() {
        System.out.println("Hello world !");
    }
};
r1.run();
 
System.out.println("方式二:Lambda 实现 Runnable接口");
Runnable r2 = () -> System.out.println("Hello world !");
r2.run();

真实应用示例(forEach):

// 遍历比较
Set<DeptItem> itemList = entity.getRppDeptItem();
if(entity.getDatasource().equals(DeptDateSourceEnum.nc.getCode())){
    itemList.forEach(item->{
        if(item.getNcid() == null && item.getPersistStatus().equals(PersistStatus.ADDED)){
            throw new RuntimeException("来源NC部门不允许在主数据新增岗位" );
        }
    });
}
二、双冒号 ::

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

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

以下是Java 8中方法引用的一些语法:

TYPEASCIIHTML
静态方法引用语法classname::methodnamePerson::getAge
对象的实例方法引用语法instancename::methodnameSystem.out::println
对象的超类方法引用语法super::methodname
类构造器引用语法classname::newArrayList::new
数组构造器引用语法typename[]::newString[]::new

简要:https://www.cnblogs.com/maohuidong/p/11527681.html

详细:https://blog.csdn.net/zhoufanyang_china/article/details/87798829

真实应用示例(stream、::):

// list转换成数组
List<String> list = Arrays.asList("a","b","c");
String[] arrays = list.stream().toArray(String[]::new);
for (String array : arrays) {
    System.out.println(array);
}

部分代码案例
未使用双冒号

public class MyTest {
    public static void main(String[] args) {
        List<String> a1 = Arrays.asList("a", "b", "c");

        for (String a : a1) {
            printValur(a);
        };

        a1.forEach(x -> MyTest.printValur(x));


    }

    public static void printValur(String str) {
        System.out.println("print value : " + str);
    }
}

使用后

a1.forEach(MyTest::printValur);
    Consumer<String> consumer = MyTest::printValur;
    a1.forEach(x -> consumer.accept(x));

未使用双冒号:

 List<String> list = a1.stream().map(x -> x.toUpperCase()).collect(Collectors.toList());
    System.out.println(list.toString());

使用双冒号:

ArrayList<String> collect = a1.stream().map(String::toUpperCase).collect(Collectors.toCollection(ArrayList::new));
    System.out.println(collect.toString());
三、Stream

采用java8 lambda表达式 实现 java list 交集 并集 差集 去重复并集

Java 8 中的 Stream 是对集合(Collection)对象功能的增强,使用的是函数式编程模式,它可以对集合进行链状流式的操作,它专注于对集合对象进行各种非常便利、高效的聚合操作(aggregate operation),或者大批量数据操作 (bulk data operation)。Stream API 借助于同样新出现的 Lambda 表达式,极大的提高编程效率和程序可读性。

流的执行:
当存在终端操作时,中间操作操作才会被执行。

入门看我:https://www.jianshu.com/p/11c925cdba50

一般详细:https://www.ibm.com/developerworks/cn/java/j-lo-java8streamapi/index.html#icomments

非常详细:https://juejin.im/post/5cc124a95188252d891d00f2

大佬文章:https://blog.csdn.net/mu_wind/article/details/109516995

1、真实应用示例(stream.map):
// 小写字母转换为大写字母
List<String> collected1 = Arrays.asList("alpha","beta");
collected1 = collected1.stream().map(string -> string.toUpperCase()).collect(Collectors.toList());
System.out.println(collected1);
2、真实应用示例(stream.map):
// string转换为list
String ids = "1,2,3,4,5";
List<Long> listIds = Arrays.asList(ids.split(",")).stream().map(e -> Long.valueOf(e.trim())).collect(Collectors.toList());
System.out.println(listIds);
3、真实应用示例(stream.map):
// 获取到所有商品ID
// List<ProductSkuImageDto> resultList = updateProductSkuValues(addedList, modifiedList, deletedList);
// 写法一
List<String> productIdsList = resultList.stream().map(ProductSkuImageDto::getProductId).collect(Collectors.toList());
// 写法二
List<String> productIdsList = resultList.stream().map(e -> e.getProductId()).collect(Collectors.toList());
4、真实应用示例(stream.forEach):
// 遍历值放到map中
protected Map<String, GoodsBomDto> getBomInfos(Set<String> parentGoodsIds){
    if(CollectionUtils.isEmpty(parentGoodsIds)){
        return new HashMap<>(0);
    }
    List<GoodsBomDto> goodsBomDtos = goodsBomApi.goodsBomByParentGoodId(String.join(",", parentGoodsIds)).getBody();
    if(CollectionUtils.isEmpty(goodsBomDtos)){
        return new HashMap<>(0);
    }
    Map<String, GoodsBomDto> parentGoodsId_bomMap = new HashMap<>(goodsBomDtos.size());
    goodsBomDtos.stream().forEach(goodsBomDto -> parentGoodsId_bomMap.put(goodsBomDto.getParentGoodsId(), goodsBomDto));
    return parentGoodsId_bomMap;
}
5、真实应用示例(stream.forEach):
// 给实体里面的数字,设置一个值
protected void set_Status(List<UnitAdapter> data, String operation) {
    data.stream().forEach(unitAdapter -> unitAdapter.set_status(operation));
6、真实应用示例(stream.filter):
List<String> list=new ArrayList<>();
list.add("zzz");
list.add("aaa");
list.add("bbb");
list.add("bbb");
list.add("zzz");
list.add("");
List<String> filtered=list.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
        filtered.forEach(System.out::println);

入门小程序:

List<String> list = Arrays.asList("abc", "def", "1234");
        System.out.println("统计字符长度");
        System.out.println("方式一:lambda表达式");
        list.stream().map(e -> e.length()).forEach(e -> System.out.println(e));
        System.out.println("方式二:函数引用");
        list.stream().map(String :: length).forEach(System.out::println);
 
        System.out.println("mapToInt 将数据流中的元素结果转换为 int 类型");
        list.stream().mapToInt(e -> e.length()).forEach(e -> System.out.println(e));
 
        System.out.println("mapToDouble 将数据流中的元素结果转换为 Double 类型");
        list.stream().mapToDouble(e -> e.length()).forEach(e -> System.out.println(e));
 
 
        List<String> list2 = Arrays.asList("a-b-c-d","e-f-i-g-h");
        System.out.println("flatmap 作用就是将元素拍平拍扁");
        // flatmapToInt、flatmapToLong、flatmapToDouble 跟flatMap 都类似的,只是类型被限定了
        list2.stream().flatMap(e -> Stream.of(e.split("-"))).forEach(e -> System.out.println(e));
 
        System.out.println("limit 限制显示元素的个数");
        List<Integer> list3 = Arrays.asList(1,2,3,4,5,6);
        list3.stream().limit(3).forEach(e -> System.out.println(e));
 
        System.out.println("distinct 去重");
        List<Integer> list4 = Arrays.asList(1,2,3,1,2,5,6,7,8,0,0,1,2,3,1);
        list4.stream().distinct().forEach(e -> System.out.println(e));
 
        System.out.println("filter 过滤");
        list4.stream().filter(e -> e<3).forEach(e -> System.out.println(e));
 
        System.out.println("skip 跳过前几个元素");
        List<String> list5 = Arrays.asList("a","b","c");
        list5.stream().skip(2).forEach(e -> System.out.println(e));
 
        System.out.println("sorted 排序,底层依赖Comparable 实现");
        list4.stream().sorted().forEach(e -> System.out.println(e));
 
        System.out.println("collect(Collectors.toSet()) 将元素收集到 Set 中");
        List<String> list6 = Arrays.asList("apple", "banana", "orange", "waltermaleon", "grape");
        list6.stream().collect(Collectors.toSet()).forEach(e -> System.out.println(e));
 
        System.out.println("count 统计数据流中的元素个数");
        System.out.println(list6.stream().count());
 
        System.out.println("findFirst 获取第一个元素");
        System.out.println(list6.stream().findFirst());
 
        System.out.println("findAny 随机获取一个元素");
        System.out.println(list6.stream().parallel().findAny());
 
        System.out.println("noneMatch 集合中是否不存在指定字符,如果不存在返回 true,否则返回 false");
        System.out.println(list6.stream().noneMatch(e -> e.equals("orange")));
 
        System.out.println("anayMatch 集合中是否存在指定字符,如果存在返回 true,否则返回 false");
        System.out.println(list6.stream().anyMatch(e -> e.equals("orange")));
 
        System.out.println("min 查找最小的元素");
        List<Integer> list7 = Arrays.asList(1,2,3,4,5,6);
        System.out.println(list7.stream().min((e1, e2) -> e1.compareTo(e2)));
 
        System.out.println("max 查找最大的元素");
        System.out.println(list7.stream().max((e1, e2) -> e1.compareTo(e2)));
 
        System.out.println("reduce 是一个规约操作,所有的元素归约成一个,比如对所有元素求和");
        System.out.println(list7.stream().reduce(0, (e1, e2) -> e1+e2));
 
        System.out.println("forEachOrdered 适用用于并行流的情况下进行迭代,能保证迭代的有序性");
        Stream.of(0,2,6,5,4,9,8,-1)
                .parallel()
                .forEach(e->{
                    System.out.println(Thread.currentThread().getName()+": "+e);});
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值