How do I manipulate the order of the files in an Arraylist?

Asked

Viewed 383 times

1

I am developing a program, in which part of the processes requires me to take the numbering of the last file listed within a ArrayList.

My doubt is this, when mine ArrayList starts adding the files listed in the directory it adds the files correctly in the sequence of items within the array, but when it arrives in file number 9 the array replaces the first file of the sequence by 10, and only recognizes the number 1 of the complete 10. How do I make the array recognize 10 as the number that comes after 9?

  • is probably treating this number as a string, and 1 comes before 9.

  • @neto Add the code you’ve already developed.

2 answers

1


Solution idea

First, you have to see that the file names have the format prefix + suffix, where the suffix is a number. With this, we can arrange your files, first by prefix and then by suffix.

Implementation of the solution

Therefore, you will need a function that knows how to sort the filenames correctly. Here’s a:

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:

  1. As any comparison function in Java, it has as its 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 the two are equal.

  2. For the sake of optimization, it is initially verified that the Stringare identical, and in this case it is known that they are equal. This case is determined with the Objects.equals(Object, Object). This check also works if both Strings are null.

  3. Case one of Strings be null (and it is already known that only one of them could be because the case where the two are treated in step 2), then considers that null precedes anything else, returning -1 or 1 in these cases.

  4. To separate the prefix from the suffix, this function traverses each string back-to-front in order to determine them for for each.

  5. If the prefix of Strings is different, so the sort is given by the prefix.

  6. Since the prefixes are equal, then the ordering is given by the suffix, which is a number.

  7. Prefixes and suffixes being equal, which can happen if you compare batatinha123 with batatinha0123, that is, when the difference is only given by the zeros to the left of the number, then it uses the standard comparison form.

Knowing how to compare the Strings, you can mount a function to compare files. I don’t know exactly how you are repressing a file. If it is directly by their names, then you can ignore that part. Otherwise, assuming the method getFilename() whatever determines the file name, 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);
}

Ah, and let’s assume that the above methods are in a class called Ordenacao.

Finally, you can order your List<Arquivo> using the method sort(List<T>, Comparator<? super T>):

Collections.sort(suaArrayList, Ordenacao::comparaArquivosPorNome);

If you are using only one List<String> instead of List<Arquivo>, use this:

Collections.sort(suaArrayList, Ordenacao::comparaNomesDeArquivos);

Testing

To test all this, let’s assume that this is the class Arquivo:

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 that this is the class that makes 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 this working on the tutorialspoint site. (Do the test by clicking the compile button and then the run button.)

0

Once I had to sort my list by date, and the sqlite did not treat as date, which I did:

@Override
    public int compareTo(Call another) {

        SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
        java.util.Date dateComparer, dateActual;

        try {
            dateActual = sdf.parse(this.getData());
            dateComparer = sdf.parse(another.getData());

            if (dateActual.before(dateComparer)) {
                return Constants.SUCESS;
            }
            if (dateActual.after(dateComparer)) {
                return Constants.ERROR;
            }

        } catch (ParseException e) {
            e.printStackTrace();
        }

        return 0;
    }

Then I ordered my list on the call:

Collections.sort(calls)

So I guess you’d just have to convert the String for whole and compare.

  • 1

    The problem is that I have not only numbers, I have words that comes before the numbering, which is the name of the file, I tried to remove the words with replaceAll, and play in a whole type doing a conversion, but it keeps giving improper format error...

Browser other questions tagged

You are not signed in. Login or sign up in order to post.