Java 中的自然排序字符串比较 - 是内置的吗?
我想要某种保留自然排序顺序1的字符串比较函数。 Java 中是否内置了类似的东西? 我在 String 类,并且 Comparator 类 只知道两个实现。
我可以自己动手(这不是一个很难的问题),但如果不需要的话,我宁愿不重新发明轮子。
在我的具体情况下,我有想要排序的软件版本字符串。 因此,我希望“1.2.10.5”被视为大于“1.2.9.1”。
1 通过“自然”排序顺序,我的意思是它以人类比较字符串的方式比较字符串,与仅对程序员有意义的“ascii-betical”排序顺序相反。 换句话说,“image9.jpg”小于“image10.jpg”,“album1set2page9photo1.jpg”小于“album1set2page10photo5.jpg”,“1.2.9.1”小于“1.2.10.5”
I'd like some kind of string comparison function that preserves natural sort order1. Is there anything like this built into Java? I can't find anything in the String class, and the Comparator class only knows of two implementations.
I can roll my own (it's not a very hard problem), but I'd rather not re-invent the wheel if I don't have to.
In my specific case, I have software version strings that I want to sort. So I want "1.2.10.5" to be considered greater than "1.2.9.1".
1 By "natural" sort order, I mean it compares strings the way a human would compare them, as opposed to "ascii-betical" sort ordering that only makes sense to programmers. In other words, "image9.jpg" is less than "image10.jpg", and "album1set2page9photo1.jpg" is less than "album1set2page10photo5.jpg", and "1.2.9.1" is less than "1.2.10.5"
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
看看这个实现。 它应该尽可能快,没有任何正则表达式或数组操作或方法调用,只有几个标志和很多情况。
这应该对字符串内的数字的任意组合进行排序,并正确支持相等并继续前进的数字。
Have a look at this implementation. It should be as fast as possible, without any regular expressions or array manipulation or method calls, just a couple of flags and a lot of cases.
This should sort any combination of numbers inside strings and properly support numbers which are equal and move on.
在java中,“自然”顺序含义是“字典顺序”,因此核心中没有像您正在寻找的那样的实现。
有开源实现。
这是一个:
NaturalOrderComparator.java
请确保阅读:
Cougaar 开源许可证
我希望这会有所帮助!
In java the "natural" order meaning is "lexicographical" order, so there is no implementation in the core like the one you're looking for.
There are open source implementations.
Here's one:
NaturalOrderComparator.java
Make sure you read the:
Cougaar Open Source License
I hope this helps!
我测试了其他人在这里提到的三个 Java 实现,发现它们的工作方式略有不同,但没有像我预期的那样。
AlphaNumericStringComparator 和 AlphanumComparator 不会忽略空格,以便将
pic2
放置在pic 1
之前。另一方面 NaturalOrderComparator 不仅忽略空格,还忽略所有前导零,以便
sig[1]
位于sig[0]
之前。关于性能 AlphaNumericStringComparator 比其他两个慢约 x10。
I have tested three Java implementations mentioned here by others and found that their work slightly differently but none as I would expect.
Both AlphaNumericStringComparator and AlphanumComparator do not ignore whitespaces so that
pic2
is placed beforepic 1
.On the other hand NaturalOrderComparator ignores not only whitespaces but also all leading zeros so that
sig[1]
precedessig[0]
.Regarding performance AlphaNumericStringComparator is ~x10 slower then the other two.
String 实现了 Comparable,这就是 Java 中的自然排序(使用比较接口进行比较)。 您可以将字符串放入 TreeSet 中或使用 Collections 或 Arrays 类进行排序。
但是,在您的情况下,您不需要“自然排序”,您确实需要一个自定义比较器,然后您可以在 Collections.sort 方法或采用比较器的 Arrays.sort 方法中使用它。
就您正在寻找的比较器内实现的具体逻辑而言(用点分隔的数字),我不知道任何现有的标准实现,但正如您所说,这不是一个难题。
编辑:在您的评论中,您的链接可以让您这里,如果您不这样做,它会做得不错不要介意它区分大小写。 以下是修改后的代码,允许您传入
String.CASE_INSENSITIVE_ORDER
:String implements Comparable, and that is what natural ordering is in Java (comparing using the comparable interface). You can put the strings in a TreeSet or sort using the Collections or Arrays classes.
However, in your case you don't want "natural ordering" you really want a custom comparator, which you can then use in the Collections.sort method or the Arrays.sort method that takes a comparator.
In terms of the specific logic you are looking for implementing within the comparator, (numbers separated by dots) I'm not aware of any existing standard implementations of that, but as you said, it is not a hard problem.
EDIT: In your comment, your link gets you here, which does a decent job if you don't mind the fact that it is case sensitive. Here is that code modified to allow you to pass in the
String.CASE_INSENSITIVE_ORDER
:如何使用 String 中的 split() 方法,解析单个数字字符串,然后将它们一一比较?
我没有检查极端情况,但这应该可行,而且非常紧凑
How about using the split() method from String, parse the single numeric string and then compare them one by one?
I did not check the corner cases but that should work and it's quite compact
它连接数字,然后进行比较。 如果不适用,则继续。
}
It concats the digits, then compares it. And if it's not applicable it continues.
}
使用RuleBasedCollator 也可能是一种选择。 尽管您必须提前添加所有排序规则,因此如果您还想考虑更大的数字,那么这不是一个好的解决方案。
添加特定的自定义,例如
2 < 10
非常简单,并且对于排序特殊版本标识符(例如Trusty
Trusty
)可能很有用。 精确< 谢尼尔 烤鸭
。Using
RuleBasedCollator
might be an option as well. Though you'd have to add all the sort order rules in advance so it's not a good solution if you want to take larger numbers into account as well.Adding specific customizations such as
2 < 10
is quite easy though and might be useful for sorting special version identifiers likeTrusty < Precise < Xenial < Yakkety
.可能回复晚了。 但我的回答可以帮助其他需要这样的比较器的人。
我也验证了其他几个比较器。 但我的似乎比我比较的其他人更有效率。 还尝试了 Yishai 发布的那个。 对于 100 个条目的字母数字数据集的数据,我的时间仅为上述时间的一半。
Might be a late reply. But my answer can help someone else who needs a comparator like this.
I verified couple of other comparators too. But mine seems bit efficient than others I compared. Also tried the one that Yishai has posted. Mine is taking only half of the time as the mentioned one for data of alphanumeric data set of 100 entries.