java8 stream, map, Option 等函数式编程的使用例子

Posted 大树叶

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java8 stream, map, Option 等函数式编程的使用例子相关的知识,希望对你有一定的参考价值。

java8 stream, map 等函数式编程的一些典型用法例子如下。

例子1: 数组元素字母小写变大写。

List<String> list= Arrays.asList("a", "b", "c", "d");
List<String> collect =list.stream().map(String::toUpperCase).collect(Collectors.toList());
System.out.println(collect); //[A, B, C, D]

例子2:数组所有元素,按某种规律计算。

List<Integer> num = Arrays.asList(1,2,3,4,5);
List<Integer> collect1 = num.stream().map(n -> n * 2).collect(Collectors.toList());
System.out.println(collect1); //[2, 4, 6, 8, 10]

例子3 对数组元素的单个元素进行处理

public static String stepCondition(List<OffsetStep> step, ExtStatementRecord singleIncomeRecord) {
		String[] array = step.stream().map(item -> item.getRule().condition(item, singleIncomeRecord)).toArray(String[]::new);
		return StringUtils.join(array, " AND ");
	}

例子4:
改造for循环。

List<String> idcards=new ArrayList<String>();//
for(int i=0;i<users.size();i++){
  idcards.add(users.get(i).getName());
}
//这种方法要写好几行代码,有没有简单点的,有,java8 API能一行搞
//定:
List<String> idcards= users.stream().map(User::getIdcard).collect(Collectors.toList())

例子5:一个java 综合例子来使用Stream, collection, Optional的例子。

private void example(int coupleID, List<Map<String, Object>> masterRecordList, List<Map<String, Object>> slaveRecordsList, List<Long> masterMarksOkIds, List<Long> slaveMarksOkIds, FieldsMergeCondition mergeCondition) {
        Set<String> fieldName = getFieldName(coupleID);
        Map<String, List<Map<String, Object>>> slaveGroup = slaveRecordsList.stream().collect(Collectors.groupingBy(item -> {
            StringBuilder key = new StringBuilder();
            fieldName.forEach(column -> key.append(Optional.ofNullable(item.get(column)).orElseGet(()->"").toString().trim()));
            return key.toString();
        }));

        Set<String> rightFieldName = getRightFieldName(coupleID);
        Map<String, Map<Object, Object>> additionalMapping = verificationCommon.getAdditionalMapping(coupleID);
        for (Map<String, Object> masterRecord : masterRecordList) {
            setFieldValues(verificationCommon.getParsedCondition(coupleID), masterRecord);
            ConditionLinkNode parsedCondition = verificationCommon.getParsedCondition(coupleID);
            Map<String, Object> mappingCondition = setMappingValues(additionalMapping, masterRecord);
            StringBuilder key = new StringBuilder();
            rightFieldName.forEach(column -> key.append(Optional.ofNullable(masterRecord.get(column)).orElseGet(()->"").toString().trim()));
            List<Map<String, Object>> slaveList = slaveGroup.get(key.toString());
            if (CollectionUtils.isEmpty(slaveList)) {
                continue;
            }
            boolean verifyOk = false;
            if (Objects.isNull(mergeCondition)) {
                if (slaveList.size() > 1) {
                    List<Long> diffIds = slaveList.stream().map(this::getRecordId).collect(Collectors.toList());
                    slaveMarksOkIds.addAll(diffIds);
                    continue;
                }
                verifyOk = true;
            } else {
                verifyOk = merge(mergeCondition, masterRecord, slaveList, verifyOk);
            }
            if (verifyOk) {
                Map<String, Object> slaveRecord = slaveList.get(0);
                if (verifyData(parsedCondition, mappingCondition, slaveRecord)) {
                    slaveMarksOkIds.addAll(slaveList.stream().map(this::getRecordId).collect(Collectors.toList()));
                    Long masterId = getRecordId(masterRecord);
                    masterMarksOkIds.add(masterId);
                }
            }
        }
    }

下面是Optional的orElse和orElseGet的区别

 private static String getRandomName(String[] names) {
        System.out.println("Generating a name...");
        return "new name";
    }
 String[] names = new String[]{"zhang", "wang", "li", "zhao", "wu"};
        Optional.of("wang").orElse(getRandomName(names)); // 执行该句时会打印"Generating a name..."
        Optional.ofNullable("wang").orElse(getRandomName(names));// 执行该句时会打印"Generating a name..."
        Optional.of("wang").orElseGet(() -> getRandomName(names)); //不执行getRandomName()

注:上面Optional.of和Optional.ofNullable()返回的结果是"wang",虽然orElse()方法会执行(实际测试过)。

optional为空时:
orElse 会执行,返回orElse中的结果
orElseGet 会执行,返回orElseGet中的结果
optional有值时:
orElse 会执行,返回optional的结果
orElseGet 不会执行,返回optional的结果
结论
无论optional是否有值,orElse都会被执行。
只有optional为空时,orElseGet才会被执行。

注意,敲黑板了:
有个场景要注意。就是通过optional来操作数据库,如果查询到有数据,则update,没数据则执行insert
代码可能是这样

Optional.ofNullable(selectEntity(id)).map(update(entity)).orElse(insert(entity))

这时,如果方法上再有事物注解@transactional,那么很有可能会引起mysql事物锁等待超时 Lock wait timeout exceeded; try restarting transaction
原因是:在同一事务内先后对同一条数据进行插入和更新操作。因为orElse是必会执行的
所以orElse中,有具体方法操作时,一定要记得使用orElseGet

另外,关于对stream() 的理解

java8中 stream不是一种数据结构,它只是某种数据源的一个视图,数据源可以是一个数组,Java容器或I/O channel等。
为函数式编程而生。对stream的任何修改都不会修改背后的数据源,比如对stream执行过滤操作并不会删除被过滤的元素,而是会产生一个不包含被过滤元素的新stream。
惰式执行。stream上的操作并不会立即执行,只有等到用户真正需要结果的时候才会执行。
可消费性。stream只能被“消费”一次,一旦遍历过就会失效,就像容器的迭代器那样,想要再次遍历必须重新生成。

例子:Java8 用stream进行分组

     List<Map<String, Object>> slaveRecordsList=new ArrayLisy<>();
     //给slaveRecordsList赋值,省略....
     
      Set<String> fieldName = getFieldName(coupleID); //得到String Set
        Map<String, List<Map<String, Object>>> slaveGroup = slaveRecordsList.stream().collect(Collectors.groupingBy(item -> {
            StringBuilder key = new StringBuilder();
            fieldName.forEach(column -> key.append(Optional.ofNullable(item.get(column)).orElse("").toString().trim()));
            return key.toString();
        }));

List的stream的分组功能

public static void testStreamGroup(){
  List<Student> stuList = new ArrayList<Student>();
  Student stu1 = new Student("10001", "孙权", "1000101", 16, '男');
  Student stu2 = new Student("10001", "曹操", "1000102", 16, '男');
  Student stu3 = new Student("10002", "刘备", "1000201", 16, '男');
  Student stu4 = new Student("10002", "大乔", "1000202", 16, '女');
  Student stu5 = new Student("10002", "小乔", "1000203", 16, '女');
  Student stu6 = new Student("10003", "诸葛亮", "1000301", 16, '男');
 
  stuList.add(stu1);
  stuList.add(stu2);
  stuList.add(stu3);
  stuList.add(stu4);
  stuList.add(stu5);
  stuList.add(stu6);
 
  Map<String, List<Student>> collect = stuList.stream().collect(Collectors.groupingBy(Student::getClassId));
  for(Map.Entry<String, List<Student>> stuMap:collect.entrySet()){
     String classId = stuMap.getKey();
     List<Student> studentList = stuMap.getValue();
     System.out.println("classId:"+classId+",studentList:"+studentList.toString());
  }
}

参考文档

  1. java8 optional那些事
  2. java8新特性 lambda Stream map(函数式编程)
  3. Java8新特性之stream、map和reduce
  4. java通过Stream对list集合分组
    (场景:
    有一个List,想对该集合中的数据进行分组处理,则可以用java8中的stream),例子见这里
    5.Java stream 多情况分组
  5. Java8中使用stream进行分组统计和普通实现的分组统计的性能对比
    (性能最好是:普通分组,其次是并行流分组,最差是串行流分组)
    6.Java8新特性之stream、map和reduce

以上是关于java8 stream, map, Option 等函数式编程的使用例子的主要内容,如果未能解决你的问题,请参考以下文章

《Java8实战》读书笔记13:Java8 与 Scala

《Java8实战》读书笔记13:Java8 与 Scala

Java8之Stream/Map

Java8 - Streams map()

Java8 - Streams map()

使用Java8 Stream API对Map按键或值进行排序