Sort on a string that may contain a number

前端 未结 23 2321
走了就别回头了
走了就别回头了 2020-11-22 02:59

I need to write a Java Comparator class that compares Strings, however with one twist. If the two strings it is comparing are the same at the beginning and end of the strin

23条回答
  •  滥情空心
    2020-11-22 03:51

    Here is the solution with the following advantages over Alphanum Algorithm:

    1. 3.25x times faster (tested on the data from 'Epilogue' chapter of Alphanum description)
    2. Does not consume extra memory (no string splitting, no numbers parsing)
    3. Processes leading zeros correctly (e.g. "0001" equals "1", "01234" is less than "4567")
    public class NumberAwareComparator implements Comparator
    {
        @Override
        public int compare(String s1, String s2)
        {
            int len1 = s1.length();
            int len2 = s2.length();
            int i1 = 0;
            int i2 = 0;
            while (true)
            {
                // handle the case when one string is longer than another
                if (i1 == len1)
                    return i2 == len2 ? 0 : -1;
                if (i2 == len2)
                    return 1;
    
                char ch1 = s1.charAt(i1);
                char ch2 = s2.charAt(i2);
                if (Character.isDigit(ch1) && Character.isDigit(ch2))
                {
                    // skip leading zeros
                    while (i1 < len1 && s1.charAt(i1) == '0')
                        i1++;
                    while (i2 < len2 && s2.charAt(i2) == '0')
                        i2++;
    
                    // find the ends of the numbers
                    int end1 = i1;
                    int end2 = i2;
                    while (end1 < len1 && Character.isDigit(s1.charAt(end1)))
                        end1++;
                    while (end2 < len2 && Character.isDigit(s2.charAt(end2)))
                        end2++;
    
                    int diglen1 = end1 - i1;
                    int diglen2 = end2 - i2;
    
                    // if the lengths are different, then the longer number is bigger
                    if (diglen1 != diglen2)
                        return diglen1 - diglen2;
    
                    // compare numbers digit by digit
                    while (i1 < end1)
                    {
                        if (s1.charAt(i1) != s2.charAt(i2))
                            return s1.charAt(i1) - s2.charAt(i2);
                        i1++;
                        i2++;
                    }
                }
                else
                {
                    // plain characters comparison
                    if (ch1 != ch2)
                        return ch1 - ch2;
                    i1++;
                    i2++;
                }
            }
        }
    }
    

提交回复
热议问题