- 概要
- 目的
『孫子の兵法』には、「道は芸術の精神であり、芸術は道の体である。道に従って芸術を支配し、芸術を用いて道を獲得する。」と書かれています。
明道 - 「道は芸術の精神であり、芸術は道の体です。道に従って芸術に進み、芸術を使用して道を獲得します。」; 道は教育哲学、教育法、および教育原則です。「明道」は、教育理論の研究を強化し、新しいカリキュラムの概念を学び、教育理論と学習理論を学び、情報技術と情報技術教育の理論的枠組みを理解することを目的としています。
優れた技術—「スキル」は能力であり、能力とは知識、方法、戦略、経験の集合体であり、「スキル」は実際的な問題を解決できるプロセスと戦略でもあり、効果と効率を向上させることができるスキルです。「優れた技術」とは、継続的に指導方法を改善し、教室での指導における実践的な指導方略を探求・蓄積し、自分自身や学校に適した指導経験を蓄積し、もちろん情報技術指導に必要な情報技術の知識やスキルを継続的に更新することを指します。
職人は「技」を極限まで追求し、実は「道」を求めており、「道」の実現に近づいている、あるいはすでに「道」を手に入れている、「道」の精神。職人が「技」だけで満足し、「道」を実現するために「技」を極限まで追求できなければ、それはただ「技」に頼って家族を養っているだけの職人になってしまいます。
Java コード簡略化の「技術」では、Java コード簡略化の「方法」を念頭に置いて説明しようとします。
-
- 読書オブジェクト
- ドメイン設計エンジニア。
- 製品開発エンジニア。
- 製品テストエンジニア。
- その他の関係者。
- 設計の原則と前提
なし
-
- 用語集
- 圧縮されたエントリ
-
- 文法を使う
- 三項式
- 文法を使う
- 簡潔な 3 項式コード
- 3項式コードCPUの実行効率が高い
三項演算子 x=y>0?A:B;では、CPU の計算能力が高く、三項演算子の 2 つの式命令がキューに入れられるため、if ...else... を使用するよりもパフォーマンスが向上します。if...else ...判定が必要です。判定前は次のコマンドがどれになるか分かりません。デフォルトの次のコマンドが矛盾している場合は、新しいコマンドに置き換えて実行してください。この時間は約 50 ~ 60 時間かかります。コマンドの計算時間を超えるクロック。
-
-
-
- オリジナルコード
-
-
if ( code .indexOf ( "." ) > 0 ) { String [ ] arr = code . 分割( " \\ ." ); ドメイン = arr [ 0 ]; コード = arr [ 1 ]; }
getBillByCodeAndDomain (コード、 ドメイン)を返します 。 |
-
-
-
- 合理化する
-
-
文字列[] arr = コード。分割( " \\ ." ); return getBillByCodeAndDomain ( code .indexOf ( " ." ) > 0 ? arr [ 1 ]: code , code .indexOf ( "." ) > 0 ? arr [ 0 ]: null ); |
-
-
-
- 予防
-
-
注: null 値の場合は例外がスローされます。
-
-
- for-each ステートメントの使用
- オリジナルコード
- for-each ステートメントの使用
-
private static JsonElement simplifyProps_LV1 ( JsonElement jsonObj , JSONObject RemoveList ) {
|
-
-
-
- 合理化する
-
-
private static JsonElement simplifyProps_LV1 ( JsonElement jsonObj , JSONObject RemoveList ) {
//業務処理 |
-
-
- try-with-resource ステートメントを活用する
-
JDK7 より前の Java には、外部リソースを自動的に閉じる文法機能はなく、JDK7 で try-with-resource 構文が追加されて初めて、この機能が実現されました。
では、try-with-resource とは何でしょうか? つまり、外部リソースのハンドル オブジェクト (FileInputStream オブジェクトなど) が AutoCloseable インターフェイスを実装する場合、テンプレートに従って簡略化することができます。
-
-
-
- オリジナルコード
-
-
入力ストリーム publicPro = null ; |
-
-
-
- 精简
-
-
InputStream publicPro = null; File file = !StringUtil.isBlank(ConfUtil.CONF_FILE_PATH)?new File(ConfUtil.CONF_FILE_PATH):new File(PUBLIC); |
-
-
- 利用 return 关键字
-
利用 return 关键字,可以提前函数返回,避免定义中间变量。
-
-
-
- 原代码
-
-
int existIndex = -1; |
-
-
-
- 精简
-
-
|
-
-
- 利用 static 关键字
-
利用 static 关键字,可以把字段变成静态字段,也可以把函数变为静态函数,调用时就无需初始化类对象。
原代码
public final class GisHelper { public double distance(double lng1, double lat1, double lng2, double lat2) { // 方法实现代码 }} |
-
-
-
- 精简
-
-
public final class GisHelper {
public static double distance(double lng1, double lat1, double lng2, double lat2) { // 方法实现代码 }} |
-
-
- 利用 lambda 表达式
-
Java 8 发布以后,lambda 表达式大量替代匿名内部类的使用,在简化了代码的同时,更突出了原有匿名内部类中真正有用的那部分代码。
-
-
-
- 原代码
-
-
new Thread(new Runnable() { public void run() { // 线程处理代码 }}).start(); |
-
-
-
- 精简
-
-
new Thread(() -> { // 线程处理代码 }).start(); |
-
-
- 利用方法引用
-
方法引用(::),可以简化 lambda 表达式,省略变量声明和函数调用。
-
-
-
- 原代码
-
-
List<String> flowIds=flowList.stream().map(item->(String)item.get(BillConstants.BIZFLOWID)).distinct().collect(Collectors.toList()); |
-
-
-
- 精简
-
-
List<String> flowIds=flowList.stream().map(String::get(BillConstants.BIZFLOWID)).distinct().collect(Collectors.toList()); |
-
-
- 利用静态导入
-
静态导入(import static),当程序中大量使用同一静态常量和函数时,可以简化静态常量和函数的引用。
import static静态导入是JDK1.5中的新特性。
一般我们导入一个类都用 import 包名.类名;
而静态导入是这样:import static 包名.类名.*;
这里的多了个static,还有就是类名后面多了个 .* 。意思是导入这个类里的静态成员(静态方法、静态变量)。当然,也可以只导入某个静态方法,只要把 .* 换成静态方法名就行了。然后在这个类中,就可以直接用方法名调用静态方法,而不必用“类名.方法名()” 的方式来调用。
-
-
-
- 精简
-
-
import static com.yonyou.ucf.mdd.ext.option.model.po.OptionDataPO.PARAMS_TYPE_ORG; |
-
-
-
- 注意事项
-
-
注意:静态引入容易造成代码阅读困难,所以在实际项目中应该警慎使用。
-
- 利用注解
- 利用 Lombok 注解
- 利用注解
Lombok 提供了一组有用的注解,可以用来消除Java类中的大量样板代码。
-
-
-
- 原代码
-
-
public class UserVO {
private Long id; private String name; public Long getId() {
} |
-
-
-
- 精简
-
-
@Data public class UserVO { private Long id; private String name; ... } |
-
-
- 利用 Validation 注解
-
采用Validation 可以避免大量的判空,长度及正则校验代码量。
-
-
-
- 精简
-
-
@Data public class B00XXXBean { /** 登录名 */ @Length(max = 10, message = "{valid.length}") @NotBlank(message = "{valid.name}") @Pattern(regexp = "^[\u4E00-\u9FA5A-Za-z0-9_]+$", message = "{valid.format}") private String staffname; /** 姓名 */ @Length(max = 10, message = "{valid.length}") @NotBlank(message = "{valid.staffrealname}") @Pattern(regexp = "^[\u4E00-\u9FA5A-Za-z0-9_]+$", message = "{valid.format}") private String realname; /** 登录密码 */ @Length(min = 1, max = 50, message = "{valid.password.length}") @NotBlank(message = "{valid.password.notblank}") @Pattern(regexp = "^[0-9a-zA-Z_]{1,}$", message = "{valid.format}") private String password; /** 确认密码 */ @NotBlank(message = "{valid.repassword}") @Pattern(regexp = "^[0-9a-zA-Z_]{1,}$", message = "{valid.format}") private String password2; /** 电话 */ @Pattern(regexp = "^[150[0-9]+]{11}", message = "{valid.tel}") private String tel; /** 邮箱 */ @Email(message = "{valid.mail}") private String mail; } |
@Service @Validated public class UserService { public Long createUser(@Valid UserCreateVO create) { // TODO: 创建用户 return null; }} |
-
-
- 利用 @NonNull 注解
-
Spring 的 @NonNull 注解,用于标注参数或返回值非空,适用于项目内部团队协作。只要实现方和调用方遵循规范,可以避免不必要的空值判断,这充分体现了阿里的“新六脉神剑”提倡的“因为信任,所以简单”。
-
-
-
- 原代码
-
-
public List<UserVO> queryCompanyUser(Long companyId) { // 检查公司标识 if (companyId == null) { return null; //业务处理 } List<UserVO> userList = queryCompanyUser(companyId); if (CollectionUtils.isNotEmpty(userList)) { for (UserVO user : userList) { // TODO: 处理业务 }} |
-
-
-
- 精简
-
-
public @NonNull List<UserVO> queryCompanyUser(@NonNull Long companyId) { } List<UserVO> userList = queryCompanyUser(companyId); for (UserVO user : userList) { // TODO: 处理公司用户 } |
-
-
- 利用注解特性
-
注解有以下特性可用于精简注解声明:1、当注解属性值跟默认值一致时,可以删除该属性赋值;2、当注解只有value属性时,可以去掉value进行简写;3、当注解属性组合等于另一个特定注解时,直接采用该特定注解。
-
-
-
- 原代码
-
-
@Lazy(true); @Service(value = "userService") @Component(value = "uimetaConfProps") @RequestMapping(path = "/getUser", method = RequestMethod.GET) |
-
-
-
- 精简
-
-
@Lazy @Service("userService") @Component("uimetaConfProps") @GetMapping("/getUser") |
-
- 利用泛型
- 泛型接口
- 利用泛型
在 Java 没有引入泛型前,都是采用 Object 表示通用对象,最大的问题就是类型无法强校验并且需要强制类型转换。
-
-
-
- 原代码
-
-
public interface Comparable { public int compareTo(Object other); } private Long id; public int compareTo(Object other) { UserVO user = (UserVO)other; return Long.compare(this.id, user.id); }} |
-
-
-
- 精简
-
-
public interface Comparable<T> { public int compareTo(T other); } @Setter @ToString public class UserVO implements Comparable<UserVO> { private Long id; public int compareTo(UserVO other) { return Long.compare(this.id, other.id); }} |
-
- 利用自身方法
- 利用构造方法
- 利用自身方法
构造方法,可以简化对象的初始化和设置属性操作。对于属性字段较少的类,可以自定义构造方法。
-
-
-
- 精简对比
-
-
简化了set属性
/* * 构造方法用于给对象的数据进行初始化 * 究竟是如何进行初始化的,对象的数据指的是什么? * 感觉书里这样讲很抽象,能否写代码举个例子 */ public class Cat { private String name; private int age;
// 无参构造方法 public Cat() {
}
// 有参构造方法 public Cat(String name, int age) { this.name = name; this.age = age; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public static void main(String[] args) { Cat blackCat1 = new Cat(); blackCat1.setName("一只黑猫"); blackCat1.setAge(7); System.out.println(blackCat1.getName() + " " + blackCat1.getAge()); Cat blackCat2 = new Cat("五更琉璃", 17); System.out.println(blackCat2.getName() + " " + blackCat2.getAge()); } }
//程序运行结果: //一只黑猫 7 //五更琉璃 17 |
-
-
- 利用链式编程
-
链式编程,也叫级联式编程,调用对象的函数时返回一个this对象指向对象本身,达到链式效果,可以级联调用。链式编程的优点是:编程性强、可读性强、代码简洁。
-
-
-
- 原代码
-
-
if (!isByAlias && dataSources.length > 1) {
|
-
-
-
- 精简
-
-
if (!isByAlias && dataSources.length > 1) {
|
-
- 利用工具方法
- 避免空值判断
- 原代码
- 避免空值判断
- 利用工具方法
if (params == null || params.isEmpty()) if( entity.getFields()!=null){ |
-
-
-
- 精简
-
-
if (!CollectionUtils..isEmpty(params)) { if (!CollectionUtils..isNotEmpty(entity.getFields())) { |
-
-
- 避免条件判断
-
-
-
-
- 原代码
-
-
if (pageIndex <= 0) {
|
-
-
-
- 精简
-
-
pageIndex=Math.max(pageIndex,1); |
-
-
- 简化赋值语句
- 精简
- 简化赋值语句
-
// JDK流派--mdd List<String> ignoreParams=Arrays.asList(new String[]{"localId","id","classId","defineId","tenantId","_status","pubts","isdeleted","propertytype"}); // Guava流派 List<String> ignoreParams=ImmutableList.of(new String[]{"localId","id","classId","defineId","tenantId","_status","pubts","isdeleted","propertytype"}); |
-
-
-
- 注意事项
-
-
注意:Arrays.asList 返回的 List 并不是 ArrayList ,不支持 add 等变更操作。
避免方法:
List<String> ignoreParams=new ArrayList<>(Arrays.asList(new String[]{"localId","id","classId","defineId","tenantId","_status","pubts","isdeleted","propertytype"})); |
-
-
- 简化数据拷贝
-
VO的拷贝
-
-
-
- 简化
-
-
BeanUtils.copyProperties(source, target); BeanUtils.copyProperties(oneBill, poiDto); |
-
-
-
- 反例
-
-
List<Object> list = JSON.parseArray(jsonObject.getString("data")); list =JSON.parseArray(GsonHelper.ToJSon(bill.getData())); |
精简代码,但不能以过大的性能损失为代价。例子是浅层拷贝,需要做JSON序列化,此处用不着 JSON 这样重量级的武器。
-
-
- 简化异常断言
- 原代码
- 简化异常断言
-
if (optionData == null) {
|
-
-
-
- 精简
-
-
Assert.notNull(optionData ,"没有对应的参数值,name: " + name); |
-
-
-
- 注意事项
-
-
注意:可能有些插件不认同这种判断,导致使用该对象时会有空指针警告。
因为java的断言是默认关闭的,需要先开启。
run -> Edit configurations,
-
- 利用数据结构
- 利用数组简化
- 利用数据结构
对于固定上下限范围的 if-else 语句,可以用数组+循环来简化。
-
-
-
- 原代码
-
-
public static int getGrade(double score) { if (score >= 90.0D) { return 1; } if (score >= 80.0D) { return 2; } if (score >= 60.0D) { return 3; } if (score >= 30.0D) { return 4; } return 5;} |
-
-
-
- 精简
-
-
private static final double[] SCORE_RANGES = new double[] {90.0D, 80.0D, 60.0D, 30.0D}; public static int getGrade(double score) { for (int i = 0; i < SCORE_RANGES.length; i++) { if (score >= SCORE_RANGES[i]) { return i + 1; } } return SCORE_RANGES.length + 1; } |
-
-
- 利用 Map 简化
-
对于映射关系的 if-else 语句,可以用Map来简化。此外,此规则同样适用于简化映射关系的 switch 语句。
-
-
-
- 原代码
-
-
public static String getBiologyClass(String name) { switch (name) { case "dog" : return "animal"; case "cat" : return "animal"; case "lavender" : return "plant"; ... default : return null; }} |
-
-
-
- 精简
-
-
private static final Map<String, String> BIOLOGY_CLASS_MAP = ImmutableMap.<String, String>builder() .put("dog", "animal") .put("cat", "animal") .put("lavender", "plant") ... .build(); public static String getBiologyClass(String name) { return BIOLOGY_CLASS_MAP.get(name); } |
-
- 利用 Optional
- 保证值存在
- 原代码
- 保证值存在
- 利用 Optional
Integer thisValue; if (Objects.nonNull(value)) { thisValue = value; } else { thisValue = DEFAULT_VALUE; } |
-
-
-
- 精简
-
-
Integer thisValue = Optional.ofNullable(value).orElse(DEFAULT_VALUE); |
-
-
- 保证值合法
- 原代码
- 保证值合法
-
Integer thisValue; if (Objects.nonNull(value) && value.compareTo(MAX_VALUE) <= 0) { thisValue = value; } else { thisValue = MAX_VALUE; } |
-
-
-
- 精简
-
-
Integer thisValue = Optional.ofNullable(value) .filter(tempValue -> tempValue.compareTo(MAX_VALUE) <= 0) .orElse(MAX_VALUE); |
-
-
- 避免空判断
- 原代码
- 避免空判断
-
String zipcode = null; if (Objects.nonNull(user)) { Address address = user.getAddress(); if (Objects.nonNull(address)) { Country country = address.getCountry(); if (Objects.nonNull(country)) { zipcode = country.getZipcode(); } }} |
-
-
-
- 精简
-
-
string zipcode = Optional.ofNullable(user) .map(User::getAddress) .map(Address::getCountry) .map(Country::getZipcode) .orElse(null); |
-
- 利用 Stream
流(Stream)是Java 8的新成员,允许你以声明式处理数据集合,可以看成为一个遍历数据集的高级迭代器。流主要有三部分构成:获取一个数据源→数据转换→执行操作获取想要的结果。每次转换原有 Stream 对象不改变,返回一个新的 Stream 对象,这就允许对其操作可以像链条一样排列,形成了一个管道。流(Stream)提供的功能非常有用,主要包括匹配、过滤、汇总、转化、分组、分组汇总等功能。
-
-
- 匹配集合数据
- 原代码
- 匹配集合数据
-
boolean isFound = false; for (UserDO user : userList) { if (Objects.equals(user.getId(), userId)) { isFound = true; break; }} |
-
-
-
- 精简
-
-
boolean isFound = userList.stream() .anyMatch(user -> Objects.equals(user.getId(), userId)); |
-
-
- 过滤集合数据
-
-
-
-
- 原代码
-
-
List<UserDO> resultList = new ArrayList<>(); for (UserDO user : userList) { if (Boolean.TRUE.equals(user.getIsSuper())) { resultList.add(user); }} |
-
-
-
- 精简
-
-
List<UserDO> resultList = userList.stream() .filter(user -> Boolean.TRUE.equals(user.getIsSuper())) .collect(Collectors.toList()); |
-
-
- 汇总集合数据
- 原代码
- 汇总集合数据
-
double total = 0.0D; for (Account account : accountList) { total += account.getBalance(); } |
-
-
-
- 精简
-
-
double total = accountList.stream().mapToDouble(Account::getBalance).sum(); |
-
-
- 转化集合数据
-
-
-
-
- 原代码
-
-
List<UserVO> userVOList = new ArrayList<>(); for (UserDO userDO : userDOList) { userVOList.add(transUser(userDO)); } |
-
-
-
- 精简
-
-
List<UserVO> userVOList = userDOList.stream() .map(this::transUser) .collect(Collectors.toList()); |
-
-
- 分组集合数据
- 原代码
- 分组集合数据
-
Map<Long, List<UserDO>> roleUserMap = new HashMap<>(); for (UserDO userDO : userDOList) { roleUserMap.computeIfAbsent(userDO.getRoleId(), key -> new ArrayList<>()) .add(userDO); } |
-
-
-
- 精简
-
-
Map<Long, List<UserDO>> roleUserMap = userDOList.stream() .collect(Collectors.groupingBy(UserDO::getRoleId)); |
-
-
- 分组汇总集合
- 原代码
- 分组汇总集合
-
Map<Long, Double> roleTotalMap = new HashMap<>(); for (Account account : accountList) { Long roleId = account.getRoleId(); Double total = Optional.ofNullable(roleTotalMap.get(roleId)).orElse(0.0D); roleTotalMap.put(roleId, total + account.getBalance()); } |
-
-
-
- 精简
-
-
|
-
- 利用程序结构
- 返回条件表达式
- 利用程序结构
条件表达式判断返回布尔值,条件表达式本身就是结果。
-
-
-
- 原代码
-
-
if(RELEASE_SUCCESS.equals(result.toString())){
|
-
-
-
- 精简
-
-
return RELEASE_SUCCESS.equals(result.toString()) |
-
- 利用设计模式
- 模板方法模式
- 利用设计模式
模板方法模式(Template Method Pattern)定义一个固定的算法框架,而将算法的一些步骤放到子类中实现,使得子类可以在不改变算法框架的情况下重定义该算法的某些步骤。
-
-
-
- 原代码
-
-
@Repository public class UserValue { /** 值操作 */ @Resource(name = "stringRedisTemplate") private ValueOperations<String, String> valueOperations; /** 值模式 */ private static final String KEY_FORMAT = "Value:User:%s"; /** 设置值 */ public void set(Long id, UserDO value) { String key = String.format(KEY_FORMAT, id); valueOperations.set(key, JSON.toJSONString(value)); } /** 获取值 */ public UserDO get(Long id) { String key = String.format(KEY_FORMAT, id); String value = valueOperations.get(key); return JSON.parseObject(value, UserDO.class); } ... } @Repository public class RoleValue { /** 值操作 */ @Resource(name = "stringRedisTemplate") private ValueOperations<String, String> valueOperations; /** 值模式 */ private static final String KEY_FORMAT = "Value:Role:%s"; /** 设置值 */ public void set(Long id, RoleDO value) { String key = String.format(KEY_FORMAT, id); valueOperations.set(key, JSON.toJSONString(value)); } /** 获取值 */ public RoleDO get(Long id) { String key = String.format(KEY_FORMAT, id); String value = valueOperations.get(key); return JSON.parseObject(value, RoleDO.class); } ... } |
-
-
-
- 精简
-
-
public abstract class AbstractDynamicValue<I, V> { /** 值操作 */ @Resource(name = "stringRedisTemplate") private ValueOperations<String, String> valueOperations; /** 设置值 */ public void set(I id, V value) { valueOperations.set(getKey(id), JSON.toJSONString(value)); } /** 获取值 */ public V get(I id) { return JSON.parseObject(valueOperations.get(getKey(id)), getValueClass()); } ... /** 获取主键 */ protected abstract String getKey(I id); /** 获取值类 */ protected abstract Class<V> getValueClass(); } @Repository public class UserValue extends AbstractValue<Long, UserDO> { /** 获取主键 */ @Override protected String getKey(Long id) { return String.format("Value:User:%s", id); } /** 获取值类 */ @Override protected Class<UserDO> getValueClass() { return UserDO.class; } } @Repository public class RoleValue extends AbstractValue<Long, RoleDO> { /** 获取主键 */ @Override protected String getKey(Long id) { return String.format("Value:Role:%s", id); } /** 获取值类 */ @Override protected Class<RoleDO> getValueClass() { return RoleDO.class; } } |
-
-
- 建造者模式
-
建造者模式(Builder Pattern)将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式。
-
-
-
- 原代码
-
-
public interface DataHandler<T> { /** 解析数据 */ public T parseData(Record record); /** 存储数据 */ public boolean storeData(List<T> dataList); } public <T> long executeFetch(String tableName, int batchSize, DataHandler<T> dataHandler) throws Exception { // 构建下载会话 DownloadSession session = buildSession(tableName); // 获取数据数量 long recordCount = session.getRecordCount(); if (recordCount == 0) { return 0; } // 进行数据读取 long fetchCount = 0L; try (RecordReader reader = session.openRecordReader(0L, recordCount, true)) { // 依次读取数据 Record record; List<T> dataList = new ArrayList<>(batchSize); while ((record = reader.read()) != null) { // 解析添加数据 T data = dataHandler.parseData(record); if (Objects.nonNull(data)) { dataList.add(data); } // 批量存储数据 if (dataList.size() == batchSize) { boolean isContinue = dataHandler.storeData(dataList); fetchCount += batchSize; dataList.clear(); if (!isContinue) { break; } } } // 存储剩余数据 if (CollectionUtils.isNotEmpty(dataList)) { dataHandler.storeData(dataList); fetchCount += dataList.size(); dataList.clear(); } } // 返回获取数量 return fetchCount; } // 使用案例 long fetchCount = odpsService.executeFetch("user", 5000, new DataHandler() { /** 解析数据 */ @Override public T parseData(Record record) { UserDO user = new UserDO(); user.setId(record.getBigint("id")); user.setName(record.getString("name")); return user; } /** 存储数据 */ @Override public boolean storeData(List<T> dataList) { userDAO.batchInsert(dataList); return true; } }); |
-
-
-
- 精简
-
-
public <T> long executeFetch(String tableName, int batchSize, Function<Record, T> dataParser, Function<List<T>, Boolean> dataStorage) throws Exception { // 构建下载会话 DownloadSession session = buildSession(tableName); // 获取数据数量 long recordCount = session.getRecordCount(); if (recordCount == 0) { return 0; } // 进行数据读取 long fetchCount = 0L; try (RecordReader reader = session.openRecordReader(0L, recordCount, true)) { // 依次读取数据 Record record; List<T> dataList = new ArrayList<>(batchSize); while ((record = reader.read()) != null) { // 解析添加数据 T data = dataParser.apply(record); if (Objects.nonNull(data)) { dataList.add(data); } // 批量存储数据 if (dataList.size() == batchSize) { Boolean isContinue = dataStorage.apply(dataList); fetchCount += batchSize; dataList.clear(); if (!Boolean.TRUE.equals(isContinue)) { break; } } } // 存储剩余数据 if (CollectionUtils.isNotEmpty(dataList)) { dataStorage.apply(dataList); fetchCount += dataList.size(); dataList.clear(); } } // 返回获取数量 return fetchCount; } // 使用案例 long fetchCount = odpsService.executeFetch("user", 5000, record -> { UserDO user = new UserDO(); user.setId(record.getBigint("id")); user.setName(record.getString("name")); return user; }, dataList -> { userDAO.batchInsert(dataList); return true; }); |
普通的建造者模式,实现时需要定义 DataHandler 接口,调用时需要实现 DataHandler 匿名内部类,代码较多较繁琐。而精简后的建造者模式,充分利用了函数式编程,实现时无需定义接口,直接使用 Function 接口;调用时无需实现匿名内部类,直接采用 lambda 表达式,代码较少较简洁。
-
-
- 代理模式
-
Spring 中最重要的代理模式就是 AOP (Aspect-Oriented Programming,面向切面的编程),是使用 JDK 动态代理和 CGLIB 动态代理技术来实现的。
-
-
-
- 原代码
-
-
@Slf4j @RestController @RequestMapping("/user") public class UserController { /** 用户服务 */ @Autowired private UserService userService; /** 查询用户 */ @PostMapping("/queryUser") public Result<?> queryUser(@RequestBody @Valid UserQueryVO query) { try { PageDataVO<UserVO> pageData = userService.queryUser(query); return Result.success(pageData); } catch (Exception e) { log.error(e.getMessage(), e); return Result.failure(e.getMessage()); } } ... } |
-
-
-
- 精简
-
-
// UserController代码同"精简1" @Slf4j @Aspect public class WebExceptionAspect { /** 点切面 */ @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)") private void webPointcut() {} /** 处理异常 */ @AfterThrowing(pointcut = "webPointcut()", throwing = "e") public void handleException(Exception e) { Result<Void> result = Result.failure(e.getMessage()); writeContent(JSON.toJSONString(result)); } ... } |
-
- 利用删除代码
“少即是多”,“少”不是空白而是精简,“多”不是拥挤而是完美。删除多余的代码,才能使代码更精简更完美。
-
-
- 删除已废弃的代码
-
删除项目中的已废弃的包、类、字段、方法、变量、常量、导入、注解、注释、已注释代码、Maven包导入、MyBatis的SQL语句、属性配置字段等,可以精简项目代码便于维护。
-
-
-
- 原代码
-
-
-
-
- 删除接口方法的public
-
对于接口(interface),所有的字段和方法都是 public 的,可以不用显式声明为 public 。
-
-
-
- 原代码
-
-
public interface JointQueryService { public abstract List<JointQuery> getQueryList(String billNumber); public abstract Map<String,Object> getQueryRuleMap(String billNumber); } |
-
-
-
- 精简
-
-
public interface JointQueryService { abstract List<JointQuery> getQueryList(String billNumber); abstract Map<String,Object> getQueryRuleMap(String billNumber); } |
-
-
- 删除枚举构造方法的 private
-
对于枚举(menu),构造方法都是 private 的,可以不用显式声明为 private 。
-
-
-
- 原代码
-
-
public enum EnumExtTypeYXY { //外部不分档模式 VAR_255("define","varchar",60,0,255); /** * 扩展字段命名方式 */ private String code; /** * 扩展字段的类型 */ private String type; /** * 扩展表的扩展数量 */ private Integer outerCount; /** * 内部表的扩展数量 */ private Integer innerCount; |
-
-
-
- 精简
-
-
public enum EnumExtTypeYXY { //外部不分档模式 VAR_255("define","varchar",60,0,255); /** * 扩展字段命名方式 */ String code; /** * 扩展字段的类型 */ String type; /** * 扩展表的扩展数量 */ Integer outerCount; /** * 内部表的扩展数量 */ Integer innerCount; |
-
-
- 删除不必要的变量
-
不必要的变量,只会让代码看起来更繁琐。
-
-
-
- 原代码
-
-
public Boolean existsUser(Long userId) { Boolean exists = userDAO.exists(userId); return exists; } |
-
-
-
- 精简
-
-
public Boolean existsUser(Long userId) { return userDAO.exists(userId); } |
-
- 多级for循环
-
-
- 原代码
-
-
-
- 精简
-
业务拆解;大循环在外,小循环在内。
-
- 开放性设计
无
-
- 兼容性设计
无
-
- 其他设计要求
无
- 产品/服务高可用指标
无
- 变更设计
无
- 附录
无