在Java中使用Map中的最后一个类似项目

时间:2017-01-31 22:53:03

标签: java sorting treemap

我有一个按照字母顺序排序的Map,使用TreeMap进行转换。 例如,Map包含String(安装程序文件名)和Path(文件系统上的安装程序路径) 地图安装程序;

我需要获取最新的安装程序文件名。但是,正则表达式似乎太复杂了。

我目前显示安装程序及其路径的代码是:

 Map<String, Path> installers = findInstallers();
    Set s = installers.entrySet();
    Iterator it = s.iterator();
    while(it.hasNext()) {
        Map.Entry entry = (Map.Entry) it.next();
        String installerFile = (String) entry.getKey();
        Path installerPath = (Path) entry.getValue();
        System.out.println(installerFile + " ==> " + installerPath.toString());
    }
    System.out.println("================================");

private Map<String, Path> findInstallers() {

    HashMap<String, Path>  installerPathMap = new HashMap<>();
    try {
        Path productReleasePath = Paths.get("C:", "test");
        List<Path> allPaths = Files.walk(productReleasePath)
                .filter(Files::isRegularFile)
                .collect(Collectors.toList());

        allPaths.forEach(path -> {
            if (!path.toFile().getName().toLowerCase().endsWith(".log")) {
                String installerFiileName = path.toFile().getName();
                installerPathMap.put(installerFiileName, path);
             }
        });

    } catch (IOException e) {
        e.printStackTrace();
    }

    return new TreeMap<>(installerPathMap);
}

这是一个示例输出:

Client_1.exe ==> C:\test\build_1\Win32\Client_1.exe
Client_5.exe ==> C:\test\build_5\Win32\Client_5.exe
Client_6.exe ==> C:\test\build_6\Win32\Client_6.exe
Server_1.exe ==> C:\test\build_1\Win64\Server_1.exe
Server_2.exe ==> C:\test\build_2\Win64\Server_2.exe
Server_Linux_1.tar.gz ==> C:\test\build_1\Linux32\Server_Linux_1.tar.gz
Server_Linux_2.tar.gz ==> C:\test\build_2\Linux32\Server_Linux_1.tar.gz
================================

我需要将Map缩短为仅包含最高键和它的值对,因此输出类似于:

Client_6.exe ==> C:\test\build_6\Win32\Client_6.exe
Server_2.exe ==> C:\test\build_2\Win64\Server_2.exe
Server_Linux_2.tar.gz ==> C:\test\build_2\Linux32\Server_Linux_1.tar.gz
================================

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

如果使用安装程序名称的根目录(即下划线之前的部分)将路径添加到地图,并在发生密钥冲突时丢弃最低版本,则可以获得所需内容。

请注意,按字母顺序排序名称将不起作用,因为版本9将在10之后排序,因此您必须提取版本并进行数字比较。

我不确定你的命名约定,但是如果我的假设不正确,下面例子中的辅助函数应该很容易修改。

public class InstallerList {

    public static void main(String[] args) throws IOException {
        Path productReleasePath = Paths.get("C:", "test");

        Collection<Path> installers = Files.walk(productReleasePath)
            .filter(Files::isRegularFile)
            .filter(p -> !p.getFileName().toString().endsWith(".log"))
            // Collect files with the highest version
            .collect(Collectors.toMap(
                // Key is installer name *without* version
                InstallerList::extractName,
                // Value mapper; identity mapping to the path
                p -> p,
                // Select newest version when there is a collision
                InstallerList::newer
            ))
            .values();

        for (Path path : installers) {
            System.out.println(path.getFileName() + " ==> " + path);
        }
    }

    // Extract the root name of an installer from a path (up to but not including the last '_')
    public static String extractName(Path path) {
        String fileName = path.getFileName().toString();
        int i = fileName.lastIndexOf('_');
        if (i < 0) {
            throw new IllegalArgumentException(fileName);
        }
        return fileName.substring(0, i);
    }

    // Return the path with the highest version number
    public static Path newer(Path p1, Path p2) {
        return extractVersion(p1) > extractVersion(p2) ? p1 : p2;
    }

    // Extract a version number from a path (number between the last '_' and the following '.')
    private static int extractVersion(Path path) {
        String fileName = path.getFileName().toString();
        int i = fileName.lastIndexOf('_');
        if (i < 0) {
            throw new IllegalArgumentException(fileName);
        }
        int j = fileName.indexOf('.', i);
        if (j < 0) {
            throw new IllegalArgumentException(fileName);
        }
        return Integer.parseInt(fileName.substring(i + 1, j));
    }
}