Quero obter uma lista de arquivos em um diretório, mas quero classificá-la para que os arquivos mais antigos sejam os primeiros. Minha solução foi chamar File.listFiles e apenas recorrer a lista com base em File.lastModified, mas eu queria saber se havia uma maneira melhor.
Edit: Minha solução atual, como sugerido, é usar um comparador anônimo:
File[] files = directory.listFiles();
Arrays.sort(files, new Comparator<File>(){
public int compare(File f1, File f2)
{
return Long.valueOf(f1.lastModified()).compareTo(f2.lastModified());
} });
file.lastModified()
uma quantidade enorme de vezes. É melhor obter todas as datas primeiro e pedir depois, para que issofile.lastModified()
seja chamado apenas uma vez por arquivo.Arrays.sort(files, LastModifiedFileComparator.LASTMODIFIED_REVERSE);
Arrays.sort(files, Comparator.comparingLong(File::lastModified));
Respostas:
Eu acho que sua solução é a única maneira sensata. A única maneira de obter a lista de arquivos é usar File.listFiles () e a documentação afirma que isso não garante a ordem dos arquivos retornados. Portanto, você precisa escrever um Comparador que use File.lastModified () e passar isso, juntamente com a matriz de arquivos, para Arrays.sort () .
fonte
Isso pode ser mais rápido se você tiver muitos arquivos. Isso usa o padrão decorate-sort-undecorate para que a data da última modificação de cada arquivo seja buscada apenas uma vez, e não sempre que o algoritmo de classificação compara dois arquivos. Isso potencialmente reduz o número de chamadas de E / S de O (n log n) para O (n).
Porém, é mais código, portanto, isso só deve ser usado se você estiver preocupado principalmente com velocidade e for mensurável mais rápido na prática (o que eu não verifiquei).
fonte
Solução elegante desde o Java 8:
Ou, se você quiser em ordem decrescente, basta inverter:
fonte
files.sort(Comparator.comparingLong(File::lastModified));
ArrayList<File> files = new ArrayList<File>(Arrays.asList(directory.listFiles()))
, isso não é mais fácil do que apenasFile[] files = directory.listFiles()
.ArrayList<File>(...)
em viniciussss é necessário para obter uma lista mutável que pode ser classificada.) Encontrei esse tópico procurando uma maneira de classificar uma lista de arquivos. Acabei de adicionar esse código para que as pessoas possam simplesmente copiá-lo se tiverem listas também.Comparator
classe não tem nenhuma chamada de métodocomparingLong
O que é uma abordagem semelhante, mas sem boxe para os objetos Long:
fonte
Você também pode observar o IO do apache commons , ele possui um comparador modificado pela última vez e muitos outros utilitários interessantes para trabalhar com arquivos.
fonte
No Java 8:
Arrays.sort(files, (a, b) -> Long.compare(a.lastModified(), b.lastModified()));
fonte
Importações:
Apache Commons
Código:
fonte
Se os arquivos que você está classificando podem ser modificados ou atualizados ao mesmo tempo, a classificação está sendo executada:
Java 8+
Java 7
Ambas as soluções criam uma estrutura de dados de mapa temporária para economizar um tempo constante da última modificação para cada arquivo no diretório. O motivo pelo qual precisamos fazer isso é que, se seus arquivos estiverem sendo atualizados ou modificados enquanto sua classificação está sendo executada, seu comparador estará violando o requisito de transitividade do contrato geral da interface do comparador, pois os últimos tempos de modificação podem estar mudando durante a comparação.
Se, por outro lado, você sabe que os arquivos não serão atualizados ou modificados durante a sua classificação, poderá obter praticamente qualquer outra resposta enviada a esta pergunta, da qual sou parcial:
Java 8+ (nenhuma modificação simultânea durante a classificação)
Nota: Eu sei que você pode evitar a conversão de e para objetos File no exemplo acima, usando a API Files :: getLastModifiedTime na operação de fluxo classificado; no entanto, você precisa lidar com exceções de IO verificadas dentro do lambda, o que é sempre um problema. . Eu diria que se o desempenho é crítico o suficiente para que a tradução seja inaceitável, eu lidaria com a IOException verificada no lambda propagando-a como uma UncheckedIOException ou renunciaria à API do Files por completo e lidaria apenas com os objetos File:
fonte
fonte
Onde
listFiles
está a coleção de todos os arquivos em ArrayListfonte
Você pode tentar a goiaba Ordenação :
fonte
Você pode usar a biblioteca Apache LastModifiedFileComparator
fonte
fonte
Eu vim para este post quando estava procurando pelo mesmo problema, mas em
android
. Não digo que essa é a melhor maneira de obter arquivos classificados pela data da última modificação, mas é a maneira mais fácil que encontrei ainda.O código abaixo pode ser útil para alguém-
obrigado
fonte
for
loop, você pode ver que eulist.length-1
adotei oi >=0
que simplesmente itera na ordem inversa.Existe uma maneira muito fácil e conveniente de lidar com o problema sem nenhum comparador extra. Apenas codifique a data modificada na String com o nome do arquivo, classifique-a e depois retire-a novamente.
Use uma String de comprimento fixo 20, coloque a data modificada (longa) nela e preencha com zeros à esquerda. Em seguida, basta anexar o nome do arquivo a esta sequência:
O que acontece é isso aqui:
Nome do arquivo1: C: \ data \ file1.html Última modificação: 1532914451455 Última modificação 20 dígitos: 00000001532914451455
Nome do arquivo1: C: \ data \ file2.html Última modificação: 1532918086822 Última modificação 20 dígitos: 00000001532918086822
transforma nomes de arquivos em:
Nome do arquivo1: 00000001532914451455C: \ data \ file1.html
Nome do arquivo2: 00000001532918086822C: \ data \ file2.html
Você pode apenas classificar esta lista.
Tudo o que você precisa fazer é remover os 20 caracteres novamente mais tarde (no Java 8, você pode removê-lo para toda a matriz com apenas uma linha usando a função .replaceAll)
fonte
Existe também uma maneira completamente diferente, que pode ser ainda mais fácil, pois não lidamos com grandes números.
Em vez de classificar toda a matriz depois de recuperar todos os nomes de arquivos e datas lastModified, você pode simplesmente inserir todos os nomes de arquivos logo após recuperá-los na posição correta da lista.
Você pode fazer assim:
Depois de adicionar o objeto2 à posição 2, ele moverá o objeto3 para a posição 3.
fonte