'sort -V'的Java替代方案

时间:2012-02-16 19:09:37

标签: java shell sorting comparator

我正在寻找shell命令的纯java替代方法:sort -V。我正在寻找一个可以简单插入的Comparator类。 sort -V命令只是使用版本系统对文件进行排序(即3.2.0-113.2.0-1大10,而不是.1更大。“

提前致谢!

2 个答案:

答案 0 :(得分:1)

我曾经写过一个通用的“像人类”比较器。我没有代码可以显示,但想法是分割每个字符串:

fragments = empty string collection
buffer = first character of the string
if character is digit, mode = NUMBER, else mode = TEXT
while there are characters left
   c = next character
   if c is digit and mode is NUMBER, add character to buffer
   else if c is not a digit and mode is TEXT, add character to buffer
   else
     add contents of buffer (as string) to the fragments collection,
     flip mode from TEXT to NUMBER or vice versa
     buffer = c
   end if
end while
add remaining contents of buffer to fragments

所以现在你有一个子串列表,包含交替的数字片段和非数字片段。 (例如something-1.0.26.jar将成为{ 'something-', '1', '.', '0', '.', '26', '.jar' }

如果对两个字符串执行此操作,则可以编写比较器,逐个比较对片段:如果两者都是数字,则进行数字比较,如果两者都是文本,则进行字符串比较,如果一个是数字,则另一个是文本,数字排在第一位。

我知道这比你想要的要多得多,但它在很多情况下都是非常有用的代码。

答案 1 :(得分:0)

初​​级:

如果您的版本字符串已明确定义,则可以将其拆分为不同的数字并直接进行比较。

3.2.0-11变为4整数,3,2,0和11而3.2.0-1变为3,2,0和1。

假设你把它们变成数组你比较src [3]< dest [3],src [2]< dest [2],...在你的比较器中,你就完成了。

使用String.split(" .-")然后在结果数组中的每个条目上调用Integer.getInteger(src [n]),可以轻松完成此操作。

高级:

现在,如果你想要"高级"这个版本我可以给你一个小技巧。如果你把你的价值观合并为一个长期 - 就像这样:

long l=src[3] << (16 * 3) + src[2] << (16 * 2) + src[1] << (16 * 1) + src[0];

这会将所有单个字段组合成一个可以比较的长字段。 (它需要一点点铸造而且第一个字段不能超过版本#32767,所有其他字段都可以转到65535)

如果您确定这些数字都不会超过255,那么您甚至可以移动8的倍数而不是16,并将它们打包成一个int(或一个可以处理最多7个字段的版本号的long--或者只要第一个没有超过127)

这项技术的一个很好的部分是,你将它从4比较下降到1并且你只携带一个值。

专家:

&#34;专家&#34;顺便说一句,版本是将所有这些包装在一个类中,这样你就不必关心它是如何实现的。带有这样界面的东西:

class VersionNo implements Comparable {
    public VersionNo(String version, File originalFileObject);
    public int compareTo(VersionNo target);
    public String toString();
    public File getOriginalFileObject();
}

现在,您可以随时更改您的实施,而不会影响您的计划中的任何其他内容 - 您甚至不需要&#34;需要&#34;考虑一个单独的比较器,当插入任何自尊的有序数据结构时,它们应自动排序。