JAVA8:找到文件名中包含最新日期的文件

时间:2017-09-18 13:51:48

标签: java collections java-8

我在FTP文件夹中的文件很少,其名称如下:

  

mainimport_31052017.csv
  mainimport_21052017.csv
  mainimport_15052017.csv

我有一个模式字符串:

  

String pattern =" mainimport_ddmmyyy";

现在我应该下载标题中包含最新日期的文件。我应该用Java 8好东西来做。

我有一个解决方案,但这还不够,我在2个语句中这样做:

1)我首先得到最新的日期:

Date newestDate = Collections.max(ftpFiles.stream().filter(fileName -> StringUtils.startsWith(fileName.getName(), prefix)).map(fileName -> {
    String fileNameSuffix = fileName.getName().split("_")[1];
    Date date = null;
    try {
        date = dateFormat.parse(fileNameSuffix);
    } catch (ParseException e) {
        e.printStackTrace();
    }

    return date;
}).collect(Collectors.toList()));

2)然后我获取最新日期的文件名:

Optional<FTPFile> file = ftpFiles.stream().filter(fileName->{
    String fileNameSuffix = fileName.getName().split("_")[1];
    Date date = null;
    try {
        date = dateFormat.parse(fileNameSuffix);
    } catch (ParseException e) {
        e.printStackTrace();
    }
    return StringUtils.startsWith(fileName.getName(), prefix) && date.equals(newestDate);

}).findFirst();

如果有可能的话,我试图在一个声明中做到这一点。

1 个答案:

答案 0 :(得分:4)

假设日期始终具有指定的六个字符表示,您可以使用

Optional<FTPFile> max = ftpFiles.stream()
    .filter(file -> file.getName().startsWith(prefix))
    .max(Comparator.comparing(file -> file.getName()
           .replaceFirst(".*_([0-9]{2})([0-9]{2})([0-9]{4}).*", "$3$2$1")));

工厂方法Comparator.comparing允许您基于属性创建Comparator,以便最大元素将是具有该属性的最大值的元素。

请注意,这只是将ddmmyyyy格式化的日期转换为yyyymmdd字符串,可以按字典顺序进行比较,只要日期和月份总是有两位数的形式,即领先零。

您可以通过准备和重用正则表达式模式来优化这一点:

Pattern pattern = Pattern.compile(".*_([0-9]{2})([0-9]{2})([0-9]{4}).*");
Optional<FTPFile> max = ftpFiles.stream()
        .filter(file -> file.getName().startsWith(prefix))
        .max(Comparator.comparing(file ->
                pattern.matcher(file.getName()).replaceFirst("$3$2$1")));

如果DateFormat是不可避免的先决条件,您可以使用

Optional<FTPFile> max = ftpFiles.stream()
        .filter(file -> file.getName().startsWith(prefix))
        .max(Comparator.comparing(file -> {
                String name = file.getName();
                name = name.substring(name.indexOf('_')+1);
                try {
                    return dateFormat.parse(name);
                } catch (ParseException e) {
                    throw new IllegalArgumentException(e);
                }
            }));

这一次执行操作,但是缺点是在比较期间执行解析操作而不是必要的操作。如果你想避免这种情况,你可以采用原来的双通设计,但你仍然不需要收集到List

ftpFiles.stream()
        .map(FTPFile::getName)
        .filter(name -> name.startsWith(prefix))
        .map(name -> {
                name = name.substring(name.indexOf('_')+1);
                try {
                    return dateFormat.parse(name);
                } catch (ParseException e) {
                    throw new IllegalArgumentException(e);
                }
            })
        .max(Comparator.naturalOrder())
        .map(date -> prefix+'_'+dateFormat.format(date))
        .flatMap(fileName -> ftpFiles.stream()
                               .filter(file -> file.getName().equals(fileName)).findAny())
        .ifPresent(System.out::println);