写在前面
一直从事java开发,下面这些是我日常工作总结出来的小经验。
1、字符串、数值操作相关
1.1、 判断字符串相等
不推荐使用的方式:
String str = null;
// 会报空指针异常
if (str.equals("abc123")) {
... } else { .. }
推荐使用的两种方式:
"abc123".equals(str);// false
Objects.equals(str,"abc123");// false
1.2、 判断字符串为空
StringUtils.isEmpty(str1)、StringUtils.isNotBlank(str1)
判断字符串为空可以用工具类StringUtils
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
1.3、基本数据类型转字符串用.toString()
把一个基本数据类型转为字符串,基本数据类型.toString()是最快的方式、String.valueOf(数据)次之、数据+””最慢
1.4、判断包装类的数值不要用 ==
所有整型包装类对象值的比较必须使用equals方法。
Integer -128~127之间是存的值,其他值是存的地址
1.5、浮点数之间的等值判断用BigDecimal
浮点数之间的等值判断,基本数据类型不能用==来比较,包装数据类型不能用 equals 来判断。
float a = 1.0f - 0.9f;
float b = 0.9f - 0.8f;
System.out.println(a);// 0.100000024
System.out.println(b);// 0.099999964
System.out.println(a == b);// false
使用 BigDecimal 来定义浮点数的值,再进行浮点数的运算操作。
BigDecimal a = new BigDecimal("1.0");
BigDecimal b = new BigDecimal("0.9");
BigDecimal c = new BigDecimal("0.8");
BigDecimal x = a.subtract(b);
BigDecimal y = b.subtract(c);
System.out.println(x); /* 0.1 */
System.out.println(y); /* 0.1 */
System.out.println(Objects.equals(x, y)); /* true */
1.6、基本数据类型与包装数据类型的使用标准
Reference:《阿里巴巴Java开发手册》
【强制】所有的 POJO 类属性必须使用包装数据类型。
【强制】RPC 方法的返回值和参数必须使用包装数据类型。
【推荐】所有的局部变量使用基本数据类型。
比如我们如果自定义了一个Student类,其中有一个属性是成绩score,如果用Integer而不用int定义,一次考试,学生可能没考,值是null,也可能考了,但考了0分,值是0,这两个表达的状态明显不一样
2、for循环相关
2.1、在for循环外面定义变量
String str = "";
List<String> list = new ArrayList<>();
for(int i=0;i<1000;i++){
str = "第 " + i + " 个";
list.add(str);
}
如上str的定义,如果放在for里面,就会造成1000个变量在内存中出现,只有当当前方法结束,才可能被释放
2.2、List被for出来的对象改变,List也会改变
List<String> list = new ArrayList<>();
for(String s:list){
s = s + “abc”;
}
如上代码,list循环完之后里面的值已经发生了改变(每个对象的地址不会变),不用再new一个list往里面添加
2.3、减少重复计算
例如下面的操作:
for (int i = 0; i < list.size(); i++)
{...}
建议替换为:
for (int i = 0, int length = list.size(); i < length; i++)
{...}
2.4、try…catch…应该放在循环外面
不要在循环中使用try…catch…,应该把其放在最外层
3、集合、对象、程序结构
3.1、检查Map里面是否有某个key
containskey(keyName)
3.2、对象深拷贝
BeanUtils.copyProperties(param,param1);
这个工具类是org.springframework.beans.BeanUtils.copyProperties提供的,可以代替字段一个一个的get、set
3.3、一个对象在需要的时候再去创建
例如:
String str = "aaa";
if (i == 1){
list.add(str);
}
建议替换为:
if (i == 1){
String str = "aaa";
list.add(str);
}
3.4、在适当的时候使用System.gc()
如果某个对象所占内存较大,或者当前对象数量很多,我们可以使用System.gc(),及时释放内存,一般用在一个方法体末尾。
调用gc()函数表明Java虚拟机花费了很多精力来回收未使用的对象,以使它们当前占用的内存可用于快速重用。当控制从方法调用返回时,Java虚拟机已尽最大努力从所有丢弃的对象中回收空间。在注释中也明确的说明了,调用System.gc()等同于调用Runtime.getRuntime().gc()。
gc()也不能保证一定进行回收(如果-XX:+DisableExplicitGC设置成true,则不会进行回收)。
3.5、apache的FileUtils
做文件操作的时候,自己去些FileUtils比较麻烦,可以使用apache的FileUtils。如下写入List并指定编码到文件中:
import org.apache.commons.io.FileUtils;
File f = new File(fileName);
FileUtils.writeLines(f, "GBK", list);
3.6、能估计到内容长度,为底层以数组方式实现的集合、工具类指定初始长度
比如ArrayList、LinkedLlist、StringBuilder、StringBuffer、HashMap、HashSet等等,以StringBuilder为例:
(1)StringBuilder() // 默认分配16个字符的空间
(2)StringBuilder(int size) // 默认分配size个字符的空间
(3)StringBuilder(String str) // 默认分配16个字符+str.length()个字符空间
3.7、复制大量数据时,使用System.arraycopy()
如下例:
public class SsytemArrayCopy {
public static void main(String[] args) {
User [] users=new User[]{new User(1,"admin","admin@qq.com"),new User(2,"maco","maco@qq,com"),new User(3,"kitty","kitty@qq,com")};//初始化对象数组
User [] target=new User[users.length];//新建一个目标对象数组
System.arraycopy(users, 0, target, 0, users.length);//实现复制
System.out.println("源对象与目标对象的物理地址是否一样:"+(users[0] == target[0]?"浅复制":"深复制"));
target[0].setEmail("admin@sina.com");
System.out.println("修改目标对象的属性值后源对象users:");
for (User user : users){
System.out.println(user);
}
}
}
class User{
private Integer id;
private String username;
private String email;
//无参构造函数
public User() { }
//有参的构造函数
public User(Integer id, String username, String email) {
super();
this.id = id;
this.username = username;
this.email = email;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", email=" + email
+ "]";
}
}
3.8、遍历Map最快的方式
HashMap<String, String> hm = new HashMap<String, String>();
hm.put("111", "222");
Set<Map.Entry<String, String>> entrySet = hm.entrySet();
Iterator<Map.Entry<String, String>> iter = entrySet.iterator();
while (iter.hasNext()){
Map.Entry<String, String> entry = iter.next();
System.out.println(entry.getKey() + " " + entry.getValue());
}