You have to write a custom comparator using a regular expressions:
public static class Data {
private final String name;
private final String description;
public Data(String name, String description) {
this.name = name;
this.description = description;
}
}
public static void main(String... args) {
List<Data> data = new ArrayList<>();
data.add(new Data("GGGG F B 15 x 1200 x 2700 T", "Description"));
data.add(new Data("GGGG F B 15 x 900 x 1800 T", "Description"));
data.add(new Data("GGGG F B 12.5 x 1200 x 2400 T", "Description"));
data.add(new Data("GGGG F B 12.5 x 1200 x 3000 T", "Description"));
data.add(new Data("GGGG F B 12.5 x 900 x 1800 T", "Description"));
data.add(new Data("GGGG F B 12.5 x 1200 x 2400 S", "Description"));
data.add(new Data("GGGG F B 15 x 1200 x 2400 T", "Description"));
data.add(new Data("GGGG F B 12.5 x 1200 x 2700 T", "Description"));
data.add(new Data("GGGG F B 15 x 900 x 1800 T", "Description"));
Comparator<Data> sortByName = new Comparator<>() {
private final Pattern pattern = Pattern.compile("([^\\s])+\\s+([^\\s])+\\s+" +
"([^\\s])+\\s+(?<length>[^\\s]+)\\sx\\s+(?<width>[^\\s]+)\\s+" +
"x\\s+(?<thickness>[^\\s]+)\\s+([^\\s]+)");
@Override
public int compare(Data one, Data two) {
Matcher matcherOne = pattern.matcher(one.name);
Matcher matcherTwo = pattern.matcher(two.name);
boolean matchOne = matcherOne.matches();
boolean matchTwo = matcherTwo.matches();
if (!matchOne || !matchTwo)
return 0;
int res = compareString(matcherOne, matcherTwo, 1);
res = res != 0 ? res : compareString(matcherOne, matcherTwo, 2);
res = res != 0 ? res : compareString(matcherOne, matcherTwo, 3);
res = res != 0 ? res : compareDouble(matcherOne, matcherTwo, "length");
res = res != 0 ? res : compareDouble(matcherOne, matcherTwo, "width");
res = res != 0 ? res : compareDouble(matcherOne, matcherTwo, "thickness");
res = res != 0 ? res : compareString(matcherOne, matcherTwo, 7);
return res;
}
private int compareDouble(Matcher one, Matcher two, String group) {
double a = Double.parseDouble(one.group(group));
double b = Double.parseDouble(two.group(group));
return Double.compare(a, b);
}
private int compareString(Matcher one, Matcher two, int group) {
String a = one.group(group);
String b = two.group(group);
return a.compareTo(b);
}
};
data.forEach(d -> System.out.println(d.name));
data.sort(sortByName);
System.out.println();
data.forEach(d -> System.out.println(d.name));
}
Output
GGGG F B 15 x 1200 x 2700 T
GGGG F B 15 x 900 x 1800 T
GGGG F B 12.5 x 1200 x 2400 T
GGGG F B 12.5 x 1200 x 3000 T
GGGG F B 12.5 x 900 x 1800 T
GGGG F B 12.5 x 1200 x 2400 S
GGGG F B 15 x 1200 x 2400 T
GGGG F B 12.5 x 1200 x 2700 T
GGGG F B 15 x 900 x 1800 T
GGGG F B 12.5 x 900 x 1800 T
GGGG F B 12.5 x 1200 x 2400 S
GGGG F B 12.5 x 1200 x 2400 T
GGGG F B 12.5 x 1200 x 2700 T
GGGG F B 12.5 x 1200 x 3000 T
GGGG F B 15 x 900 x 1800 T
GGGG F B 15 x 900 x 1800 T
GGGG F B 15 x 1200 x 2400 T
GGGG F B 15 x 1200 x 2700 T
900 x 1800to come before1200 x 3000? The string-sorting is lexicographical and1comes before9in the alphabet. Thats why it sorts like that. Do you actually want to interpret the numbers as numbers and sort them ascending instead of lexicographical? This will be quite difficult if you only have the data as text, since you will have to extract the numbers and parse them.Comparatorthat combines all of that.String? On the level of your class, cant you have it asdouble length; int width; int thickness;? Would be much easier then.