Idea of solution
First, you have to see that the file names have the prefix + suffix format, where the suffix is a number. With this, we can orgazinar your files, ordering them first by the prefix and then by the suffix.
Implementing the solution
As such, you will need a function that knows how to sort the file names correctly. Here's one:
public static int comparaNomesDeArquivos(String nome1, String nome2) {
if (Objects.equals(nome1, nome2)) return 0;
if (nome1 == null) return -1;
if (nome2 == null) return 1;
int sufixo1 = 0, sufixo2 = 0;
int n;
int p = 1;
for (n = nome1.length() - 1; n >= 0; n--) {
char c = nome1.charAt(n);
if (c < '0' || c > '9') break;
sufixo1 += (c - '0') * p;
p *= 10;
}
p = 1;
String prefixo1 = nome1.substring(0, n + 1);
for (n = nome2.length() - 1; n >= 0; n--) {
char c = nome2.charAt(n);
if (c < '0' || c > '9') break;
sufixo2 += (c - '0') * p;
p *= 10;
}
String prefixo2 = nome2.substring(0, n + 1);
int a = prefixo1.compareTo(prefixo2);
if (a != 0) return a;
int b = sufixo1 - sufixo2;
if (b != 0) return b;
return nome1.compareTo(nome2);
}
The explanation of this function is as follows:
Like any comparison function in Java , it has as parameter two elements to be compared. Returns a positive number if the first element is after the second, negative if it is before, or zero if both are the same.
For the sake of optimization, we first check whether% w and% w are identical, and in this case we know that they are equal. This case is determined with String
". This check also works if both Objects.equals(Object, Object)
s is String
.
If one of the null
s is String
(and it is already known that only one of them could be because the case where the two are is treated in step 2), then consider that null
precedes any else, returning -1 or 1 in these cases.
To separate the suffix prefix, this function traverses each back-to-front string for the purpose of determining them. For this, a null
loop is used for each.
If the prefix of for
s is different, then the ordering is given by the prefix.
Since the prefixes are the same, then the ordering is given by the suffix, which is a number.
Since prefixes and suffixes are the same, what can happen if you compare String
with batatinha123
, that is, when the difference is only for the zeros to the left of the number, then it uses the form of standard comparison.
Knowing how to compare% s with% s, you can set up a function to compare files. I do not know exactly how you're repressing a file. If it goes directly by their names, then you can skip this part. Otherwise, assuming the batatinha0123
method is what determines the filename, do this:
public static int comparaArquivosPorNome(Arquivo arquivo1, Arquivo arquivo2) {
String nome1 = arquivo1 == null ? null : arquivo1.getFilename();
String nome2 = arquivo2 == null ? null : arquivo2.getFilename();
return comparaNomesDeArquivos(nome1, nome2);
}
Oh, and let's assume that the above methods are in a class called String
.
Finally, you can sort your getFilename()
using method Ordenacao
:
Collections.sort(suaArrayList, Ordenacao::comparaArquivosPorNome);
If you're only using List<Arquivo>
instead of sort(List<T>, Comparator<? super T>)
, use this:
Collections.sort(suaArrayList, Ordenacao::comparaNomesDeArquivos);
Test
To test all this, let's assume that this is the class List<String>
:
public class Arquivo {
private String nome;
public Arquivo(String nome) {
this.nome = nome;
}
public String getFilename() {
return nome;
}
@Override
public String toString() {
return "arquivo {" + nome + "}";
}
}
And let this be the class that runs our tests:
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
public class Teste {
public static void main(String[] args) {
// 1. Cria as listas.
List<String> lista1 = Arrays.asList(
"batata", "batata0", "batata000", "batata3", null, "azul 6", "azul 50", "azul 51", "batata", "azul 051", "azul 5", "laranja"
);
List<Arquivo> lista2 = lista1.stream().map(Arquivo::new).collect(Collectors.toList());
// 2. Ordena as listas.
Collections.sort(lista1, Ordenacao::comparaNomesDeArquivos);
Collections.sort(lista2, Ordenacao::comparaArquivosPorNome);
// 3. Mostra as listas ordenadas.
System.out.println(lista1);
System.out.println(lista2);
}
}
Here is the output produced:
[null, azul 5, azul 6, azul 50, azul 051, azul 51, batata, batata, batata0, batata000, batata3, laranja]
[arquivo {null}, arquivo {azul 5}, arquivo {azul 6}, arquivo {azul 50}, arquivo {azul 051}, arquivo {azul 51}, arquivo {batata}, arquivo {batata}, arquivo {batata0}, arquivo {batata000}, arquivo {batata3}, arquivo {laranja}]
See all that working on the tutorialspoint site.
>