设为首页 加入收藏

TOP

精练代码:一次 Java 函数式编程的重构之旅(一)
2018-02-26 08:40:11 】 浏览:972
Tags:精练 代码 一次 Java 函数 编程 重构 之旅

摘要:通过一次并发处理数据集的Java代码重构之旅,展示函数式编程如何使得代码更加精练。

难度:中级

基础知识

在开始之前,了解“高阶函数”和“泛型”这两个概念是必要的。

高阶函数就是接收函数参数的函数,能够根据传入的函数参数调节自己的行为。类似C语言中接收函数指针的函数。最经典的就是接收排序比较函数的排序函数。高阶函数不神秘哦!在Java8之前,就是那些可以接收回调接口作为参数的方法;在本文中,那么接收 Function, Consumer, Supplier 作为参数的函数都是高阶函数。高阶函数使得函数的能力更加灵活多变。

泛型是能够接纳多种类型作为参数进行处理的能力。很多函数的功能并不限于某一种具体的类型,比如快速排序,不仅可以用于整型,也可以用于字符串,甚至可用于对象。泛型使得函数在类型处理上更加灵活。

高阶函数和泛型两个特点结合起来,可使得函数具备强大的抽象表达能力。

重构前

基本代码如下。主要用途是根据具体的业务数据获取接口 IGetBizData ,并发地获取指定Keys值对应的业务数据集。

package zzz.study.function.refactor.before;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import zzz.study.function.refactor.TaskUtil;

/**
 * Created by shuqin on 17/6/23.
 */
public class ConcurrentDataHandlerFrame {

  public static void main(String[] args) {
    List<Integer> allData = getAllData(getKeys(), new GetTradeData());
    System.out.println(allData);
  }

  public static List<String> getKeys() {
    List<String> keys = new ArrayList<String>();
    for (int i=0; i< 20000; i++) {
      keys.add(String.valueOf(i));
    }
    return keys;
  }

  /**
   * 获取所有业务数据
   */
  public static <T> List<T> getAllData(List<String> allKeys, final IGetBizData iGetBizData) {
    List<String> parts = TaskUtil.divide(allKeys.size(), 1000);
    System.out.println(parts);
    ExecutorService executor = Executors.newFixedThreadPool(parts.size());
    CompletionService<List<T>>
        completionService = new ExecutorCompletionService<List<T>>(executor);
    for (String part: parts) {
      int start = Integer.parseInt(part.split(":")[0]);
      int end = Integer.parseInt(part.split(":")[1]);
      if (end > allKeys.size()) {
        end = allKeys.size();
      }
      final List<String> tmpRowkeyList = allKeys.subList(start, end);
      completionService.submit(new Callable<List<T>>() {
        public List<T> call() throws Exception {
          return iGetBizData.getData(tmpRowkeyList);
        }
      });
    }

    List<T> result = new ArrayList<T>();
    for (int i=0; i< parts.size(); i++) {
      try {
        result.addAll(completionService.take().get());
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
    executor.shutdown();
    return result;
  }

}

/** 业务数据接口 */
interface IGetBizData<T> {
  List<T> getData(List<String> keys);
}

/** 获取业务数据具体实现 */
class GetTradeData implements IGetBizData<Integer> {

  public List<Integer> getData(List<String> keys) {
    // maybe xxxService.getData(keys);
    List<Integer> result = new ArrayList<Integer>();
    for (String key: keys) {
      result.add(Integer.valueOf(key) % 1000000000);
    }
    return result;
  }

}

代码本身写得不坏,没有拗口的地方,读起来也比较流畅。美中不足的是,不够通用化。 心急的读者可以看看最后面重构后的代码。这里还是从重构过程开始。

重构过程

从小处着手

如果面对一大块代码不知如何下手,那么就从小处着手,先动起来。 对于如下代码,了解 Java8 Stream api 的同学肯定知道怎么做了:

  public List<Integer> getData(List<String> keys) {
    // maybe xxxService.getData(keys);
    List<Integer> result = new ArrayList<Integer>();
    f
首页 上一页 1 2 3 4 5 6 7 下一页 尾页 1/7/7
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇算法余晖 下一篇编辑 Spring Converter 入门之字..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目