首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >老板看了我的代码,直呼“666”,说涨工资!

老板看了我的代码,直呼“666”,说涨工资!

作者头像
程序员小强
发布于 2019-10-30 07:13:30
发布于 2019-10-30 07:13:30
39600
代码可运行
举报
运行总次数:0
代码可运行

作者:涛姐涛哥 来源:https://url.cn/5PswiUJ

如何更规范化编写Java 代码的重要性想必毋需多言,其中最重要的几点当属提高代码性能、使代码远离Bug、令代码更优雅。

一、MyBatis 不要为了多个查询条件而写 1 = 1

当遇到多个查询条件,使用where 1=1 可以很方便的解决我们的问题,但是这样很可能会造成非常大的性能损失,因为添加了 “where 1=1 ”的过滤条件之后,数据库系统就无法使用索引等查询优化策略,数据库系统将会被迫对每行数据进行扫描(即全表扫描) 以比较此行是否满足过滤条件,当表中的数据量较大时查询速度会非常慢;此外,还会存在SQL 注入的风险。

反例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<select id="queryBookInfo" parameterType="com.tjt.platform.entity.BookInfo" resultType="java.lang.Integer">
 select count(*) from t_rule_BookInfo t where 1=1
<if test="title !=null and title !='' ">
 AND title = #{title}
</if>
<if test="author !=null and author !='' ">
 AND author = #{author}
</if>
</select>

正例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<select id="queryBookInfo" parameterType="com.tjt.platform.entity.BookInfo" resultType="java.lang.Integer">
 select count(*) from t_rule_BookInfo t
<where>
<if test="title !=null and title !='' ">
 title = #{title}
</if>
<if test="author !=null and author !='' ">
 AND author = #{author}
</if>
</where>
</select>

UPDATE 操作也一样,可以用 标记代替 1=1。

二、迭代entrySet() 获取Map 的key 和value

当循环中只需要获取Map 的主键key时,迭代keySet() 是正确的;但是,当需要主键key 和取值value 时,迭代entrySet() 才是更高效的做法,其比先迭代keySet() 后再去通过get 取值性能更佳。

反例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//Map 获取value 反例:
HashMap<String, String> map = new HashMap<>();
for (String key : map.keySet()){
    String value = map.get(key);
}

正例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//Map 获取key & value 正例:
HashMap<String, String> map = new HashMap<>();
for (Map.Entry<String,String> entry : map.entrySet()){
 String key = entry.getKey();
 String value = entry.getValue();
}

三、使用Collection.isEmpty() 检测空

使用Collection.size() 来检测是否为空在逻辑上没有问题,但是使用Collection.isEmpty() 使得代码更易读,并且可以获得更好的性能;除此之外,任何Collection.isEmpty() 实现的时间复杂度都是O(1) ,不需要多次循环遍历,但是某些通过Collection.size() 方法实现的时间复杂度可能是O(n)

反例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
LinkedList<Object> collection = new LinkedList<>();
if (collection.size() == 0){
 System.out.println("collection is empty.");
}

正例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
LinkedList<Object> collection = new LinkedList<>();
if (collection.isEmpty()){
    System.out.println("collection is empty.");
}

//检测是否为null 可以使用CollectionUtils.isEmpty()
if (CollectionUtils.isEmpty(collection)){
    System.out.println("collection is null.");

}

四、初始化集合时尽量指定其大小

尽量在初始化时指定集合的大小,能有效减少集合的扩容次数,因为集合每次扩容的时间复杂度很可能时O(n),耗费时间和性能。

反例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//初始化list,往list 中添加元素反例:
int[] arr = new int[]{1,2,3,4};
List<Integer> list = new ArrayList<>();
for (int i : arr){
 list.add(i);
}

正例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//初始化list,往list 中添加元素正例:
int[] arr = new int[]{1,2,3,4};
//指定集合list 的容量大小
List<Integer> list = new ArrayList<>(arr.length);
for (int i : arr){
    list.add(i);
}

五、使用StringBuilder 拼接字符串

一般的字符串拼接在编译期Java 会对其进行优化,但是在循环中字符串的拼接Java 编译期无法执行优化,所以需要使用StringBuilder 进行替换。

反例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//在循环中拼接字符串反例
String str = "";
for (int i = 0; i < 10; i++){
    //在循环中字符串拼接Java 不会对其进行优化
    str += i;
}

正例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//在循环中拼接字符串正例
String str1 = "Love";
String str2 = "Courage";
String strConcat = str1 + str2;  //Java 编译器会对该普通模式的字符串拼接进行优化
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10; i++){
   //在循环中,Java 编译器无法进行优化,所以要手动使用StringBuilder
    sb.append(i);
}

六、若需频繁调用Collection.contains 方法则使用Set

在Java 集合类库中,List的contains 方法普遍时间复杂度为O(n),若代码中需要频繁调用contains 方法查找数据则先将集合list 转换成HashSet 实现,将O(n) 的时间复杂度将为O(1)。

反例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//频繁调用Collection.contains() 反例
List<Object> list = new ArrayList<>();
for (int i = 0; i <= Integer.MAX_VALUE; i++){
    //时间复杂度为O(n)
    if (list.contains(i))
    System.out.println("list contains "+ i);
}

正例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//频繁调用Collection.contains() 正例
List<Object> list = new ArrayList<>();
Set<Object> set = new HashSet<>();
for (int i = 0; i <= Integer.MAX_VALUE; i++){
    //时间复杂度为O(1)
    if (set.contains(i)){
        System.out.println("list contains "+ i);
    }
}

七、使用静态代码块实现赋值静态成员变量

对于集合类型的静态成员变量,应该使用静态代码块赋值,而不是使用集合实现来赋值。

反例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//赋值静态成员变量反例
private static Map<String, Integer> map = new HashMap<String, Integer>(){
    {
        map.put("Leo",1);
        map.put("Family-loving",2);
        map.put("Cold on the out side passionate on the inside",3);
    }
};
private static List<String> list = new ArrayList<>(){
    {
        list.add("Sagittarius");
        list.add("Charming");
        list.add("Perfectionist");
    }
};

正例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//赋值静态成员变量正例
private static Map<String, Integer> map = new HashMap<String, Integer>();
static {
    map.put("Leo",1);
    map.put("Family-loving",2);
    map.put("Cold on the out side passionate on the inside",3);
}

private static List<String> list = new ArrayList<>();
static {
    list.add("Sagittarius");
    list.add("Charming");
    list.add("Perfectionist");
}

八、删除未使用的局部变量、方法参数、私有方法、字段和多余的括号

九、工具类中屏蔽构造函数

工具类是一堆静态字段和函数的集合,其不应该被实例化;但是,Java 为每个没有明确定义构造函数的类添加了一个隐式公有构造函数,为了避免不必要的实例化,应该显式定义私有构造函数来屏蔽这个隐式公有构造函数。

反例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class PasswordUtils {
//工具类构造函数反例
private static final Logger LOG = LoggerFactory.getLogger(PasswordUtils.class);

public static final String DEFAULT_CRYPT_ALGO = "PBEWithMD5AndDES";

public static String encryptPassword(String aPassword) throws IOException {
    return new PasswordUtils(aPassword).encrypt();
}

正例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class PasswordUtils {
//工具类构造函数正例
private static final Logger LOG = LoggerFactory.getLogger(PasswordUtils.class);

//定义私有构造函数来屏蔽这个隐式公有构造函数
private PasswordUtils(){}

public static final String DEFAULT_CRYPT_ALGO = "PBEWithMD5AndDES";

public static String encryptPassword(String aPassword) throws IOException {
    return new PasswordUtils(aPassword).encrypt();
}

十、删除多余的异常捕获并跑出

用catch 语句捕获异常后,若什么也不进行处理,就只是让异常重新抛出,这跟不捕获异常的效果一样,可以删除这块代码或添加别的处理。

反例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//多余异常反例
private static String fileReader(String fileName)throws IOException{

    try (BufferedReader reader = new BufferedReader(new FileReader(fileName))) {
        String line;
        StringBuilder builder = new StringBuilder();
        while ((line = reader.readLine()) != null) {
            builder.append(line);
        }
        return builder.toString();
    } catch (Exception e) {
        //仅仅是重复抛异常 未作任何处理
        throw e;
    }
}

正例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//多余异常正例
private static String fileReader(String fileName)throws IOException{

    try (BufferedReader reader = new BufferedReader(new FileReader(fileName))) {
        String line;
        StringBuilder builder = new StringBuilder();
        while ((line = reader.readLine()) != null) {
            builder.append(line);
        }
        return builder.toString();
        //删除多余的抛异常,或增加其他处理:
        /*catch (Exception e) {
            return "fileReader exception";
        }*/
    }
}

十一、字符串转化使用String.valueOf(value) 代替 " " + value

把其它对象或类型转化为字符串时,使用String.valueOf(value) 比 ""+value 的效率更高。

反例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//把其它对象或类型转化为字符串反例:
int num = 520;
// "" + value
String strLove = "" + num;

正例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//把其它对象或类型转化为字符串正例:
int num = 520;
// String.valueOf() 效率更高
String strLove = String.valueOf(num);

十二、避免使用BigDecimal(double)

BigDecimal(double) 存在精度损失风险,在精确计算或值比较的场景中可能会导致业务逻辑异常。

反例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// BigDecimal 反例
BigDecimal bigDecimal = new BigDecimal(0.11D);

正例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// BigDecimal 正例
BigDecimal bigDecimal1 = bigDecimal.valueOf(0.11D);

十三、返回空数组和集合而非 null

若程序运行返回null,需要调用方强制检测null,否则就会抛出空指针异常;返回空数组或空集合,有效地避免了调用方因为未检测null 而抛出空指针异常的情况,还可以删除调用方检测null 的语句使代码更简洁。

反例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//返回null 反例
public static Result[] getResults() {
    return null;
}

public static List<Result> getResultList() {
    return null;
}

public static Map<String, Result> getResultMap() {
    return null;
}

正例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//返回空数组和空集正例
public static Result[] getResults() {
    return new Result[0];
}

public static List<Result> getResultList() {
    return Collections.emptyList();
}

public static Map<String, Result> getResultMap() {
    return Collections.emptyMap();
}

十四、优先使用常量或确定值调用equals 方法

对象的equals 方法容易抛空指针异常,应使用常量或确定有值的对象来调用equals 方法。

反例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//调用 equals 方法反例
private static boolean fileReader(String fileName)throws IOException{

 // 可能抛空指针异常
 return fileName.equals("Charming");
}

正例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//调用 equals 方法正例
private static boolean fileReader(String fileName)throws IOException{

    // 使用常量或确定有值的对象来调用 equals 方法
    return "Charming".equals(fileName);

    //或使用:java.util.Objects.equals() 方法
   return Objects.equals("Charming",fileName);
}

十五、枚举的属性字段必须是私有且不可变

枚举通常被当做常量使用,如果枚举中存在公共属性字段或设置字段方法,那么这些枚举常量的属性很容易被修改;理想情况下,枚举中的属性字段是私有的,并在私有构造函数中赋值,没有对应的Setter 方法,最好加上final 修饰符。

反例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public enum SwitchStatus {
    // 枚举的属性字段反例
    DISABLED(0, "禁用"),
    ENABLED(1, "启用");

    public int value;
    private String description;

    private SwitchStatus(int value, String description) {
        this.value = value;
        this.description = description;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}

正例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public enum SwitchStatus {
    // 枚举的属性字段正例
    DISABLED(0, "禁用"),
    ENABLED(1, "启用");

    // final 修饰
    private final int value;
    private final String description;

    private SwitchStatus(int value, String description) {
        this.value = value;
        this.description = description;
    }

    // 没有Setter 方法
    public int getValue() {
        return value;
    }

    public String getDescription() {
        return description;
    }
}

十六、tring.split(String regex)部分关键字需要转译

使用字符串String 的plit 方法时,传入的分隔字符串是正则表达式,则部分关键字(比如 .[]()| 等)需要转义。

反例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// String.split(String regex) 反例
String[] split = "a.ab.abc".split(".");
System.out.println(Arrays.toString(split));   // 结果为[]

String[] split1 = "a|ab|abc".split("|");
System.out.println(Arrays.toString(split1));  // 结果为["a", "|", "a", "b", "|", "a", "b", "c"]

正例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// String.split(String regex) 正例
// . 需要转译
String[] split2 = "a.ab.abc".split("\\.");
System.out.println(Arrays.toString(split2));  // 结果为["a", "ab", "abc"]

// | 需要转译
String[] split3 = "a|ab|abc".split("\\|");
System.out.println(Arrays.toString(split3));  // 结果为["a", "ab", "abc"]

End

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-10-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 MoziInnovations 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
Apache Superset1.2.0教程(四)—— CentOS环境安装
前文中,我们已经在windows环境进行了superset的安装,也对图表功能进行了展示。但是在平时使用以及生产环境中,还是需要在centos环境下进行操作。
大数据流动
2021/08/13
1.7K2
Apache Superset1.2.0教程(四)—— CentOS环境安装
CentOS 7上MySQL主从同步的实现
CentOS 7环境部署MySQL主从服务器,根据PHP程序员的要求创建数据库与表。
星哥玩云
2022/08/16
5050
CentOS 7上MySQL主从同步的实现
CentOS 6.4编译安装MySQL8.0
MySQL 8.0 正式版 8.0.11 已发布,官方表示 MySQL 8 要比 MySQL 5.7 快 2 倍,还带来了大量的改进和更快的性能!
星哥玩云
2022/08/16
5820
CentOS6.7下使用 cmake编译安装MySQL5.5.32
cmake是一个跨平台的开源元构建系统,可以构建、测试和打包软件。它可以用来支持多种本地构建环境,包括make,苹果的xcode和微软的Visual Studio,本篇文章将在CentOS6.7下使用 cmake编译安装MySQL5.5.32。
用户9042463
2021/09/30
8600
CentOS7(Linux)源码安装MySQL5.7.30
软件应用最重要的就是数据库了,可是还有小伙伴不会在Linux上安装MySQL数据库,今天就来讲讲如何在CentOS7环境使用源码进行安装MySQL5.7.30。
一个正经的程序员
2022/04/11
7210
CentOS7(Linux)源码安装MySQL5.7.30
Centos搭建powerdns权威dns服务器——安装篇
DNS(Domain Name Service) 域名解析服务,就是将域名和 ip 之间做相应的转换,利用 TCP 和 UDP 的53端口。
山深有杏
2024/01/30
2K0
Centos搭建powerdns权威dns服务器——安装篇
CentOS7下源码安装MySQL 8.x
会选择使用源码安装MySQL,想必对MySQL及其他的安装方式已经有了一定的了解,这里就不对周边信息进行过多赘述了,直接开始吧。
端碗吹水
2020/09/23
8870
CentOS7下源码安装MySQL 8.x
使用lamp搭建博客_php laravel框架
部署 lamp平台–Linux、Apache、MySQL 与 PHP–源码编译安装
全栈程序员站长
2022/11/07
1.2K0
使用lamp搭建博客_php laravel框架
CentOS 7 安装Percona Mysql Server
此方法我也不知道为什么在CentOS7里面安装之后可以用,在Debian服务器里面无法进行编译安装使用。另外在使用的过程中,有时候可能也需要Percona-Server-client的支持。针对这个问题,可以使用以下方法解决:将文件上传到/home/soft/目录下,然后进行安装。安装方法如下:
Tacc
2022/01/11
5540
CentOS 7 安装Percona Mysql Server
centos-6.5安装部署LNMP环境
安装依赖库:yum -y install zlib zlib-devel openssl openssl-devel pcre-devel
用户1679793
2019/02/15
7240
linux(centos7)源码安装系列-mysql
1.下载源码包 wget https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.36.tar.gz 2.创建mysql用户 useradd -M -s /sbin/nologin mysql 3.创建mysql数据目录及日志目录,并更改目录所有者 mkdir -p /usr/local/mysql/data mkdir -p /usr/local/mysql/log chown -R mysql:mysql /usr/local/mysql
用户8568307
2022/03/14
5560
【玩转服务器】CentOS下安装mysql
mysql 是一个关系型数据库管理系统,是最流行的关系型数据库管理系统之一,本文将介绍如何在 CentOS 7.x 中安装 mysql 。
参谋带个长
2023/12/11
5830
centos7.4安装LNMP
系统最小化安装,只安装了一些常用包(vim、lirzs、gcc*、wget、bash-completion)
萧晚歌
2020/08/19
9730
Superset 部署
Apache Superset是一个现代的数据探索和可视化平台。它功能强大且十分易用,可对接各种数据源,包括很多现代的大数据分析引擎,拥有丰富的图表展示形式,并且支持自定义仪表盘,且Superset是由Python语言编写的Web应用,要求Python3.7以上的环境
码农GT038527
2024/08/29
3350
Python中操作mysql知识(一)
Python 标准数据库接口为 Python DB-API,Python DB-API为开发人员提供了数据库应用编程接口。
py3study
2020/01/06
6350
Python中操作mysql知识(一)
源码包编译安装mysql & cmake 原
环境: OS:centos 7 _ x86_64 MySQL:mysql-5.6.35
阿dai学长
2019/04/03
2.8K0
CentOS下源码编译安装LNMP(附源码包)
LNMP指的是一个基于CentOS/Debian编写的Nginx、PHP、MySQL、phpMyAdmin、eAccelerator一键安装包。可以在VPS、独立主机上轻松的安装LNMP生产环境。LNMP代表的就是:Linux系统下Nginx+MySQL+PHP这种网站服务器架构。Linux是一类Unix计算机操作系统的统称,是目前最流行的免费操作系统。代表版本有:debian、centos、Ubuntu、Fedora、gentoo等;Nginx是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP代理服务器;Mysql是一个小型关系型数据库管理系统;PHP是一种在服务器端执行的嵌入HTML文档的脚本语言。这四种软件均为免费开源软件,组合到一起,成为一个免费、高效、扩展性强的网站服务系统。
星哥玩云
2022/07/14
1.7K0
CentOS下源码编译安装LNMP(附源码包)
Centos 7安装mysql-5.7.22
wget https://mirrors.aliyun.com/epel/epel-release-latest-7.noarch.rpm
py3study
2018/08/03
1K0
linux之在centos7中配置java开发环境
首先下载好相应的Linux版本的jdk、tomcat、eclipse、mysql,然后利用xftp5上传到/opt目录下
西西嘛呦
2020/08/26
5750
VPS重做系统都需要做什么
可以参考 http://dev.mysql.com/doc/refman/5.6/en/source-configuration-options.html
老高的技术博客
2022/12/27
1K0
相关推荐
Apache Superset1.2.0教程(四)—— CentOS环境安装
更多 >
LV.1
米扑科技技术总监
目录
  • 一、MyBatis 不要为了多个查询条件而写 1 = 1
  • 二、迭代entrySet() 获取Map 的key 和value
  • 三、使用Collection.isEmpty() 检测空
  • 四、初始化集合时尽量指定其大小
  • 五、使用StringBuilder 拼接字符串
  • 六、若需频繁调用Collection.contains 方法则使用Set
  • 七、使用静态代码块实现赋值静态成员变量
  • 八、删除未使用的局部变量、方法参数、私有方法、字段和多余的括号
  • 九、工具类中屏蔽构造函数
  • 十、删除多余的异常捕获并跑出
  • 十一、字符串转化使用String.valueOf(value) 代替 " " + value
  • 十二、避免使用BigDecimal(double)
  • 十三、返回空数组和集合而非 null
  • 十四、优先使用常量或确定值调用equals 方法
  • 十五、枚举的属性字段必须是私有且不可变
  • 十六、tring.split(String regex)部分关键字需要转译
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档