2

How can I achieve a custom sorting to the content of field name:

  • first element: P followed by numbers [1-9]{2} always on first
  • followed by : P followed by numbers 0[0-9]
  • followed by : S
  • followed by numbers [1-9]{2}
  • and then the rest in normal order i1.getName().compareToIgnoreCase(i2.getName())

    private static Comparator<Item> itemComperator = new Comparator<Item>() {
        @Override
        public int compare(Item i1, Item i2) {
            if (i1.getName().matches("P[1-9]{2}") && i2.getName().matches("P0[0-9]"))
                return -1;
            else if (i1.getName().matches("S[1-9]{2}"))
                return -1;
            else
                return i1.getName().compareToIgnoreCase(i2.getName());
        }
    };
    
    @Test
    public void sortItem() {
        Item item01 = new Item(1, "R59");
        Item item02 = new Item(2, "S48");
        Item item03 = new Item(3, "P01");
        Item item04 = new Item(4, "P25");
        Item item05 = new Item(5, "R99");
    
        List<Item> items = Arrays.asList(item01, item02, item03, item04, item05);
        System.out.println("before sorting");
        long seed = System.nanoTime();
        Collections.shuffle(items, new Random(seed));
        for (Item i : items) {
            System.out.println(i.getId() + " " + i.getName());
        }
    
        System.out.println("after sorting");
        Collections.sort(items, itemComperator);
        for (Item i : items) {
            System.out.println(i.getId() + " " + i.getName());
        }
    
    
    }
    
    public class Item {
        private int id;
        private String name;
    
        public Item(int id, String name) {
            this.id = id;
            this.name = name;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
    

output expected:

after sorting
4 P25
3 P01
2 S48
1 R59
5 R99
1
  • Can you include the required out-put with the question .. ??? Commented Apr 8, 2016 at 8:39

1 Answer 1

5

I think that I would first map each of the inputs to a "kind" number, which is based upon the list of criteria above. For example:

int kind(String input) {
  if (input.matches("P[1-9]{2}") {
    return 0;
  } else if (input.matches("P0[0-9]")) {
    return 1;
  } else if (input.matches("S.*")) {
    return 2;
  } else if (input.matches("[1-9]{2}")) {
    return 3;
  } else {
    return 4;
  }
}

This gives you a way to see if the two strings are of the same "kind"; if not, return the ordering based on the kind. If they are the same kind, just compare them using (case insensitive) lexicographic ordering (you don't specify, but I assume you want e.g. "P11" to come before "P22"):

public int compare(Item a, Item b) {
  String nameA = a.getName();
  String nameB = b.getName();

  int kindA = kind(nameA);
  int kindB = kind(nameB);
  if (kindA != kindB) {
    return Integer.compare(kindA, kindB);
  } else {
    return nameA.compareToIgnoreCase(nameB);
  }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Maybe input.matches("S.*") instead of input.matches("S*")?

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.