昨天在青铜时代群里看到读者朋友们在讨论 Java 最常用的工具类,我觉得大家推荐的确实都挺常见的,我自己用的频率也蛮高的。恰好我在 programcreek 上看到过一篇类似的文章,就想着梳理一下分享给大家。
在 Java 中,工具类通常用来定义一组执行通用操作的方法。本篇文章将会向大家展示 8 个工具类以及它们最常用的方法,类的排名和方法的排名均来自可靠的数据,从 GitHub 上最受欢迎的 50000 个开源 Java 项目中精心挑选。
为了方便大家的理解,我会在介绍每个类的方法时写一段小 Demo,这样大家就能知道每个方法该怎么用。放心吧,方法是干嘛的我也不会保密的。😄
1)IOUtils
mons.io.IOUtils
,操作 IO 流的工具类,下面是其常用的方法。
closeQuietly()
,关闭 IO 流,并且忽略 null 值和异常。
IOUtils.closeQuietly(output);
copy()
,将字节从输入流复制到输出流。
IOUtils.copy(inputStream, new FileOutputStream(File));
toByteArray()
,以byte[]
的形式获取输入流中的内容。
URLConnection conn = new URL(url).openConnection();InputStream is = conn.getInputStream();byte[] result = IOUtils.toByteArray(is);
write()
,将字符或者字节写入输出流中。
IOUtils.write("沉默王二", response.getOutputStream(), "UTF-8");
toInputStream()
,将指定的字符转成输入流。
String content=req.getParameter("content");InputStream inputStream=IOUtils.toInputStream(content,"utf-8");
readLines()
,从输入流中一行一行地读取,并按照指定的字符编码返回字符串列表。
List<String> lines = IOUtils.readLines(new InputStreamReader(new FileInputStream(file), "utf-8"));
copyLarge()
,从输入流中复制内容到输出流,超过 2GB。
private File downloadFile(HttpResponse response) {File dir = new File("downloadedFiles");if (!dir.exists()) {dir.mkdir();}File outputFile = new File("downloadedFiles/temp" + RandomStringUtils.randomAlphanumeric(3));try {IOUtils.copyLarge(response.getEntity().getContent(), new FileOutputStream(outputFile));return outputFile;} catch (Exception e) {throw new RuntimeException(e);} finally {request.releaseConnection();}}
readFully()
,把输入流中的内容读入到字节数组中。
byte[] intArray = new byte[Bytes.SIZEOF_INT];IOUtils.readFully(in, intArray);
2)FileUtils
mons.io.FileUtils
,操作文件或者目录的工具类,下面是其常用的方法。
deleteDirectory()
,删除目录。
FileUtils.deleteDirectory(file);
readFileToString()
,把文件的内容读入到字符串中。
String fileAsString = FileUtils.readFileToString(reportFile);
deleteQuietly()
,删除文件,但不抛出异常。
FileUtils.deleteQuietly(outputFile);
copyFile()
,把文件复制到一个新的位置。
FileUtils.copyFile(source, dest);
writeStringToFile()
,把字符串写入到文件。
FileUtils.writeStringToFile(templateFile, generatedText, Charset.forName("UTF-8"));
forceMkdir()
,强制创建目录,包括任何必需但不存在的父目录。
File uploadDirectory = new File(this.uploadPath);if (!uploadDirectory.exists()) {FileUtils.forceMkdir(uploadDirectory);}
write()
,把字符或者字节写入到文件。
FileUtils.write(new File("C:\\Users\\cmower\\test.txt"), "沉默王二", "utf-8");
listFiles()
,列出指定目录下的所有文件。
public void processResultsDirectory(String dirName) {File root = new File(dirName);try {Collection<File> files = FileUtils.listFiles(root,new RegexFileFilter(jmeterJTLFileName),DirectoryFileFilter.DIRECTORY);for (Iterator<File> iterator = files.iterator(); iterator.hasNext();) {File file = (File) iterator.next();parse(file);}} catch (Exception e) {e.printStackTrace();}}
copyDirectory()
,将目录下的所有子目录及文件复制到新的目录。
FileUtils.copyDirectory(source, dest);
forceDelete()
,强制删除文件或者目录及其所有子目录和文件。
FileUtils.forceDelete(tmpFile);
3)StringUtils
mons.lang3.StringUtils
,操作字符串的工具类,并且是 null 安全的,下面是其常用的方法。
isBlank()
,检查字符是否为空字符串"",或者 null,或者空格。
if (StringUtils.isBlank(name)){throw new IllegalArgumentException("姓名不能为空");}
检查结果如下所示。
StringUtils.isBlank(null)= trueStringUtils.isBlank("") = trueStringUtils.isBlank(" ") = trueStringUtils.isBlank("沉默王二")= falseStringUtils.isBlank(" 沉默王二 ") = false
isNotBlank()
,与isBlank()
检查的结果相反。
isEmpty()
,检查字符是否为空字符串"",或者 null;和isBlank()
不同,不包括空格的检查。
if (StringUtils.isEmpty(name)) {throw new IllegalArgumentException("姓名不能为 null 或者空字符串");}
检查结果如下所示。
StringUtils.isEmpty(null)= trueStringUtils.isEmpty("") = trueStringUtils.isEmpty(" ") = falseStringUtils.isEmpty("沉默王二")= falseStringUtils.isEmpty(" 沉默王二 ") = false
isNotEmpty()
,与isEmpty()
检查的结果相反。
join()
,将多个元素连接成一个字符串。
StringUtils.join(null) = nullStringUtils.join([]) = ""StringUtils.join([null])= ""StringUtils.join(["沉默", "王二"]) = "沉默王二"StringUtils.join([null, "", "一枚有趣的程序员"]) = "一枚有趣的程序员"
equals()
,比较两个字符序列是否相等。
StringUtils.equals(null, null) = trueStringUtils.equals(null, "沉默王二") = falseStringUtils.equals("沉默王二", null) = falseStringUtils.equals("沉默王二", "沉默王二") = trueStringUtils.equals("cmower", "CMOWER") = false
split()
,把字符串拆分为数组,拆分符为空白字符。
StringUtils.split(null) = nullStringUtils.split("") = []StringUtils.split("沉默王二 沉默王三") = ["沉默王二", "沉默王三"]StringUtils.split("沉默王二 沉默王三") = ["沉默王二", "沉默王三"]StringUtils.split(" 沉默王二 ") = ["沉默王二"]
replace()
,替换另一个字符串中所有出现的字符串。
StringUtils.replace(null, *, *) = nullStringUtils.replace("", *, *)= ""StringUtils.replace("any", null, *) = "any"StringUtils.replace("any", *, null) = "any"StringUtils.replace("any", "", *)= "any"StringUtils.replace("沉默王二", "二", null) = "沉默王二"StringUtils.replace("沉默王二", "二", "") = "沉默王"StringUtils.replace("沉默王二", "二", "三") = "沉默王三"
4)FilenameUtils
mons.io.FilenameUtils
,操作文件名或者路径的工具类,下面是其常用的方法。
getExtension()
,获取文件的扩展名。
FilenameUtils.getExtension("牛逼.txt"); --> "txt"FilenameUtils.getExtension("a/b/牛逼.jpg"); --> "jpg"FilenameUtils.getExtension("a/牛逼.txt/c"); --> ""FilenameUtils.getExtension("a/b/c"); --> ""
getBaseName()
,获取单纯的文件名或者路径名,文件时去掉路径和扩展名;路径时去掉父级路径。
FilenameUtils.getBaseName("a/b/牛逼.txt"); --> "牛逼"FilenameUtils.getBaseName("牛逼.txt"); --> "牛逼"FilenameUtils.getBaseName("a/b/c");--> cFilenameUtils.getBaseName("a/b/c/"); --> ""
getName()
,如果是文件时,获取文件名和后缀,去掉路径;如果是路径时,去掉父级路径。
FilenameUtils.getName("a/b/牛逼.txt"); --> "牛逼.txt"FilenameUtils.getName("牛逼.txt"); --> "牛逼.txt"FilenameUtils.getName("a/b/c");--> cFilenameUtils.getName("a/b/c/"); --> ""
concat()
,将路径和文件名连接在一起。
FilenameUtils.concat("/foo/", "bar");--> /foo/barFilenameUtils.concat("/foo", "bar"); --> /foo/barFilenameUtils.concat("/foo", "/bar");--> /barFilenameUtils.concat("/foo", "C:/bar"); --> C:/barFilenameUtils.concat("/foo", "C:bar"); --> C:bar (*)FilenameUtils.concat("/foo/a/", "../bar");--> foo/barFilenameUtils.concat("/foo/", " ../../bar"); --> nullFilenameUtils.concat("/foo/", "/bar"); --> /barFilenameUtils.concat("/foo/.. ", "/bar"); --> /barFilenameUtils.concat("/foo", " bar/c.txt");--> /foo/bar/c.txtFilenameUtils.concat("/foo/c.txt", "bar");--> /foo/c.txt/bar (!)
wildcardMatch()
,检查文件名是否匹配指定的格式。
wildcardMatch("c.txt", "*.txt")--> truewildcardMatch("c.txt", "*.jpg")--> falsewildcardMatch("a/b/c.txt", "a/b/*") --> truewildcardMatch("c.txt", "*.???")--> truewildcardMatch("c.txt", "*.????")--> false
separatorsToUnix()
,将所有分隔符转换为正斜杠的 Unix 分隔符。
FilenameUtils.separatorsToUnix("my/unix/filename");
getFullPath()
,获取文件的完整路径。
getFullPath("C:\a\b\c.txt" --> C:\a\b\getFullPath("~/a/b/c.txt" --> ~/a/b/getFullPath("a.txt" --> ""
5)ArrayUtils
mons.lang3.ArrayUtils
,操作数组的工具类,下面是其常用的方法。
contains()
,检查数组中是否包含某个值
public static boolean containsAll(Object[] one, Object[] two) {for (Object b : two) {if (!ArrayUtils.contains(one, b)) {return false;}}return true;}
addAll()
,将所有元素添加到一个数组中。
ArrayUtils.addAll(null, null)= nullArrayUtils.addAll(array1, null) = cloned copy of array1ArrayUtils.addAll(null, array2) = cloned copy of array2ArrayUtils.addAll([], []) = []ArrayUtils.addAll([null], [null]) = [null, null]ArrayUtils.addAll(["a", "b", "c"], ["1", "2", "3"]) = ["a", "b", "c", "1", "2", "3"]
clone()
,浅拷贝一个数组。
public QualityGateTask[] getQueue() {return (QualityGateTask[]) ArrayUtils.clone(queue);}
isEmpty()
,检查数组是否为 null 或者没有元素。
if (ArrayUtils.isEmpty(objectIds)) {throw new IllegalArgumentException("对象的ID不能为空");}
add()
,在数组中添加一个新的元素,原数组不变。
ArrayUtils.add(null, true)= [true]ArrayUtils.add([true], false) = [true, false]ArrayUtils.add([true, false], true) = [true, false, true]
subarray()
,根据起始下标和结束下标截取一个子数组。
public byte[] fetchData(String blobKey, long startIndex, long l) {CountingInputStream inputStream = new CountingInputStream(getInputStream(blobKey));byte[] bytes = new byte[(int) l];try {int readSize = inputStream.read(bytes, (int) startIndex, (int) l);if (readSize < l) {bytes = ArrayUtils.subarray(bytes, 0, readSize - 1);}} catch (IOException e) {LOGGER.warn("Failed to read bytes", e);} finally {try {inputStream.close();} catch (IOException ignored) {LOGGER.warn("Exception while closing inputStream", ignored);}}return bytes;}
indexOf()
,找出指定数组的下标。
ArrayUtils.indexOf(idxVal, i);
6)DigestUtils
mons.codec.digest.DigestUtils
,加密的工具类,下面是其常用的方法。
md5Hex()
,计算字符串的 MD5 摘要,并返回 32 位的十六进制字符。
DigestUtils.md5Hex("沉默王二");
md5()
,计算字符串的 MD5 摘要,并返回 16 个元素的字节数组。
DigestUtils.md5("沉默王二");
7)StringEscapeUtils
mons.text.StringEscapeUtils
,字符串的转义和反转义工具类,下面是其常用的方法。
unescapeHtml4()
,反转义 HTML。
StringEscapeUtils.unescapeHtml4("<div></div>");--> <div></div>
escapeHtml4()
,转义 HTML。
StringEscapeUtils.escapeHtml4("<div></div>");--> <div></div>
escapeJava()
,转义 Java。
StringEscapeUtils.escapeJava("沉默王二");--> \u6C89\u9ED8\u738B\u4E8C
unescapeJava()
StringEscapeUtils.escapeJava("\u6C89\u9ED8\u738B\u4E8C");--> 沉默王二
8)BeanUtils
大多数 Java 开发人员习惯于创建getter/setter
的JavaBean,然后通过调用相应的getXxx
和setXxx
方法访问对应字段。但在某些情况下,需要动态访问 Java 对象的属性,mons.beanutils.BeanUtils
就派上用场了。
copyProperties()
,拷贝所有属性。
private static void dto2Entity() {UserDTO user = new UserDTO();user.setId(1l);user.setUsername("joking");user.setCreationDate("-04-20");EUser u = new EUser();ConvertUtils.register(new DateStringConverter(), Date.class);try {BeanUtils.copyProperties(u, user);} catch (IllegalAccessException | InvocationTargetException e) {e.printStackTrace();}}
其中 UserDTO 类的源码如下所示。
public class UserDTO implements Serializable {private static final long serialVersionUID = 2963408818099106614L;private long id;private String username;private String creationDate;// getter/setter@Overridepublic String toString() {return "UserDTO [id=" + id + ", username=" + username + ", creationDate=" + creationDate + "]";}}
其中 EUser 类的源码如下所示。
public class EUser implements Serializable {private static final long serialVersionUID = -692192937932555368L;private long id;private String username;private Date creationDate;//getter/setter@Overridepublic String toString() {return "EUser [id=" + id + ", username=" + username + ", creationDate=" + creationDate + "]";}}
其中 DateStringConverter 类的源码如下所示。
public class DateStringConverter implements Converter {@SuppressWarnings("unchecked")@Overridepublic <T> T convert(Class<T> type, Object value) {if(type.equals(Date.class) && String.class.isInstance(value)) {return (T)DateUtils.convert((String)value);} else if(type.equals(String.class) && Date.class.isInstance(value)){return (T)DateUtils.format((Date)value);} else {return (T)value;}}}
getProperty()
,返回 bean 指定的属性值。
String fieldValue = BeanUtils.getProperty(value, fieldName);
setProperty()
,设置 bean 指定的属性值。
BeanUtils.setProperty(object, propertyName, value);
说实在的,没想到整理起来这么费事,不知不觉 5 个小时过去了。每个类都有很多方法,还要为每个方法敲一个 Demo,真的是很辛苦。但为了你们,再苦再累二哥也心甘情愿啊。
觉得有点用记得给我点赞哦!😎
简单介绍一下。10 年前,当我上大学的时候,专业被调剂到了计算机网络,主要学的是 Java 编程语言,但当时没怎么好好学,每年都要挂科两三门;因此工作后吃了不少亏。但是最近几年,情况发生了很大改变,你应该也能看得到我这种变化。通过坚持不懈地学习,持续不断地输出,我的编程基本功算得上是突飞猛进。
为了帮助更多的程序员,我创建了“沉默王二”这个 ID,专注于分享有趣的 Java 技术编程和有益的程序人生。一开始,阅读量寥寥无几,关注人数更是少得可怜。但随着影响力的逐步扩大,阅读量和关注人都在猛烈攀升。
你在看这篇文章的时候,应该也能发现,我在 CSDN 上的总排名已经来到了第 71 位,这个排名还是非常给力的。有很多读者都说,我可以冲击第一名,我不愿意藏着掖着,我是有这个野心的。
如果你也喜欢我的文章,请记得微信搜索「沉默王二」,回复“1024”更有美团技术大佬整理的 Java 面试攻略相送,还有架构师的面试视频哦。
绝对不容错过,期待与你的不期而遇。
如果觉得《作为一个Java程序员 这 8 个开源类库你必须知道!》对你有帮助,请点赞、收藏,并留下你的观点哦!