首页 > 其他分享 >jdk内置的一些工具类

jdk内置的一些工具类

时间:2024-03-03 15:23:39浏览次数:21  
标签:Files ... 内置 String jdk Objects path Path 工具

目录

java中一些工具类

一. java.util.Objects

1. 介绍

该类自jdk1.7引入, 此类包含用于对对象进行操作或在操作前检查某些条件的static实用程序方法.

例如: hashcode计算, 对象比较, 判空, toString, 索引范围检查等等.

相比于我们常见的使用表达式, 静态方法可以更好的配合函数式编程.

2. 方法

image-20220816233552558

Objects类中的方法都相当简单, openjdk17中总计代码行数未破500行(包括注释), 这些方法在空安全和索引检查方面非常实用, 特别是结合Stream使用时.

例如:

// 如果a为空, 会抛出空指针
if(a.equals(b)) {
	// ...  
}
// 可以替换成下面的代码
if(Objects.equals(a, b)) {
    // ...
}

// 可能导致NPE
int hashCode = o.hashCode();
// 空安全的hashCode
int hashCode = Objects.hashCode(o);

// 空安全的toString, 如果o为null, 会变成"null"字符串
String s = Objects.toString(o);
// 空安全的toString, 如果o为null, 会返回传入的字符串, 此处为空字符串.
String s = Objects.toString(o, "");

// 排序比较
String a = "Abc";
String b = "abD";
int compared = Objects.compare(a, b, String.CASE_INSENSITIVE_ORDER);

// 空断言, 为空直接报错
Objects.requireNonNull(obj);
// 可修改为空的报错消息
Objects.requireNonNull(obj, "不能为空!");
// 为空则调用supplier获取错误消息, 常用于错误消息较长需要拼接等情况.
Objects.requireNonNull(obj, () -> "不能为空!");
// 为空则使用给定的默认值, 如果默认也为空则报错
var nonNullObj = Objects.requireNonNullElse(obj, defaultObj);
// 为空则调用supplier获取默认值
var nonNullObj = Objects.requireNonNullElse(obj, () -> { .... return defaultObj; });

// 便于函数式编程的空检查
boolean isNull = Objects.isNull(obj);
boolean nonNull = Objects.nonNull(obj);
list.stream().map(...).filter(Objects::nonNull).collect(....);

// 索引范围检查
Objects.checkIndex(index, length);
Objects.checkFromIndexSize(fromIndex, size, length);
Objects.checkFromToIndex(fromIndex, toIndex, length);

二. java.util.Collections

1. 介绍

集合操作的工具类, Collection, Map, Enumeration 等接口类型的工具类.

2. 方法

image-20240302195105901

内部方法主要有:

  • empty开头的用于创建各种空集合的方法. jdk9以后可以用各种接口类型的空参 of 静态方法创建.

  • checked开头的返回动态类型安全的集合视图的方法.

  • synchronized开头的获取同步集合视图的方法.

  • unmodifiable开头的获取不可变集合视图的方法, jdk10以后可以用List.copyOf.

  • singleton 开头创建单个元素的集合的方法, jdk9以后可以用List.of, Set.of, Map.of 等替换.

其它方法也都是顾名思义.

  • 二分查找: binarySearch
  • 交换: swap
  • 排序: sort
  • 随机打乱: shuffle
  • 旋转(末尾元素移到最前, 前面元素后移): rotate
  • 频率计数(指定元素出现多少次): frequency
  • 无交集判断: disjoint
  • 以一个元素的多次重复创建列表: nCopies
  • 子列表查找: indexOfSubList, lastIndexOfSubList
  • 替换: replaceAll, copy, fill
  • 添加: addAll
  • 反转: reverse
  • 获取反转的Comparator: reverseOrder

使用需要注意的细节:

  1. singleton, empty, unmodifiable, nCopies 方法所创建的集合视图是不可变的.

  2. copy 其实是替换目标列表中的元素为源列表中的元素, 当目标列表的size小于源列表会索引越界.

    var dest = new ArrayList<String>();
    // IndexOutOfBoundsException: Source does not fit in dest
    Collections.copy(dest, List.of("abc"));
    
  3. fill 同样是替换, 将列表中的元素全部替换为指定元素.

    var dest = new ArrayList<String>();
    Collections.fill(dest, "haha");
    System.out.println(dest); // 输出[]
    dest.add("abc");
    Collections.fill(dest, "haha"); // 输出[haha]
    

三. java.nio.file.Files

1. 介绍

java.nio.file.Files类是java1.7引入的一个用于简化一些常用IO操作的工具类.

Files 类中的方法没有使用 File 作为参数, 而是使用 Path 类作为参数. Path 是文件系统路径的抽象.

任何与文件相关的操作, 首先都可以考虑 Files 类中是否已经存在.

2. 方法

image-20240302204231280

2.1. 复制

将输入复制到输出目标, 当输出目标是 Path 时, 可以指定 CopyOption.

CopyOption 一般实现是 StandardCopyOption 枚举类.

  • copy(InputStream, Path, CopyOption...)
  • copy(Path, OutputStream)
  • copy(Path, Path, CopyOption...)

2.2. 创建

create 开头的方法, 可以创建文件夹, 文件, 临时文件夹, 临时文件, 链接.

// 创建文件夹
Files.createDirectory(dirPath);
// 创建文件
Files.createFile(filePath);
// 创建链接
Files.createLink(linkPath);
// 创建符号链接
Files.createSymbolicLink(symbolicPath);
// 在系统的临时文件夹创建临时文件夹
Files.createTempFile(tempFilePrefix, tempFileSufix);
// 在指定文件夹下创建临时文件
Path dirPath = ...
Files.createTempFile(dirPath, tempFilePrefix, tempFileSufix);
// 在系统的临时目录创建临时文件夹
Files.createTempDirectory(tempDirPrefix);
// 在指定文件夹下创建临时文件夹
Files.createTempDirectory(dirPath, tempDirPrefix);

2.3. 删除

delete开头的方法, 可以删除文件和空文件夹, 但是不能删除有文件的文件夹.

如果要递归地删除文件夹和文件, 需要配合walkFileTree:

// 删除
Files.delete(filePath);
// 递归删除
Files.walkFileTree(
    Path.of("./dirToRemove"),
    new SimpleFileVisitor<Path>() {
      @Override
      public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
          throws IOException {
        Files.delete(file);
        return FileVisitResult.CONTINUE;
      }

      @Override
      public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
        Files.delete(dir);
        return FileVisitResult.CONTINUE;
      }
    });

2.4. 判断文件是否存在

exists, notExists, 字面理解即可.

2.4. 查找文件

find 递归地查找文件, 可以指定深度和查找条件, 可以通过FileVisitOption选择关闭跟随符号引用.

需要注意流的关闭.

try (Stream<Path> pathStream =
    Files.find(
        Path.of("./dir"),
        Integer.MAX_VALUE,
        (path, attrs) -> !Files.isDirectory(path) && path.endsWith(".java"))) {
  pathStream.forEach(System.out::println);
}

2.5. 获取, 检查文件的属性或状态

getis 开头的各种方法.

size 可以获取文件的大小.

2.6. 直接将一个字符文件按行读入

lines 方法, 返回 Straem<String>, 比较简单的按行读入的方法.

Stream<String> lines = Files.lines(path);
lines.map(..).forEach(...);

2.7. 返回两个文件第一个不匹配的字节的位置

mismatch.

对于文件 f, mismatch(f,f) 始终返回 -1.

对于文件 fg, mismatch(f,g)mismatch(g,f) 相同.

2.8. 移动(重命名)文件

move.

示例:

// 重命名
Path source = ...
Files.move(source, source.resolveSibling("newname"));
// 移动并替换已存在文件
Path source = ...
Path newdir = ...
Files.move(source, newdir.resolve(source.getFileName()), REPLACE_EXISTING);

2.9. 新建输入和输出

new 开头的各种方法. 可以创建 BufferedReader, BufferedWriter, InputStream, OutputStream, ByteChannel.

newDirectoryStream用于创建可以遍历文件夹的 DirectoryStream.

示例:

// 遍历特定后缀的文件
List<Path> listSourceFiles(Path dir) throws IOException {
    List<Path> result = new ArrayList<>();
    try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir, "*.{c,h,cpp,hpp,java}")) {
        for (Path entry: stream) {
            result.add(entry);
        }
    } catch (DirectoryIteratorException ex) {
        // I/O error encountered during the iteration, the cause is an IOException
        throw ex.getCause();
    }
    return result;
}
// 遍历自定义条件的文件
Path dir = ...
try (var stream =
        Files.newDirectoryStream(dir, path -> Files.size(path) > 1000L)) {
    
}

2.10. 探测文件类型

probeContentType. 返回的是MIME字符串, 例如: image/jpg, text/plain 等等, 无法探测到结果时返回null.

依赖平台特定实现.

2.11. 读取文件内容, 属性, 链接

read.

// 读取所有字节
byte[] bytes = Files.readAllBytes(Path.of("./file.txt"));
// 读取所有行
List<String> lines = Files.readAllLines(Path.of("./file.txt"));
// 指定编码
List<String> lines = Files.readAllLines(Path.of("./file.txt"), StandardCharsets.UTF_8);
// 读取文件属性
Path path = ...
BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);
Map<String,Object> attrMap = Files.readAttributes(path, "*");
// 以字符串读入
String content = Files.readString(path);
// 指定编码
String content = Files.readString(path, StandardCharsets.UTF_8);
// 读取符号链接
Path path = Files.readSymbolicLink(path);

2.12. 设置文件属性, 修改时间, 所有者, 权限等.

set.

Path path = ...
// 设置dos的hidden属性
Files.setAttribute(path, "dos:hidden", true);
// 设置最后修改时间
FileTime now = FileTime.fromMillis(System.currentTimeMillis());
Files.setLastModifiedTime(path, now);
// 设置owner
UserPrincipalLookupService lookupService =
  provider(path).getUserPrincipalLookupService();
UserPrincipal joe = lookupService.lookupPrincipalByName("joe");
Files.setOwner(path, joe);
// 设置Posix的文件权限 (static import PosixFilePermission.*)
Files.setPosixFilePermissions(path, EnumSet.of(OWNER_READ, OWNER_WRITE, GROUP_READ));

2.13. 遍历文件树

walk.

walk 方法与 walkFileTree 不同, walk 直接返回 Stream<Path>, 而 walkFileTree 通过回调设置如何处理文件.

walk 方法返回的Stream<Path> 建议配合 try-with-resource 或类似机制确保流关闭, 如果流不关闭对目录的访问也不会关闭.

// 遍历输出所有文件的文件名
try (Stream<Path> paths = Files.walk(Path.of("./dir"))) {
  paths.filter(Files::isRegularFile)
      .map(Path::getFileName)
      .map(Path::toString)
      .forEach(System.out::println);
}
// 遍历深度两层
try (Stream<Path> paths = Files.walk(Path.of("./dir"), 2)) {
  paths.filter(Files::isRegularFile)
      .map(Path::getFileName)
      .map(Path::toString)
      .forEach(System.out::println);
}

// 递归删除文件和文件夹
Path start = ...
Files.walkFileTree(start, new SimpleFileVisitor<Path>() {
  @Override
  public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
      throws IOException
  {
      Files.delete(file);
      return FileVisitResult.CONTINUE;
  }
  @Override
  public FileVisitResult postVisitDirectory(Path dir, IOException e)
      throws IOException
  {
      if (e == null) {
          Files.delete(dir);
          return FileVisitResult.CONTINUE;
      } else {
          // directory iteration failed
          throw e;
      }
  }
});

// 递归复制文件夹和文件
final Path source = ...
final Path target = ...

Files.walkFileTree(source, EnumSet.of(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE,
  new SimpleFileVisitor<Path>() {
      @Override
      public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
          throws IOException
      {
          Path targetdir = target.resolve(source.relativize(dir));
          try {
              Files.copy(dir, targetdir);
          } catch (FileAlreadyExistsException e) {
               if (!Files.isDirectory(targetdir))
                   throw e;
          }
          return CONTINUE;
      }
      @Override
      public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
          throws IOException
      {
          Files.copy(file, target.resolve(source.relativize(file)));
          return CONTINUE;
      }
  });

2.14. 写文件

write. 可以通过参数的 OpenOption 设置写文件的选项, 一般实现是StandardOpenOption

Path path = Path.of("./file.txt");
// 写字节
Files.write(path, bytes);
// 写字符串
Files.writeString(path, "hello");
// 写多个字符串
Files.write(path, List.of("hello", " ", "world"));
// Append模式
Files.writeString(path, StandardOpenOption.APPEND);
// 设置编码
Files.writeString(path, "你好!", StandardCharsets.UTF_8);

四. java.util.Comparator

Comparator 类本身较少直接使用, 一般配合集合进行排序时用到, 或者在某些sorted集合中使用.

Comparator 本身提供了一些非常有用的函数式编程的组合方法, 可以非常方便的创建需要的 Comparator.

静态方法 comparing 可以从一个 Function 创建Comparator.

其本质是通过 Function 从要比较的对象上获取数据, 然后再进行比较.

thenComparing 可以组合Comparator, 实现多重排序.

image-20240303123838110

示例:

// 指定按照长度排序 (基础类型使用对应的comparing和thenComparing方法)
List<String> strings = ....	
strings.sort(Comparator.comparingInt(String::length));
// 忽略大小写排序
strings.sort(String.CASE_INSENSITIVE_ORDER);
// 按长度排序并忽略大小写
strings.sort(Comparator.comparingInt(String::length).thenComparing(String.CASE_INSENSITIVE_ORDER));
// 按长度排序并忽略大小写(另一种方式, 但会有装箱拆箱)
strings.sort(Comparator.comparing(String::length, String.CASE_INSENSITIVE_ORDER));
// 反序排序
strings.sort(Comparator.reverseOrder());
// 忽略大小写反序排序
strings.sort(String.CASE_INSENSITIVE_ORDER.reversed());
// 按年龄再按身高排序 (对于基础类型的比较, 有提供相应的方法, 可以减少泛型带来的装箱拆箱)
List<User> users = ...
users.sort(Comparator.comparingInt(User::age).thenComparingInt(User::height));
// 以email地址排序, null优先
List<User> users = ...
users.sort(Comparator.nullsFirst(Comparator.comparing(User::email)));

值得注意的细节:

  • 如果用于比较的字段有可能为空, 必须使用 nullsFirstnullsLastnull 进行处理. 否则可能出现空指针.
  • 如果用于比较的字段是基础类型, 优先使用对应的 comparingthenComparing 方法, 避免拆箱装箱.

五. 其它

java.util.Base64

提供Base64的编解码.

var encoded = Base64.getEncoder().encodeToString("hello".getBytes());
System.out.println(encoded);
System.out.println(new String(Base64.getDecoder().decode(encoded)));

java.uitl.HexFormat

jdk17及以上可用.

提供格式化16进制字符串的方法.

示例:

var bytes = new byte[]{ (byte) 0xAB, (byte) 0xCD, (byte) 0xEF };
System.out.println(HexFormat.of().formatHex(bytes)); // abcdef
System.out.println(HexFormat.of().withUpperCase().formatHex(bytes)); // ABCDEF
System.out.println(HexFormat.ofDelimiter(":").withUpperCase().formatHex(bytes)); // AB:CD:EF

java.util.StringJoiner

将序列以分隔符拼接起来, 可以设置前后缀.

示例:

StringJoiner sj = new StringJoiner(":", "[", "]");  
sj.add("George").add("Sally").add("Fred");  
String desiredString = sj.toString();

Collectors.joining 实际上就是使用了该类实现.

对于集合和数组, String类提供了不含前后缀的拼接方法: String.join.

标签:Files,...,内置,String,jdk,Objects,path,Path,工具
From: https://www.cnblogs.com/wymc/p/18050074

相关文章

  • 网页浏览器Chrome开发者调试工具-Source(源码)-断点调试、条件断点、日志断点
    前言全局说明网页浏览器Chrome开发者调试工具-Source(源码)-断点调试、条件断点、日志断点断点,是某行代码要执行,还没有执行的一个暂停点一、截图对照1.1Chrome浏览器1.1.1蓝色,普通断点1.1.2设置断点类型图中分别是:backpoint:普通断点(蓝色)Conditionalbreakp......
  • unhide 是一款强大的取证工具,主要用于查找和发现被隐藏的进程、TCP/UDP端口以及其他隐
    unhide是一款强大的取证工具,主要用于查找和发现被隐藏的进程、TCP/UDP端口以及其他隐藏技术。其基本技术原理如下:ROOTKIT和LKM:ROOTKIT(RootKit)是一种恶意软件,常用于隐藏恶意活动和进程。它通过修改操作系统的核心组件和内核模块(LinuxKernelModule,LKM)来实现对系统的隐匿。u......
  • .NET开源功能强大的串口调试工具
    前言今天大姚给大家分享一款.NET开源的、功能强大的串口调试工具:LLCOM。工具介绍LLCOM是一个.NET开源的、功能强大的串口调试工具。支持Lua自动化处理、串口调试、串口监听、串口曲线、TCP测试、MQTT测试、编码转换、乱码恢复等功能。功能列表收发日志清晰明了,可同时显示HEX......
  • vs工具dumpbin查看依赖的lib、dll
    转载:https://blog.csdn.net/weixin_34910922/article/details/109320939?spm=1001.2101.3001.6650.11&utm_medium=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~Rate-11-109320939-blog-104154281.pc_relevant_aa&depth_1-utm_source=distribute.pc_relev......
  • 无法创建spring2.X版本,无法使用JDK8, 用idea创建spring2.X版本,使用JDK8解决方案
    1、解释原因spring2.X版本在2023年11月24日停止维护了,因此创建spring项目时不再有2.X版本的选项,只能从3.1.X版本开始选择而Spring3.X版本不支持JDK8,最低支持JDK17,因此JDK8也无法主动选择了当然,停止维护只代表我们无法用idea主动创建spring2.X版本的项目了,不代表我们无法使用,该......
  • 一文掌握人才盘点工具
    很多人认为人才盘点是HR的事情,作为项目经理和PMO基本上没有操心过?但是真正用人的人是你,为公司拿结果的人也是你,但是你从来没有盘点过有多少人,什么样的人可用?这些人的能力如何?潜力如何?所有项目最终都是通过人来完成的,不懂得盘点和发挥人才的价值,为你优秀的项目成员争取机会,把你项......
  • redis 工具类
    一、Redis工具类一、RedisUtil​直接用RedisTemplate操作Redis,需要很多行代码,因此直接封装好一个RedisUtils,这样写代码更方便点。这个RedisUtils交给Spring容器实例化,使用时直接注解注入。packagecom.jin.util;importjava.util.List;importjava.util.Map;importjava.......
  • 如何用压缩工具对指定文件进行备份保存
    使用场景:当你的程序文件需要每日自动备份时 脚本文件:新建记事本文件,重命名为bak.bat@echooff::设置7z的命令行程序路径setzip7=D:\\7-Zip\\7z.exe::设置压缩包保存路径setSave=E:\\datebak::当天日期,备份文件名setcurdate=%date:~0,4%-%date:~5,2%-%date:~8,2%::......
  • PS 第四节 钢笔工具
    PS第四节钢笔工具......
  • PS 第五节 形状工具 + 图层样式
    PS第五节形状工具+图层样式......