Reputation: 940
I am currently using SortedSet<String> fileNames = new TreeSet<String>()
to sort file names, but they are not being ordered like I wanted to.
That's exactly what I do:
File folder = new File(PATH);
File[] listOfFiles = folder.listFiles();
SortedSet<String> fileNames = new TreeSet<String>;
for (int i = 0; i < listOfFiles.length; i++)
{
if (listOfFiles[i].isFile())
{
fileNames.add(listOfFiles[i].getName());
}
}
Output:
X_1(1).PNG
X_1(2).PNG
X_1(3).PNG
X_10(1).PNG
X_10(2).PNG
X_10(3).PNG
X_100(1).PNG
X_100(2).PNG
X_100(3).PNG
Desired output:
X_1(1).PNG
X_1(2).PNG
X_1(3).PNG
X_2(1).PNG
X_2(2).PNG
X_2(3).PNG
Upvotes: 0
Views: 341
Reputation: 11959
You are looking for a natural sort comparator, one which understands sequence of number.
You could use one of these:
The first may be used as a maven dependency, however since the Comparator does not implements Comparator<String>
(but rather only Comparator
) you may as well do a pull request to do that.
The last one is probably the best as it is ASL 2.0.
By the way, you should keep using File (or Path) in the TreeSet and pass in a comparator:
Comparator<String> naturalSortComparator = ...;
TreeSet<File> files = new TreeSet<>(Comparators.comparing(File::getName, naturalSortComparator));
This one will sort File
entries by name using the naturalSortComparator
.
Upvotes: 0
Reputation: 404
Put this Comparator parameter in the TreeSet constructor :
Comparator<String> stringComparator = (o1, o2) -> {
int o1FirstNum = Integer.parseInt(o1.substring(o1.indexOf('_') + 1, o1.indexOf('(')));
int o2FirstNum = Integer.parseInt(o2.substring(o2.indexOf('_') + 1, o2.indexOf('(')));
if (o1FirstNum == o2FirstNum) {
int o1SecondNum = Integer.parseInt(o1.substring(o1.indexOf('(') + 1, o1.indexOf(')')));
int o2SecondNum = Integer.parseInt(o2.substring(o2.indexOf('(') + 1, o2.indexOf(')')));
return o1SecondNum - o2SecondNum;
}
return o1FirstNum - o2FirstNum;
};
SortedSet<String> fileNames = new TreeSet<String>(stringComparator);
Upvotes: 1
Reputation: 844
This Comparator should resolve your problem.
public class Test {
public static void main(String... args) {
String[] list = {"X_1(1).PNG", "X_1(2).PNG", "X_1(3).PNG", "X_10(1).PNG", "X_10(2).PNG", "X_10(3).PNG", "X_100(1).PNG", "X_100(2).PNG", "X_100(3).PNG"};
SortedSet<String> fileNames = new TreeSet<>(Test::compare);
fileNames.addAll(Arrays.asList(list));
fileNames.forEach(System.out::println);
}
private static int compare(String first, String second) {
int firstNumber = Integer.parseInt(first.substring(first.indexOf('_') + 1, first.indexOf('(')));
int secondNumber = Integer.parseInt(second.substring(first.indexOf('_') + 1, second.indexOf('(')));
int difference = firstNumber - secondNumber;
if (difference != 0) {
return difference;
}
firstNumber = Integer.parseInt(first.substring(first.indexOf('(') + 1, first.indexOf(')')));
secondNumber = Integer.parseInt(second.substring(first.indexOf('(') + 1, second.indexOf(')')));
return firstNumber - secondNumber;
}
}
Upvotes: 0