【Kotlin】高级函数及最佳实践

Kotlin 高级函数及最佳实践

    • 背景
    • 实践
    • 原理

背景

在kotlin实践过程中,函数名可以被当作普通变量一样使用。函数可以被当作值来传递、赋值给变量,也可以作为参数传递给其他函数,甚至可以作为函数的返回值。而合理使用高级函数,可以对一些重复代码进行抽象,从而达到复用的目的,以下笔者将结合实践经历,对这一函数进行实践和分析。


实践

我们先看这样一个示例,入参有一个operate函数,在传参时可以自定义函数的实现。

fun add(a: Int, b: Int, operate: (Int) -> Int): Int {
	return operate(a + b)
}

fun test() {
	add(1, 2) {
  	value -> value / 2
  }
  // 输出: 1
}

业务实践中,我们设想这样一个场景,有一系列的数据源,mysql、doris、tidb等等,然后需求是每次都要从另外一个mysql分页查询数据,然后对这一些列的数据源里的数据做一些合并操作处理,而且操作这些数据源的时候,是有依赖关系的,前者处理完后,发送mq处理下一个数据源。代码示例如下:

 fun handleTidb(mergeTask: MergeTaskVo) {
        var minId = mereDataMapper.fetchMinId(mergeTask) - 1
        var mergeDataList = mereDataMapper.listPage(minId, DEFAULT_SIZE, mergeTask)
        while (!CollectionUtils.isEmpty(mergeDataList)) {
            val studentPerformanceDetailList = mutableListOf<StudentPerformanceDetail>()
            for (item in mergeDataList) {
                val studentPerformanceDetailVo = MergeDataVo().toStudentPerformanceDetail(item)
                studentPerformanceDetailList.add(studentPerformanceDetailVo)
            }
            performanceMergeService.batchModifyTidbTeacherPerformance(studentPerformanceDetailList)
            minId = mergeDataList[mergeDataList.size - 1].id!!
            mergeDataList = mereDataMapper.listPage(minId, DEFAULT_SIZE, mergeTask)
        }
        // 发送mq处理tidb数据
        msgProducer.sendMsg(topic, mysql_tag, mergeTask.taskId, mergeTask)
    }

    fun handleMysql(mergeTask: MergeTaskVo) {

        var minId = mereDataMapper.fetchMinId(mergeTask) - 1
        var mergeDataList = mereDataMapper.listPage(minId, DEFAULT_SIZE, mergeTask)
        while (!CollectionUtils.isEmpty(mergeDataList)) {
            val studentPerformanceDetailList = mutableListOf<StudentPerformanceDetail>()
            for (item in mergeDataList) {
                val studentPerformanceDetailVo = MergeDataVo().toStudentPerformanceDetail(item)
                studentPerformanceDetailList.add(studentPerformanceDetailVo)
            }
            performanceMergeService.batchInsertPerformanceDetail(studentPerformanceDetailList)
            minId = mergeDataList[mergeDataList.size - 1].id!!
            mergeDataList = mereDataMapper.listPage(minId, DEFAULT_SIZE, mergeTask)
        }

        msgProducer.sendMsg(topic, doris_tag, mergeTask.taskId, mergeTask)
    }
        // ...

上面的例子中我们可以看到有着很多重复的代码,纵观上面的操作,其实就真正操作数据库时的那个步骤不太同,那么这里我们可以用高级函数进一步抽象:

这里,我们抽象出了 operate 函数,然后再看 handleTidb 方法,一下子就简洁易懂了很多。

 protected fun baseOperate(mergeTask: MergeTaskVo, operate: (List<StudentPerformanceDetail>) -> Unit) {
        // 初始化的最小id减去1, 便于后边每次查询能统一包含最小id的记录
        var minId =  mereDataMapper.fetchMinId(mergeTask) - 1
        var mergeDataList = mereDataMapper.listPage(minId, DEFAULT_SIZE, mergeTask)
        while (!CollectionUtils.isEmpty(mergeDataList)) {
            val studentPerformanceDetailList = mutableListOf<StudentPerformanceDetail>()
            for (item in mergeDataList) {
                val studentPerformanceDetailVo = MergeDataVo().toStudentPerformanceDetail(item)
                studentPerformanceDetailList.add(studentPerformanceDetailVo)
            }
            operate(studentPerformanceDetailList)

            minId = mergeDataList[mergeDataList.size - 1].id!!
            mergeDataList = mereDataMapper.listPage(minId, DEFAULT_SIZE, mergeTask)
        }
        msgProducer.sendMsg(Constants.CLASS_MERGE_MESSAGE_TOPIC, Constants.HANDLE_TIDB_PERFORMANCE_TYPE_RECORD_TAG, mergeTask.taskId, mergeTask)

    }


    fun handleTidb(mergeTask: MergeTaskVo) {
        baseOperate(mergeTask) {
            param -> performanceMergeService.batchModifyTidbTeacherPerformance(param)
        }
        // 发送mq处理tidb数据
        msgProducer.sendMsg(topic, mysql_tag, mergeTask.taskId, mergeTask)
    }

原理

关于它的原理其实也很简单,其实就是一个语法糖,当我们查看它的字节码,然后反编译成Java字节码时,本质上还是跟我们在每一个函数方法里重写了查库逻辑。具体操作, 选中文件 -> Tools -> Kotlin -> Show Kotlin Bytecode:
【Kotlin】高级函数及最佳实践_第1张图片
反编译后Java文件:

public void handleTidb(@NotNull MergeTaskVo mergeTask) {
      Intrinsics.checkParameterIsNotNull(mergeTask, "mergeTask");
     
      int minId = this.getMereDataMapper().fetchMinId(mergeTask) - 1;

      for(List mergeDataList = this.getMereDataMapper().listPage(minId, this.getDEFAULT_SIZE(), mergeTask); !CollectionUtils.isEmpty((Collection)mergeDataList); mergeDataList = this.getMereDataMapper().listPage(minId, this.getDEFAULT_SIZE(), mergeTask)) {
         List studentPerformanceDetailList = (List)(new ArrayList());
         Iterator var6 = mergeDataList.iterator();

         while(var6.hasNext()) {
            MergeData item = (MergeData)var6.next();
            StudentPerformanceDetail studentPerformanceDetailVo = (new MergeDataVo()).toStudentPerformanceDetail(item);
            studentPerformanceDetailList.add(studentPerformanceDetailVo);
         }

         this.getPerformanceMergeService().batchModifyTidbStudentPerformance(studentPerformanceDetailList);
         Integer var10000 = ((MergeData)mergeDataList.get(mergeDataList.size() - 1)).getId();
         if (var10000 == null) {
            Intrinsics.throwNpe();
         }

         minId = var10000;
      }
    }

你可能感兴趣的:(Kotlin,kotlin,开发语言,android,高级函数)