我有一个按照字母顺序排序的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
================================
非常感谢任何帮助。
答案 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));
}
}