所以,我有一个代表程序版本的文件夹列表,我想获得最新版本(文件夹旁边有一些垃圾文件!):
0.0.0.256
0.0.1.1
0.0.1.2
0.0.1.5
0.0.1.11
0.0.1.68
0.0.2.1
等等。
如果我想在这里只获得最新的版本文件夹,我怎么能实现呢?
目前,我知道现在的版本不会高于0.0.1.x,(以上只是一个例子)所以我可以使用
for(String name:names)
{
if (name.indexOf("0.0.1")==0)
{
ret = name;
}
}
System.out.println("Current Installed Version Folder: "+ret);
但这不会永远持续下去。我怎么能写一些代码,总会给我最高代表性的版本号?我现在可以想办法如何做到这一点(检查第0个字符,然后是第2个,第4个等等),但我认为有一个更聪明的方法。有什么快速的想法吗?
答案 0 :(得分:2)
想法是使用比较器来比较每个String(我删除了使用Set的部分):
public static void main(String [] args){
String [] names = { "0.0.1.1",
"1.0.1.1",
"0.0.1.2",
"0.0.1.5",
"0.0.1.11",
"0.0.0.100",
"0.0.0.256",
"0.0.2.1",
"0.0.1.68"};
String maxVersion = names[0];
for(int i = 1; i < names.length; i++){
if(compare(maxVersion, names[i]) == 1)
maxVersion = names[i];
}
System.out.print(maxVersion);
}
static int compare(String a, String b){
String[] sA = a.split("\\.");
String[] sB = b.split("\\.");
for(int i = 0; i < sA.length; i++){
int cmp = Integer.compare(Integer.parseInt(sB[i]), Integer.parseInt(sA[i]));
if(cmp != 0)
return cmp;
}
return 0;
}
哪个输出:
"1.0.1.1"
请注意,这假设每个版本号具有相同的长度,但您可以通过在拆分时检查结果数组的长度来更改此值。
我遇到了另一个问题:我在版本文件夹旁边找到了一些文件, 所以我无法从File.list()
获取名称列表
您可以使用FileNameFilter
方法提供listFiles
:
File file = new File("/pathToVersionFolders");
File[] files = file.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return new File(dir, name).isDirectory();
}
});
现在你只有目录了。如果您只想获取名称,可以使用list
。
答案 1 :(得分:2)
如果要使用Java 8 Stream API,则必须编写一个自定义比较器。
List<String> sortedVersions = versions.stream().sorted((o1, o2) -> {
String[] o1Split = o1.split("\\.");
String[] o2Split = o2.split("\\.");
int i = 0;
while (i++ < Math.min(o2Split.length, o1Split.length)) {
int o1IntValue = Integer.parseInt(o1Split[i - 1]);
int o2IntValue = Integer.parseInt(o2Split[i - 1]);
if (o1IntValue != o2IntValue) {
return o1IntValue - o2IntValue;
}
}
return 0;
}).collect(Collectors.toList());
String highestVersion = sortedVersions.get(sortedVersions.size() - 1);
System.out.println(highestVersion);
答案 2 :(得分:1)
目前接受的答案假设您总是拥有完全相同的编号方案,这在您的情况下可能是正确的。 &#34;垃圾文件&#34;您之前提到过的内容会被使用isDirectory()
过滤器过滤掉,但是如果您有一些垃圾目录呢?
更通用的解决方案不关心确切的版本控制方案,而是将输入文件名拆分为一组数字/非数字段,然后通过匹配段号来对文件进行排序(如果两者都是数字,则按字母顺序排列数字,字母数字除此以外)。 I've blogged about this approach here。 The idea was inspired by this answer here。比较器可能如下所示:
public final class FilenameComparator implements Comparator<String> {
private static final Pattern NUMBERS =
Pattern.compile("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)");
@Override public final int compare(String o1, String o2) {
// Optional "NULLS LAST" semantics:
if (o1 == null || o2 == null)
return o1 == null ? o2 == null ? 0 : -1 : 1;
// Splitting both input strings by the above patterns
String[] split1 = NUMBERS.split(o1);
String[] split2 = NUMBERS.split(o2);
for (int i = 0; i < Math.min(split1.length, split2.length); i++) {
char c1 = split1[i].charAt(0);
char c2 = split2[i].charAt(0);
int cmp = 0;
// If both segments start with a digit, sort them numerically using
// BigInteger to stay safe
if (c1 >= '0' && c1 <= '9' && c2 >= 0 && c2 <= '9')
cmp = new BigInteger(split1[i]).compareTo(new BigInteger(split2[i]));
// If we haven't sorted numerically before, or if numeric sorting yielded
// equality (e.g 007 and 7) then sort lexicographically
if (cmp == 0)
cmp = split1[i].compareTo(split2[i]);
// Abort once some prefix has unequal ordering
if (cmp != 0)
return cmp;
}
// If we reach this, then both strings have equally ordered prefixes, but
// maybe one string is longer than the other (i.e. has more segments)
return split1.length - split2.length;
}
}
答案 3 :(得分:0)
有很多解决方案。例如
.
这是一种伪代码。
long version = 0;
String[] parts = versionSpec.split("\\.");
for (String part : parts) {
int n = part.length;
version = version * n + Integer.parseInt(part);
}
//此时您有版本的数字表示。
现在您可以根据需要比较版本。例如,您可以实现自己的Comparator
。
编辑:解决方案已修复。现在n
是动态计算的。
答案 4 :(得分:0)
由于版本号始终具有此结构[0-9]+(\.[0-9]+)*
,因此您可以扫描目录以查找适合此模式的文件夹名称。
一旦获得版本目录列表,就可以将它们拆分为单独的数字(拆分为“。”字符),然后在从左到右的列上对它们进行排序。
答案 5 :(得分:0)
这对我有用,但根据程序版本的更新方式,可能对其他人不起作用。
我使用Files的lastModified
属性来确定哪个版本目录是最新修改的。在我的例子中,最近修改的文件夹也是该程序的最新/最高版本。它为我节省了很多字符串解析。
使用directory.listFiles()
获取该目录中所有文件夹的数组,然后将其传递给此方法以获取最后修改过的文件夹数组中的索引。 fileList [index]将成为程序的最新版本文件夹。
/**
* Determine the index in an array of files[] of the most recently modified file
* by comparing the lastModified property from all files in the array.
*
* @param fileList Array of files from a desired directory
* @return Integer index of most recently modified file/directory.
* Returns -1 if the File[] array is null.
*/
public static int getLatestModified(File[] fileList){
if(fileList!= null){
long latestVersion = 0;
int index = 0;
for(int i = 0; i < fileList.length; i++){
File currentDir = fileList[i];
if(currentDir.lastModified() > latestVersion){
latestVersion = currentDir.lastModified();
index = i;
}
}
return index;
}else{
System.out.println("Error: fileList is null.");
return -1;
}
}
编辑:如果文件和文件夹位于版本的同一目录中,则可以添加带有isDirectory
的if语句,以仅从文件夹中获取lastModified属性。
答案 6 :(得分:-1)
使用Java 8,您可以使用流和自然顺序比较器。 例如:
List<String> versions = Arrays.asList(
"0.0.1.1",
"1.0.1.1",
"0.2.1.11",
"0.0.1.2",
"0.0.1.5",
"0.1.11",
"0.1.1.11",
"0.0.0.100",
"0.0.0.256",
"2.0.0.256",
"1.0.0.256",
"0.0.2.1",
"0.0.1.68");
String highest = versions.stream()
.sorted(Comparator.naturalOrder())
.collect(Collectors.toList())
.get(versions.size() - 1);
System.out.println(highest);