Java中按字符优先排序
我需要对列表进行排序,以便所有以char开头的字符串都先按以number开头的字符串升序排序。是否有任何内置算法可以做到这一点?如果没有,解决这个问题的最佳方法是什么Java中按字符优先排序,java,sorting,Java,Sorting,我需要对列表进行排序,以便所有以char开头的字符串都先按以number开头的字符串升序排序。是否有任何内置算法可以做到这一点?如果没有,解决这个问题的最佳方法是什么 Doctor Review 3rd Party Contact Appointment 24-Hour Service Doctor Preparation 到 我正在尝试编写自定义比较器,但不确定如何对以字符和数字开头的字符串进行分组。您可以定义自己的字符串(请参见下面代码中的myrules) 这种方法也适用于第一个位置之后的
Doctor Review
3rd Party Contact
Appointment
24-Hour Service
Doctor Preparation
到
我正在尝试编写自定义比较器,但不确定如何对以字符和数字开头的字符串进行分组。您可以定义自己的字符串(请参见下面代码中的myrules
)
这种方法也适用于第一个位置之后的数字
List<String> list = new ArrayList<String>();
list.add("Doctor Review");
list.add("Doctor Review A"); // check sort order of this entry!
list.add("Doctor Review 1"); // check sort order of this entry!
list.add("3rd Party Contact");
list.add("Appointment");
list.add("24-Hour Service");
list.add("Doctor Preparation");
String myrules = "< a, A < b, B < c, C < d, D < e, E < f, F < g, G < h, H < i, I" +
"< j, J < k, K < l, L < m, M < n, N < o, O < p, P < q, Q < r, R" +
"< s, S < t, T < u, U < v, V < w, W < x, X < y, Y < z, Z" +
"< 0 < 1 < 2 < 3 < 4 < 5 < 6 < 7 < 8 < 9";
try {
RuleBasedCollator myRuleBasedCollator = new RuleBasedCollator(myrules);
Collections.sort(list, myRuleBasedCollator);
for (String s : list) {
System.out.println(s);
}
} catch (ParseException e) {
e.printStackTrace();
}
正如您所猜测的,需要一个自定义的
比较器
现在,您将遇到的困难是使用ASCII集合之外的字符;特别是,由于Java在内部将文本数据存储为UTF-16代码单元,BMP之外的任何内容都将是两个字符
但让我们说,这不是一个问题,你唯一关心的是“古老的”阿拉伯数字,它恰好可以用一个字符表示
那么这就是如何编写这样一个比较器(未经测试!):
公共静态最终比较器阿拉伯数字最后比较器
=新的比较器()
{
@凌驾
公共整数比较(最终字符串o1,最终字符串o2)
{
返回doCompare(CharBuffer.wrap(o1),CharBuffer.wrap(o2));
}
专用int文件包(最终字符缓冲区buf1,最终字符缓冲区buf2)
{
//测试每个缓冲器的空度
final int r1=buf1.remaining();
最终整数r2=buf2.剩余();
如果(r1==0)
返回r2==0?0:-1;
如果(r2==0)
return 1;//我们知道r1在这里不是空的
//从两个缓冲区抓取第一个字符
final char c1=buf1.get();
final char c2=buf2.get();
//如果两个字符相同,我们必须继续
如果(c1==c2)
返回文件(buf1、buf2);
//它们不是…测试它们是否是数字
最终布尔值oneIsDigit=字符.isDigit(c1);
最终布尔值twoIsDigit=字符.isDigit(c2);
//两者都是数字:返回合同期望的内容
如果(一个数字和两个数字)
返回c1-c2;
//从这一点上,我们知道至少有一个字符是
//没有一个数字,而且它们都是不同的。
如果(oneIsDigit)
返回1;
if(twoIsDigit)
返回-1;
//两者都不是数字,但我们知道它们是不同的:
//只需退还差额
返回c1-c2;
}
}
}
这个怎么样
public class TryMe {
public static void main(String[] args) {
List<String> sortMe = new ArrayList<>();
sortMe.add("Doctor Review");
sortMe.add("3rd Party Contact");
sortMe.add("Appointment");
sortMe.add("24-Hour Service");
sortMe.add("Doctor Preparation");
Collections.sort(sortMe, new MyComparator());
System.out.println(sortMe);
}
private static class MyComparator implements Comparator<String> {
@Override
public int compare(String o1, String o2) {
if (Character.isDigit(o1.charAt(0))) {
if (Character.isDigit(o2.charAt(0))) {
//replace here with "return o1.compareTo(o2)" for original
int i1 = getFirstDigits(o1);
int i2 = getFirstDigits(o2);
if (i1 == i2) return o1.compareTo(o2);
return i1 - i2;
} else {
return 1;
}
}
if (Character.isDigit(o2.charAt(0))) return -1;
return o1.compareTo(o2);
}
}
private static int getFirstDigits(String from) {
int i = 0;
for (i = 0 ; i < from.length() ; i++) {
if (!Character.isDigit(from.charAt(i))) {
return Integer.parseInt(from.substring(0, i));
}
}
if (i > 0) return Integer.parseInt(from.substring(0, i));
throw new IllegalArgumentException("No digits to parse, should not happen");
}
}
公共类TryMe{
公共静态void main(字符串[]args){
List sortMe=new ArrayList();
增加(“医生回顾”);
排序添加(“第三方联系人”);
sortMe.添加(“任命”);
添加(“24小时服务”);
sortMe.添加(“医生制剂”);
Collections.sort(sortMe,newmycomparator());
System.out.println(sortMe);
}
私有静态类MyComparator实现Comparator{
@凌驾
公共整数比较(字符串o1、字符串o2){
if(Character.isDigit(o1.charAt(0))){
if(Character.isDigit(o2.charAt(0))){
//此处替换为“返回o1.比较(o2)”作为原始
int i1=getFirstDigits(o1);
int i2=获取第一个数字(o2);
如果(i1==i2)返回o1,与(o2)比较;
返回i1-i2;
}否则{
返回1;
}
}
if(Character.isDigit(o2.charAt(0)))返回-1;
返回o1。与(o2)相比;
}
}
私有静态int getFirstDigits(字符串来自){
int i=0;
对于(i=0;i0)返回Integer.parseInt(来自.substring(0,i));
抛出新的IllegalArgumentException(“没有要解析的数字,不应该发生”);
}
}
ArrayList list=new ArrayList();
列表。添加(“医生审查”);
列表。添加(“第三方联系人”);
列表。添加(“任命”);
列表。添加(“24小时服务”);
列表。添加(“医生制剂”);
ArrayList newlist=新的ArrayList();
集合。排序(列表);
for(字符串x:列表)
{
如果(!Character.isDigit(x.charAt(0))){
新增(x);
}
}
for(字符串x:列表)
{
if(Character.isDigit(x.charAt(0))){
新增(x);
}
}
解决方案,使用另一个列表 没有内置算法,没有,但您可以编写自定义的比较器。另外,对于ASCII集合之外的字符应该怎么办?你可以找到这样一个比较器的例子,它将按字母和数字进行排序。我将研究编写一个自定义的比较器
类,就像@fge所说的。你希望以什么顺序第二行和十条戒律
sorted?这只是您关心的第一个char
,还是希望保留整个字符串比较的模式?second Chance
是在22次机会之前还是之后出现的呢?
不错,但这是高度依赖于区域设置的(通常是字符串排序),我不明白为什么要执行递归调用。如果第一个字符相同,为什么我们需要检查第二个字符?我想我们只需要知道第一个字符是否是数字,以及如何将其与第二个字符串的第一个数字进行比较。如果我看得正确,你的代码已经正确了。如果第一个代码相同,我们仍然需要比较第二个和更进一步,对吗?请注意,我知道这段代码并不理想……“如果第一段代码相同,我们仍然需要比较第二段代码,然后再进一步比较,对吗?”是的,但正常的字符串比较可以
Appointment
Doctor Preparation
Doctor Review
Doctor Review A
Doctor Review 1
24-Hour Service
3rd Party Contact
public static final Comparator<String> ARABIC_NUMBERS_LAST_COMPARATOR
= new Comparator<String>()
{
@Override
public int compare(final String o1, final String o2)
{
return doCompare(CharBuffer.wrap(o1), CharBuffer.wrap(o2));
}
private int doCompare(final CharBuffer buf1, final CharBuffer buf2)
{
// Test for the emptiness of each buffer
final int r1 = buf1.remaining();
final int r2 = buf2.remaining();
if (r1 == 0)
return r2 == 0 ? 0 : -1;
if (r2 == 0)
return 1; // we know that r1 is not empty here
// Grab the first character from both buffers
final char c1 = buf1.get();
final char c2 = buf2.get();
// If both characters are the same we must continue
if (c1 == c2)
return doCompare(buf1, buf2);
// They are not... Test whether either of them is a digit
final boolean oneIsDigit = Character.isDigit(c1);
final boolean twoIsDigit = Character.isDigit(c2);
// Both are digits: return what the contract expects
if (oneIsDigit && twoIsDigit)
return c1 - c2;
// From this point on we know that at least one character is
// not a digit, and that they are both different.
if (oneIsDigit)
return 1;
if (twoIsDigit)
return -1;
// Both are not digits, but we know them to be different:
// just return the difference
return c1 - c2;
}
}
}
public class TryMe {
public static void main(String[] args) {
List<String> sortMe = new ArrayList<>();
sortMe.add("Doctor Review");
sortMe.add("3rd Party Contact");
sortMe.add("Appointment");
sortMe.add("24-Hour Service");
sortMe.add("Doctor Preparation");
Collections.sort(sortMe, new MyComparator());
System.out.println(sortMe);
}
private static class MyComparator implements Comparator<String> {
@Override
public int compare(String o1, String o2) {
if (Character.isDigit(o1.charAt(0))) {
if (Character.isDigit(o2.charAt(0))) {
//replace here with "return o1.compareTo(o2)" for original
int i1 = getFirstDigits(o1);
int i2 = getFirstDigits(o2);
if (i1 == i2) return o1.compareTo(o2);
return i1 - i2;
} else {
return 1;
}
}
if (Character.isDigit(o2.charAt(0))) return -1;
return o1.compareTo(o2);
}
}
private static int getFirstDigits(String from) {
int i = 0;
for (i = 0 ; i < from.length() ; i++) {
if (!Character.isDigit(from.charAt(i))) {
return Integer.parseInt(from.substring(0, i));
}
}
if (i > 0) return Integer.parseInt(from.substring(0, i));
throw new IllegalArgumentException("No digits to parse, should not happen");
}
}
ArrayList<String> list = new ArrayList<String>();
list.add("Doctor Review");
list.add("3rd Party Contact");
list.add("Appointment");
list.add("24-Hour Service");
list.add("Doctor Preparation");
ArrayList<String> newlist = new ArrayList<>();
Collections.sort(list);
for (String x : list)
{
if (!Character.isDigit(x.charAt(0))) {
newlist.add(x);
}
}
for (String x : list)
{
if (Character.isDigit(x.charAt(0))) {
newlist.add(x);
}
}