Java 的“sort -V”替代方案
我正在寻找 shell 命令的纯 java 替代方案:sort -V
。我正在寻找一个可以简单插入的比较器类。 sort -V
命令只是使用版本系统对文件进行排序(即 3.2.0-11
比 3.2.0-1
大 10,不是 0.1 大)。
提前致谢!
I'm looking for a pure-java alternative for the shell command: sort -V
. I'm looking for a Comparator class that can simply be plugged in.
The sort -V
command simply sorts files with a version system (i.e. 3.2.0-11
is 10 bigger than 3.2.0-1
, not .1 bigger).
Thanks in advance!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我曾经写过一个通用的“像人类一样”的比较器。我没有代码可以显示,但想法是像这样分割每个字符串:
所以现在你有了一个子字符串列表,其中包含交替的数字片段和非数字片段。 (例如
something-1.0.26.jar
将变为{ 'something-', '1', '.', '0', '.', '26', '.jar ' }
)如果对两个字符串都执行此操作,则可以编写一个比较器来逐一比较这对片段:如果两者都是数字,则进行数值比较,如果两者都是文本,则进行字符串比较,如果一个是数字,另一个是文本,数字优先。
我知道这比您想要的要多得多,但在许多情况下这是一段非常有用的代码。
I wrote a generic "like a human" comparator once. I've got no code to show but the idea was to split each string like this:
So now you've got a list of substrings, containing alternating number fragments and non-number fragments. (E.g.
something-1.0.26.jar
will become{ 'something-', '1', '.', '0', '.', '26', '.jar' }
)If you do this to both strings, you can then write a comparator that compares the pairs fragments one by one: if both are numbers, do a numerical comparison, if both are texts, string compare, if one is number, the other is text, number comes first.
I know this is a lot more than what you want but it is quite a useful piece of code to have in many situations.
初学者:
如果您的版本字符串定义明确,那么您可以将其拆分为不同的数字并直接进行比较。
3.2.0-11 变为 4 个整数,3、2、0 和 11,而 3.2.0-1 变为 3、2、0 和 1。
假设您将它们放入数组中,您将比较 src[3] <目标[3],源[2] < dest[2], ... 在你的比较器中,你就完成了。
在您的情况下,可以使用 String.split(".-") 轻松完成此操作,然后对结果数组中的每个条目调用 Integer.getInteger(src[n]) 。
高级:
现在,如果您想要“高级”版本,我可以向您展示一个小技巧。如果你将你的值组合成一个长整型,就像这样:
这会将所有单独的字段组合成一个可以比较的长整型。
(它需要一点转换,并且第一个字段不能超过版本 # 32767,所有其他字段都可以超过版本 # 32767)
如果您确定没有一个数字会超过 255,那么您甚至可以移动 8 的倍数而不是 16并将它们打包成一个 int (或者一个 long 类型,可以处理最多 7 个字段的版本号——或者 8 个字段,只要第一个字段不超过 127)
这个技术的优点是是你把它从 4 比较到 1 并且你只携带一个值。
专家:
顺便说一句,“专家”版本是将所有这些包装在一个类中,这样您就不必关心它是如何实现的。具有这样的接口的东西:
现在您可以随时更改您的实现,并且不会影响程序中的任何其他内容 - 您甚至“不需要”考虑单独的比较器,这些比较器在插入任何内容时应该自动排序自尊的有序数据结构。
Beginner:
If your version string is clearly defined then you can split it up into different numbers and compare them directly.
3.2.0-11 becomes 4 ints, 3, 2, 0 and 11 whereas 3.2.0-1 becomes 3, 2, 0 and 1.
Assuming you made them into arrays you compare src[3] < dest[3], src[2] < dest[2], ... inside your comparator and you are done.
This can be done easily in your case with String.split(".-") then calling Integer.getInteger(src[n]) on each entry in the resulting array.
Advanced:
Now, if you want the "Advanced" version of this I can show you a little trick. If you take your values and combine them into a single long--something like this:
This will combine all the individual fields into a single long that can be compared.
(it will need a little casting AND the first field cannot go over version # 32767, all the others can go to 65535)
If you are sure none of the numbers will go over 255 then you could even shift by multiples of 8 instead of 16 and pack them into an int (or a long that can handle a version number with up to 7 fields--or 8 as long as the first one doesn't go over 127)
The nice part of this technique is that you take it from 4 compares down to 1 and you are only carrying around a single value.
Expert:
The "Expert" version, by the way, is to wrap all this inside a class so that you really don't care how it's implemented. Something with an interface like this:
Now you can change your implementation any time you want and not effect anything else in your program--you don't even "Need" to consider a separate comparator, these should automatically sort themselves when inserted in any self-respecting ordered data structure.