JAVA8新特性 ( Lambda 表达式、双冒号、stream)

JAVA8新特性 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中方法引用的一些语法:
  静态方法引用语法:classname::methodname 例如:Person::getAge
  对象的实例方法引用语法:instancename::methodname 例如:System.out::println
  对象的超类方法引用语法: super::methodname
  类构造器引用语法: classname::new 例如:ArrayList::new
  数组构造器引用语法: typename[]::new 例如: String[]: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);
}

 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

 真实应用示例(stream.map):

// 小写字母转换为大写字母
List<String> collected1 = Arrays.asList("alpha","beta");
collected1 = collected1.stream().map(string -> string.toUpperCase()).collect(Collectors.toList());
System.out.println(collected1);

 真实应用示例(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);

 真实应用示例(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());

 真实应用示例(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;
}

 真实应用示例(stream.forEach):

// 给实体里面的数字,设置一个值
protected void set_Status(List<UnitAdapter> data, String operation) {
    data.stream().forEach(unitAdapter -> unitAdapter.set_status(operation));

 入门小程序:

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);});

  

原文地址:https://www.cnblogs.com/tangshengwei/p/12587976.html