0

I have a List of Strings. EXAMPLE_1, EXAMPLE_2, EXAMPLE_3 ... EXAMPLE_99 What is the best algorithm for sorting here?

Is it possible with a Collator? This is my current procedure, but I guess there could be a better way:

public class Example implements Comparable<Example> {
    private final String id;

    public getId() {
        return id;
    }

    private Integer getIdNo() {
        try {
            return Integer.parseInt(getId().replaceAll("[\\D]", ""));
        } catch (NumberFormatException e) {
            return null;
        }
    }

    @Override
    public int compareTo(Example o) {
        if ((getIdNo() == null && getIdNo() != null) || (getProductFeatureId_sizeNo() < o.getProductFeatureId_sizeNo())) {
            return -1;
        } else if (o.getIdNo() == null || getIdNo() > o.getIdNo()) {
            return 1;
        }

        return 0;
    }
}
5
  • Your code will fail if getIdNo() returns null for o. Commented Jun 29, 2012 at 7:12
  • right, thanks for this addition. But I need a better way for comparing this. try/catch doesn't seem to be a good way... Commented Jun 29, 2012 at 7:18
  • 1
    I don't really see any other way. You could use a regexp to extract the numerical part, but in the end, you'll need to use parseInt(), and handle the exception (even if it never happens) Commented Jun 29, 2012 at 7:22
  • Why no use the default sort provided bu Collections ? Commented Jun 29, 2012 at 7:25
  • @pavi that would be right if target strings would be like "Example_XX" where XX is 01,02,03,..99. At fact "EXAMPLE_2" is less then "EXAMPLE_20". Can you have two decimals strings? Commented Jun 29, 2012 at 7:31

4 Answers 4

2

This is better alternative - AlphanumComparator.java

Copying the code for ready reference -

public class AlphanumComparator implements Comparator
{
    private final boolean isDigit(char ch)
    {
        return ch >= 48 && ch <= 57;
    }

    /** Length of string is passed in for improved efficiency (only need to calculate it once) **/
    private final String getChunk(String s, int slength, int marker)
    {
        StringBuilder chunk = new StringBuilder();
        char c = s.charAt(marker);
        chunk.append(c);
        marker++;
        if (isDigit(c))
        {
            while (marker < slength)
            {
                c = s.charAt(marker);
                if (!isDigit(c))
                    break;
                chunk.append(c);
                marker++;
            }
        } else
        {
            while (marker < slength)
            {
                c = s.charAt(marker);
                if (isDigit(c))
                    break;
                chunk.append(c);
                marker++;
            }
        }
        return chunk.toString();
    }

    public int compare(Object o1, Object o2)
    {
        if (!(o1 instanceof String) || !(o2 instanceof String))
        {
            return 0;
        }
        String s1 = (String)o1;
        String s2 = (String)o2;

        int thisMarker = 0;
        int thatMarker = 0;
        int s1Length = s1.length();
        int s2Length = s2.length();

        while (thisMarker < s1Length && thatMarker < s2Length)
        {
            String thisChunk = getChunk(s1, s1Length, thisMarker);
            thisMarker += thisChunk.length();

            String thatChunk = getChunk(s2, s2Length, thatMarker);
            thatMarker += thatChunk.length();

            // If both chunks contain numeric characters, sort them numerically
            int result = 0;
            if (isDigit(thisChunk.charAt(0)) && isDigit(thatChunk.charAt(0)))
            {
                // Simple chunk comparison by length.
                int thisChunkLength = thisChunk.length();
                result = thisChunkLength - thatChunk.length();
                // If equal, the first different number counts
                if (result == 0)
                {
                    for (int i = 0; i < thisChunkLength; i++)
                    {
                        result = thisChunk.charAt(i) - thatChunk.charAt(i);
                        if (result != 0)
                        {
                            return result;
                        }
                    }
                }
            } else
            {
                result = thisChunk.compareTo(thatChunk);
            }

            if (result != 0)
                return result;
        }

        return s1Length - s2Length;
    }
}

Note: you should generify this class if you're using java 1.5+

Sign up to request clarification or add additional context in comments.

Comments

1
private Integer getIdNo() {
        try {
            return Integer.parseInt(getId().replaceAll("[\\D]", ""));
        } catch (NumberFormatException e) {
            return 0;
        }
    }

@Override
public int compareTo(Example o) {
    if(o == null) {
        return 1;
    }
    return getIdNo().compareTo(o.getIdNo());
}

Comments

1

To build on @Jeshuruns answer, you could skip all the number parsing like this:

  @Override
  public int compareTo(Example o) {
      if (o == null) {
          return 1;
      }
      if (getId().length() != o.getId().length() {
          return (getId().length() - o.getId().length());
      } else {
          return getId().compareTo(o.getId());
      }
  }

Comments

0

You can Write something like this.

public class Sorter implements Comparator<String>
{
   public int compareTo(String str1,String str2)
   {
       if( str1 == null )
       {
           return -1;
       }
       if( str2 == null )
       {
           return 1;
       }
       int val1 = Integer.parseInt(this.split("_")[1]);
       int val2 = Integer.parseInt(str.split("_")[1]);

       if(val1<val2)
       {
           return -1;
       }
       else if(val1 > val2)
       {
           return 1;
       }
       else
       {
           return 0;
       }
   }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.