【问题标题】:Complex sorting of Java ArrayList [duplicate]Java ArrayList的复杂排序[重复]
【发布时间】:2013-02-28 19:38:37
【问题描述】:

我在trendList 变量中存储了以下字符串。我进行了排序,但数据没有正确排序。

ACLK_SCRN_200MHZ_DATAB_S0_P1:8 应该在 ACLK_SCRN_200MHZ_DATAB_S0_P10:8 之前

1 < 10 开始,其余字符串以此类推。

问题:如何进行这种字母数字排序以获得正确的顺序?

我必须自己制作函数吗?那会是什么样子?

List<String> trendList = new ArrayList<String>(80000);

Collections.sort(trendList);

ACLK_SCRN_200MHZ_DATAB_S0_P0:8
ACLK_SCRN_200MHZ_DATAB_S0_P10:8
ACLK_SCRN_200MHZ_DATAB_S0_P11:8
ACLK_SCRN_200MHZ_DATAB_S0_P12:8
ACLK_SCRN_200MHZ_DATAB_S0_P13:8
ACLK_SCRN_200MHZ_DATAB_S0_P14:8
ACLK_SCRN_200MHZ_DATAB_S0_P15:8
ACLK_SCRN_200MHZ_DATAB_S0_P1:8
ACLK_SCRN_200MHZ_DATAB_S0_P2:8
ACLK_SCRN_200MHZ_DATAB_S0_P3:8
ACLK_SCRN_200MHZ_DATAB_S0_P4:8
ACLK_SCRN_200MHZ_DATAB_S0_P5:8
ACLK_SCRN_200MHZ_DATAB_S0_P6:8
ACLK_SCRN_200MHZ_DATAB_S0_P7:8
ACLK_SCRN_200MHZ_DATAB_S0_P8:8
ACLK_SCRN_200MHZ_DATAB_S0_P9:8
ACLK_SCRN_200MHZ_DATAB_S1_P0:8
ACLK_SCRN_200MHZ_DATAB_S1_P10:8
ACLK_SCRN_200MHZ_DATAB_S1_P11:8
ACLK_SCRN_200MHZ_DATAB_S1_P12:8
ACLK_SCRN_200MHZ_DATAB_S1_P13:8
ACLK_SCRN_200MHZ_DATAB_S1_P14:8
ACLK_SCRN_200MHZ_DATAB_S1_P15:8
ACLK_SCRN_200MHZ_DATAB_S1_P1:8
ACLK_SCRN_200MHZ_DATAB_S1_P2:8
ACLK_SCRN_200MHZ_DATAB_S1_P3:8
ACLK_SCRN_200MHZ_DATAB_S1_P4:8
ACLK_SCRN_200MHZ_DATAB_S1_P5:8
MLC_C_SAMPLE
MLC_SAMPLE
SWR
TOUCHDOWN
TEST_REV

【问题讨论】:

  • 您可以编写一个正则表达式并在数字上使用自定义字符串比较器。但是,实现一个解析这些字符串的对象并在对象上实现自定义compareTo() 方法或Comparator 会更有意义。

标签: java sorting alphanumeric


【解决方案1】:

您得到该结果是因为它仅使用默认的 String.compareTo 比较字符串,该字符串使用原始字符代码。 ':' 出现在 '0'-'9' 之后,因此它会在之后进行整理。

您需要提供自己的Comparator 并致电

Collections.sort(trendList, new CustomComparator());

【讨论】:

    【解决方案2】:

    你可以用你自己的 Comparator 来做这样的事情:

    class TrendListComparator implements Comparator<String> {
         // retrieve the P and S
         final Pattern p = Pattern.compile(".*_S(\\d+)_P(\\d+).*");
         public int compare(String str1, String str2) {
             Matcher m1 = p.matcher(str1);
             Matcher m2 = p.matcher(str2);
             if (m1.matches() && m2.matches()) {
                 Integer s1 = Integer.valueOf(m.group(1));
                 Integer p1 = Integer.valueOf(m.group(2));
                 Integer s2 = Integer.valueOf(m.group(1));
                 Integer p2 = Integer.valueOf(m.group(2));
                 // compare
                 return s1.equals(s2) ? p1.compareTo(p2) : s1.compareTo(s2);
             } else {
                 return str1.compareTo(str2); // standard sort if no P and S
             }
         }
    }
    
    Collections.sort(trendList, new TrendListComparator());
    

    您可以在此处查看运行示例:http://ideone.com/AleOEy

    您甚至可以只使用一个 Matcher 并在同一排序过程中一直重复使用它:

    class TrendListComparator implements Comparator<String> {
         // retrieve the P and S
         final Matcher m = Pattern.compile(".*_S(\\d+)_P(\\d+).*_S(\\d+)_P(\\d+).*").matcher("");
         public int compare(String str1, String str2) {
             if (m.reset(str1 + str2).matches()) {
                 Integer s1 = Integer.valueOf(m.group(1));
                 Integer p1 = Integer.valueOf(m.group(2));
                 Integer s2 = Integer.valueOf(m.group(3));
                 Integer p2 = Integer.valueOf(m.group(4));
                 // compare
                 return s1.equals(s2) ? p1.compareTo(p2) : s1.compareTo(s2);
             } else {
                 return str1.compareTo(str2); // standard sort if no P and S
             }
         }
    }
    

    见:http://ideone.com/EsfFPj

    【讨论】:

    • 嘿,我真的很喜欢这段代码,但是如何进行错误检查呢?就像检查字符串中是否有整数一样?我一直在“出错”!
    • @user1022944 您可以在此处查看运行示例:ideone.com/AleOEy
    【解决方案3】:

    您可以将自定义比较器传递给Collections.sort() 函数:

    Collections.sort(trendList, new Comparator<String>() {
    
        @Override
        public int compare(String s1, String s2) {
            int sValue1 = s1.split(...) // split the strings to retrieve their values
            int sValue2 = // ...
            int pValue1 = // ...
            int pValue2 = // ...
            if (sValue1 > sValue2) { return 1; }
            if (sValue1 < sValue2) { return -1; }
            if (pValue1 > pValue2) { return 1; }
            if (pValue 1 < pValue2) { return -1; }
            return 0;
        }
    
    });
    

    【讨论】:

      【解决方案4】:

      您可以创建自己的类来实现Comparator&lt;String&gt; 接口。在compare 方法中,您将需要解析字符串并从字符串的相关部分中提取需要按数字排序的数字。如果 s1 小于 s2,该方法应该返回一个小于 0 的数字,如果 s1 等于 s2 则返回 0,如果 s1 大于 s2 则返回大于 0。

      public class MyTrendListComparator implements Comparator<String>
      {
          public int compare(String s1, String s2)
          {
              // Parse and compare here.
          }
      }
      

      然后将比较器的实例传递给Collections.sort

      Collections.sort(trendList, new MyTrendListComparator());
      

      【讨论】:

        【解决方案5】:

        代码如下:

        import java.util.Arrays;
        import java.util.Collections;
        import java.util.Comparator;
        import java.util.List;
        
        public class CustomSorter {
           public static void main( String[] args ) {
              String[] data = {
                 "ACLK_SCRN_200MHZ_DATAB_S0_P0:8",
                 "ACLK_SCRN_200MHZ_DATAB_S0_P10:8",
                 ...
                 "ACLK_SCRN_200MHZ_DATAB_S1_P4:8",
                 "ACLK_SCRN_200MHZ_DATAB_S1_P5:8",
              };
              List<String> trendList = Arrays.asList( data );
              Collections.sort( trendList, new Comparator< String >(){
                 @Override public int compare( String o1, String o2 ){
                    String[] p1 = o1.split( "_S\\d+_P" );
                    String[] p2 = o2.split( "_S\\d+_P" );
                    if( p1.length != 2 ) {
                       throw new IllegalStateException("Unexpected item: '"+o1+"'");
                    }
                    if( p2.length != 2 ) {
                       throw new IllegalStateException("Unexpected item: '"+o1+"'");
                    }
                    final int i1;
                    try{
                       i1 = Integer.parseInt(p1[1].substring(0,p1[1].indexOf(':')));
                    } catch( NumberFormatException x ) {
                       throw new IllegalStateException( "Unexpected item: '"+o1+"'");
                    }
                    final int i2;
                    try{
                       i2 = Integer.parseInt(p2[1].substring(0,p2[1].indexOf(':')));
                    } catch( NumberFormatException x ) {
                       throw new IllegalStateException("Unexpected item: '"+o2+"'");
                    }
                    int cmp = p1[0].compareTo( p2[0] );
                    if( cmp == 0 ) {
                       cmp = i1 - i2;
                    }
                    return cmp;
                 }});
              for( String entry : trendList ) {
                 System.out.println( entry );
              }
           }
        }
        

        和输出:

        ACLK_SCRN_200MHZ_DATAB_S0_P0:8
        ACLK_SCRN_200MHZ_DATAB_S0_P1:8
        ACLK_SCRN_200MHZ_DATAB_S0_P2:8
        ACLK_SCRN_200MHZ_DATAB_S0_P3:8
        ACLK_SCRN_200MHZ_DATAB_S0_P4:8
        ACLK_SCRN_200MHZ_DATAB_S0_P5:8
        ACLK_SCRN_200MHZ_DATAB_S0_P6:8
        ACLK_SCRN_200MHZ_DATAB_S0_P7:8
        ACLK_SCRN_200MHZ_DATAB_S0_P8:8
        ACLK_SCRN_200MHZ_DATAB_S0_P9:8
        ACLK_SCRN_200MHZ_DATAB_S0_P10:8
        ACLK_SCRN_200MHZ_DATAB_S0_P11:8
        ACLK_SCRN_200MHZ_DATAB_S0_P12:8
        ACLK_SCRN_200MHZ_DATAB_S0_P13:8
        ACLK_SCRN_200MHZ_DATAB_S0_P14:8
        ACLK_SCRN_200MHZ_DATAB_S0_P15:8
        ACLK_SCRN_200MHZ_DATAB_S1_P0:8
        ACLK_SCRN_200MHZ_DATAB_S1_P1:8
        ACLK_SCRN_200MHZ_DATAB_S1_P2:8
        ACLK_SCRN_200MHZ_DATAB_S1_P3:8
        ACLK_SCRN_200MHZ_DATAB_S1_P4:8
        ACLK_SCRN_200MHZ_DATAB_S1_P5:8
        ACLK_SCRN_200MHZ_DATAB_S1_P10:8
        ACLK_SCRN_200MHZ_DATAB_S1_P11:8
        ACLK_SCRN_200MHZ_DATAB_S1_P12:8
        ACLK_SCRN_200MHZ_DATAB_S1_P13:8
        ACLK_SCRN_200MHZ_DATAB_S1_P14:8
        ACLK_SCRN_200MHZ_DATAB_S1_P15:8
        

        【讨论】:

        • 很好,但是什么是STR_LENGTH?
        • ACLK_SCRN_200MHZ_DATAB_S12 将出现在 ACLK_SCRN_200MHZ_DATAB_S2 之前,如果您不检查 S\\d+ 号码。
        • 好的,按照你的建议修改答案。
        • 这很好。最后一个问题。如果有一个字符串不包含“_”或“:”,但我仍然希望它正确排序怎么办?似乎 substring( 0, p1[1].indexOf( ':' )) 会破坏代码,因为 indexOf 会返回-1。那么我会重新分配 i1 和 i2 什么?
        • 添加了错误处理。请发布输入字符串的详尽规范。
        猜你喜欢
        • 2021-11-04
        • 1970-01-01
        • 2016-06-13
        • 1970-01-01
        • 1970-01-01
        • 2013-07-05
        • 2015-11-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多