10

How can I sort an array first by length, then alphabetically?

I have a list of things with numbers on them, and I am currently getting:

Something1 Something10 Something2 Something3

Whereas I want to get:

Something1 Something2 Something3 Something10

Brian
  • 2,191
  • 3
  • 20
  • 30
  • 1
    By any chance, homework? – Dean J Aug 04 '10 at 19:19
  • Nope, just have a ton of files I wanted to rename really quickly. They are numbered, but the numbers need to be shifted by a bit and the rest of the file name changed around. But the natural ordering by the operating system generally returns 1 10 11 12 13 14 15 16 17 18 19 2 20 etc. – Brian Aug 04 '10 at 19:34
  • 1
    Having you tried just using leading zeroes in your numbers? IE, 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11. – Jeff Davis Aug 04 '10 at 19:52
  • Have a look at the answers for http://stackoverflow.com/questions/104599/sort-on-a-string-that-may-contain-a-number if what you really want is a sort that understands the number part. – Paul Tomblin Aug 04 '10 at 19:19

6 Answers6

25
public class MyComparator implements Comparator<String>{
    @Override
    public int compare(String o1, String o2) {  
      if (o1.length() > o2.length()) {
         return 1;
      } else if (o1.length() < o2.length()) {
         return -1;
      }
      return o1.compareTo(o2);
    }
}

Then use:

Collections.sort(yourList, new MyComparator());
KeatsPeeks
  • 19,126
  • 5
  • 52
  • 83
10

Here's a concise Java 8 solution:

List<String> list = Arrays.asList("Something1", "Something10", "Something2", "Something3");
list.sort(Comparator.comparing(String::length).thenComparing(String::compareTo));

Or, case-insensitive version:

list.sort(Comparator.comparing(String::length).thenComparing(String::compareToIgnoreCase));
Lukas Eder
  • 211,314
  • 129
  • 689
  • 1,509
4

Create a Comparator which compares by length first and if the lengths are the same, uses the String.compareTo().

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
1

Sorting first by length and then lexically will work ONLY if the string prefixes (i.e. the part before the number) is the same length in all cases. I believe you may really want to write a comparator that separates the string and numeric parts and sorts alphabetically on the string and numerically on the number part.

Jim Garrison
  • 85,615
  • 20
  • 155
  • 190
0

Define a class to hold your item in. Seems like you want it to be a String.

For that class, you need to define the Comparable interface and put the logic to compare in its abstract method.

int compareTo(T o)  

For example:

class MyString extends String
{
  @Override
  int compareTo(Object obj)
  {
    // put your logic in here. 
    // Return -1 if this is "less than" obj. 
    // Return 0 if this is equal to obj
    // Return 1 if this is "greater than" obj.

    // Test length first
    if (length() < obj.length())
      return -1;
    if (length() > obj.length())
      return 1;

    // Lengths are the same, use the alphabetical compare defined by String already
    return super.compareTo(obj);
   }
}

Disclaimer, I didn't actually test this code, but it should be close to what you want.

Starkey
  • 9,673
  • 6
  • 31
  • 51
0

By using lambda, The java program looking like.

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

public class Test1 {

    public static void main(String[] args) {
        
        String str = "This is am example";
        List<String> strl = Arrays.asList(str.split(" "));
        strl.sort( (o1,o2)->{
            if(o1.length() > o2.length())      return 1;
            else if(o1.length() < o2.length()) return -1;
            else                               return o1.compareTo(o2);
        });
        System.out.println(strl);

    }
}
Rajeev Ranjan
  • 272
  • 2
  • 11
  • 20