我正在寻找shell命令的纯java替代方法:sort -V
。我正在寻找一个可以简单插入的Comparator类。
sort -V
命令只是使用版本系统对文件进行排序(即3.2.0-11
比3.2.0-1
大10,而不是.1更大。“
提前致谢!
答案 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;考虑一个单独的比较器,当插入任何自尊的有序数据结构时,它们应自动排序。