JAVA代码优化实践
创建可缓冲的IO流
IO流想必大家都使用得比较多,我们经常需要把数据写入某个文件,或者从某个文件中读取数据到内存中,甚至还有可能把文件a,从目录b,复制到目录c下等。
JDK给我们提供了非常丰富的API,可以去操作IO流。
例如:
public class IoTest1 {public static void main(String[] args) {FileInputStream fis = null;FileOutputStream fos = null;try {File srcFile = new File("/Users/dv_susan/Documents/workspace/jump/src/main/java/com/sue/jump/service/test1/1.txt");File destFile = new File("/Users/dv_susan/Documents/workspace/jump/src/main/java/com/sue/jump/service/test1/2.txt");fis = new FileInputStream(srcFile);fos = new FileOutputStream(destFile);int len;while ((len = fis.read()) != -1) {fos.write(len);}fos.flush();} catch (IOException e) {e.printStackTrace();} finally {try {if (fos != null) {fos.close();}} catch (IOException e) {e.printStackTrace();}try {if (fis != null) {fis.close();}} catch (IOException e) {e.printStackTrace();}}}
}
这个例子主要的功能,是将1.txt文件中的内容复制到2.txt文件中。这例子使用普通的IO流从功能的角度来说,也能满足需求,但性能却不太好。
因为这个例子中,从1.txt文件中读一个字节的数据,就会马上写入2.txt文件中,需要非常频繁的读写文件。
优化:
public class IoTest {public static void main(String[] args) {BufferedInputStream bis = null;BufferedOutputStream bos = null;FileInputStream fis = null;FileOutputStream fos = null;try {File srcFile = new File("/Users/dv_susan/Documents/workspace/jump/src/main/java/com/sue/jump/service/test1/1.txt");File destFile = new File("/Users/dv_susan/Documents/workspace/jump/src/main/java/com/sue/jump/service/test1/2.txt");fis = new FileInputStream(srcFile);fos = new FileOutputStream(destFile);bis = new BufferedInputStream(fis);bos = new BufferedOutputStream(fos);byte[] buffer = new byte[1024];int len;while ((len = bis.read(buffer)) != -1) {bos.write(buffer, 0, len);}bos.flush();} catch (IOException e) {e.printStackTrace();} finally {try {if (bos != null) {bos.close();}if (fos != null) {fos.close();}} catch (IOException e) {e.printStackTrace();}try {if (bis != null) {bis.close();}if (fis != null) {fis.close();}} catch (IOException e) {e.printStackTrace();}}}
}
这个例子使用BufferedInputStream和BufferedOutputStream创建了可缓冲的输入输出流。
最关键的地方是定义了一个buffer字节数组,把从1.txt文件中读取的数据临时保存起来,后面再把该buffer字节数组的数据,一次性批量写入到2.txt中。
这样做的好处是,减少了读写文件的次数,而我们都知道读写文件是非常耗时的操作。也就是说使用可缓存的输入输出流,可以提升IO的性能,特别是遇到文件非常大时,效率会得到显著提升。
减少循环次数
在我们日常开发中,循环遍历集合是必不可少的操作。
但如果循环层级比较深,循环中套循环,可能会影响代码的执行效率。
反例:
for(User user: userList) {for(Role role: roleList) {if(user.getRoleId().equals(role.getId())) {user.setRoleName(role.getName());}}
}
这个例子中有两层循环,如果userList和roleList数据比较多的话,需要循环遍历很多次,才能获取我们所需要的数据,非常消耗cpu资源。
正例:
Map<Long, List<Role>> roleMap = roleList.stream().collect(Collectors.groupingBy(Role::getId));
for (User user : userList) {List<Role> roles = roleMap.get(user.getRoleId());if(CollectionUtils.isNotEmpty(roles)) {user.setRoleName(roles.get(0).getName());}
}
减少循环次数,最简单的办法是,把第二层循环的集合变成map,这样可以直接通过key,获取想要的value数据。
虽说map的key存在hash冲突的情况,但遍历存放数据的链表或者红黑树的时间复杂度,比遍历整个list集合要小很多。