有一个版本列表作为文件夹,想找到最高版本

时间:2014-01-27 15:08:32

标签: java sorting version directory

所以,我有一个代表程序版本的文件夹列表,我想获得最新版本(文件夹旁边有一些垃圾文件!):

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个等等),但我认为有一个更聪明的方法。有什么快速的想法吗?

7 个答案:

答案 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 hereThe 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)

有很多解决方案。例如

  1. 将您的字符串拆分为.
  2. 对结果数组进行迭代,并通过将当前数字添加到结果* 10,
  3. 来创建整数
  4. 比较结果数字
  5. 这是一种伪代码。

    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);