2015-07-04 35 views
0

我想按特定顺序排序长度为1或2的字符串的ArrayList。Java - 自定义排序字符串的ArrayList

顺序

1m, 2m, 3m ... 9,, 1p...9p, 1s...9s, E, S, W, N,Wd, Gd, Rd 

,如果你的想法?

例如,ArrayList是;

N 2p 9s 9s 1p 9m N 4s 1m 5p 7m 2s 5s 5m 

我想写一个方法,在这个ArrayList是一个字段,将按期望的顺序。

问题类似于指向比较器的点,但我发现每个解释都很混乱,但是做了一些与我想要的不同的东西。

只需完全写出订单,我就完美无缺。

+0

http://docs.oracle.com/javase/7/docs/api/java/util/Comparator。html – ares

+3

*如果你有这个想法?*不,坦率地说,我不知道。如果你不能清楚地定义规则来判断一个字符串是在另一个字符串之前还是之后,那么你就不能实现它。这个规则被称为比较器。 –

+0

你发现混淆比较方法的是什么?这正是你需要做的。要求澄清原始问题 - 请不要再次提出同样的问题。 –

回答

1

因为我主张重开这一点,这里有一个Comparator<String>会做你想要什么:

package testJ; 

import java.util.Arrays; 
import java.util.Comparator; 
import java.util.List; 

public class WeirdOrderComparator implements Comparator<String> { 
    private static List<String> COMPASS_ORDER = Arrays.asList("E:S:W:N" 
     .split(":")); 
    private static List<String> D_ORDER = Arrays.asList("W:G:R".split(":")); 
    private static List<String> SUFFIX_ORDER = Arrays.asList("m:p:s::d" 
     .split(":")); 

    private int indexFor(String target, List<String> order) { 
    int r = order.indexOf(target); 
    if (r < 0) { 
     return order.size(); 
    } else { 
     return r; 
    } 
    } 

    private int getSuffixNumber(String s) { 
    switch (s.length()) { 
    case 1: 
     return indexFor("", SUFFIX_ORDER); 
    case 2: 
     return indexFor(s.substring(1), SUFFIX_ORDER); 
    default: 
     return 99; 
    } 
    } 

    private int getWithinGroupNumber(int suffixGroup, String s) { 
    switch (suffixGroup) { 
    case 0: 
    case 1: 
    case 2: 
     return Integer.valueOf(s.substring(0, s.length() - 1)); 
    case 3: 
     return indexFor(s, COMPASS_ORDER); 
    case 4: 
     return indexFor(s.substring(0, 1), D_ORDER); 
    default: 
     return 99; 
    } 
    } 

    public int compare(String o1, String o2) { 
    int sfx1 = getSuffixNumber(o1); 
    int sfx2 = getSuffixNumber(o2); 
    if (sfx1 != sfx2) { 
     return sfx1 - sfx2; 
    } 
    int grp1 = getWithinGroupNumber(sfx1, o1); 
    int grp2 = getWithinGroupNumber(sfx2, o2); 
    if (grp1 != grp2) { 
     return grp1 - grp2; 
    } 
    return o1.compareTo(o2); 
    } 
} 

它可以作为:

package testJ; 

import java.util.ArrayList; 
import java.util.Arrays; 
import java.util.Collections; 
import java.util.List; 

public class WeirdOrderTest { 
    public static void main(String args[]) { 
    List<String> testList = Arrays.asList("N 2p 9s 9s 1p 9m N 4s 1m 5p 7m 2s 5s 5m".split(" ")); 
    System.out.println("Original order: " + testList); 
    ArrayList<String> sorted = new ArrayList<String>(); 
    sorted.addAll(testList); 
    Collections.sort(sorted, new WeirdOrderComparator()); 
    System.out.println("Sorted: " + sorted); 
    } 
} 

这将产生:

Original order: [N, 2p, 9s, 9s, 1p, 9m, N, 4s, 1m, 5p, 7m, 2s, 5s, 5m] 
Sorted: [1m, 5m, 7m, 9m, 1p, 2p, 5p, 2s, 4s, 5s, 9s, 9s, N, N] 

这里的一般策略是:

  1. 找到一个可以区分两个字符串的规则。在这种情况下,我首先确定字符串的一般“组”:以“m”,“p”,“s”结尾的单个字母或以“d”结尾的内容。

  2. 如果该规则区分两个输入,则返回一个数字,如果o1应该优先,则返回负数;如果o1应该晚一些,则返回正数。要记住这个约定,请考虑“这就像o1 - o2,如果o1o2是小整数”(忽略溢出)。

  3. 如果规则不区分o1o2,找到另一条规则等

  4. 最后,如果您运行的规则,返回0或委托给其他一些比较。

记住这个,你Comparator应该合理处理,你不要指望字符串 - 它可以抛出一个异常(因为这一个会,如果你给它“XS”),但如果不投一个例外,那么结果应该是一致的。也就是说,如果compare(x, y) < 0compare(y, z) < 0那么如果compare(x, z)不会引发异常,则compare(x, z)必须是负数,而不管xyz是什么。确保这种结构的一种方法是按照我在此处所做的方式构建比较器,其中我为每个字符串找到一系列“订单号”,然后在订单号无帮助时委托给String.compareTo