繁体   English   中英

Java-字符串的自定义排序ArrayList

[英]Java - Custom Sort ArrayList of Strings

我想按特定顺序对长度为1或2的字符串的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是将其按所需顺序放置的字段的类中编写一个方法。

相似的问题指向比较器,但是我发现每个解释都非常混乱,但是无论如何我做的都不一样。

只需完全将订单写完即可,Id非常好。

由于我主张重新打开它,因此下面的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随后出现,则返回正数。 为了记住这一约定,请考虑“如果o1o2是小整数,则就像o1 - o2 ”(忽略溢出)。

  3. 如果该规则不能区分o1o2 ,请找到另一个规则, o1 o2

  4. 最后,如果您用完规则,则返回0或委托其他比较。

请记住,您的Comparator应该合理地处理您不期望的字符串-它可以引发异常(因为如果您给它赋予“ Xs”,它将引发异常),但是如果它不引发异常,则结果应为一致的。 也就是说,如果compare(x, y) < 0compare(y, z) < 0则如果compare(x, z)没有引发异常,则不管x是什么, compare(x, z)必须为负。 , yz为。 确保比较器的一种方法是按照我在此处所做的方式构造比较器,在该方法中,我为每个字符串找到一系列“订单号”,然后如果订单号无济于事,则委托给String.compareTo

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM