Ordenar saída de acordo txt(java)

Olá senhores.

Supondo a seguinte classe:

public class teste {
    Integer codigo;
    String nome;

    public Integer getCodigo() {
        return codigo;
    }

    public void setCodigo(Integer codigo) {
        this.codigo = codigo;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        if(nome.isEmpty())
            this.nome = "Vazio";
        else
            this.nome = nome;
    }
}

Após instancia e dar os set’s gostaria de ler um arquivo TXT, onde o mesmo conteria a ordem de impressão dos campo. Portanto se o txt tivesse assim

codigo
nome

1\tLucas
Na tela deveria demonstrar primeiramente o código e depois o nome. Caso esteja assim:

nome
codigo

Lucas\t1

Primeiramente deveria ser mostrado o nome e depois o código. Caso tenha algum campo que não exista devera imprimir uma coluna vazia no meio ex:

codigo
endereco
nome

1\t\tLucas

Agradeceria muito se alguém pudesse me ajudar.

@montero

Esta muito confuso seu tópico, então vou usar suposições.

  • Suponho que esteja usando uma grid (JTable do Swing) para listar os dados do txt.
    R: Simples, use AbstractTableModel se quer fazer do jeito certo, ou DefaultTableModel se quizer fazer da forma preguiçosa e simples.

Isso explica como usar AbstractTableModel
http://www.botecodigital.info/java/criando-um-model-para-um-jtable-com-abstracttablemodel/

E isso explica por que usar Abstract ao invés do Default

Para gravar dados em um txt é muito simples. Sempre uso uma classe controladora.
Montei esta app, ela cadastra, altera, exclui e lista dados com base na sua classe “Teste”.
Preste bastante atenção nos métodos, possui bastante coisa que pode seu útil para vc.
Qualquer duvida entre em contato

TopicoDaSuposicao.rar (59,9 KB)

Eu não te dei a resposta a seu problema, o sistema que montei não irá listar na ordem código, nome, endereço. De uma olhada, e tente entende-lo pois é muito simples de implementar o que vc precisa a partir disso.

Bom dia, correto mas não era exatamente isso que eu queria sobre isso esta tranquilo. Vou tentar exemplificar melhor dado a classe que demonstrei la em cima. Suponha que já tenha sido dados os set’s em ambos campos.

teste obj = new teste(); //eu sei não pus o método construtor na classe mas isso é o de menos
obj.setCodigo(1);
obj.setNome("Lucas");

Visto que não importa da onde as informações 1 e Lucas viera, o que importa é que elas já estão no objeto “obj”. se eu fosse largar estas informações no console eu faria:

system.out.println(getCodigo()+"\t"+getNome());

isto me daria a saída nesta ordem CODIGO\tNOME ficando 1\tLucas. Porem se eu quisesse por o nome antes do código teria que fazer:

system.out.println(getNome()+"\t"+getCodigo());

O que eu gostaria de fazer é definir a ordem dos campos através de um arquivo texto, por exemplo. Se no arquivo texto eu botasse:

Codigo
Nome

No print do console sairia o código anterior ao nome como no primeiro exemplo, porem se eu colocasse no arquivo texto:

Nome
Codigo

teríamos a saída no console de acordo segundo exemplo. Porem caso eu colocasse no arquivo texto um campo que não existe no objeto ele botaria nesta posição um espaço exmplo:

Arquivo texto:
Nome
Endereco
Codigo

saida no console ficaria(usando tab como separador):

Lucas\t\t1

outro exemplo

Arquivo texto:
Nome
Codigo
Endereco

saida no console ficaria(usando tab como separador):

Lucas\t1\t

Acredito que agora ficou claro, qualquer duvida por gentileza informar.

Entendi, neste caso vc precisa parametrizar, para isso, vc precisa criar um outro controlador de txt, ele gerará um arquivo que possui parâmetros do seu sistema. Ali vc definirá a ordem das coisas, para preenchimento da grid e/ou pront, use um if.

Nunca usei mas acredito que seja possível armazenar os métodos em um array, desta forma executa-lo na ordem desejada sem if, mas ae cabe a vc pesquisar, ou alguém mais experiente responde-lo.

Cheguei a pensar em fazer com loop e if’s mas achei esta alternativa muito exótica(para não dizer gambiarra kkk), gostaria de achar uma solução mais limpa , pois imagina em uma tebela de 200 campos como isso ficaria, mas não achei nada até então.

Uma forma de se fazer isso é criando um Map com o nome da propriedade que você quer para o método que deve ser chamado. Quando chamar seu método para imprimir, vc usa esse map para chamar o código.

Você tá usando java 8? Dá uma lida em method references.

1 curtida

Cheguei a ver esses Map. Porem não compreendi direito como utilizar nesta minha situação, tens como fazer um pequeno exemplo? Sim, é o java 8.

No fim das contas usar Maps é só uma forma mais “elegante” do que usar ifs. Como elegancia é subjetiva, use o if se ficar mais confortável.

Como um exemplo, imagine que você quer retornar o código rgb de uma cor, baseada no seu nome.
Você pode escrever:

String getCodigoCor(String cor) {
    if (cor.equals("azul")) return "#0000FF";
    if (cor.equals("verde")) return "#00FF00";
    if (cor.equals("vermelho")) return "#FF0000";
    return "???";
  }

Que quebra algumas convençoes de código por aí, mas aí com algumas chaves fica totalmente razoável.
Com mapas, você faria assim:

String getCodigoCor2(String cor) {
    Map<String, String> cores = new HashMap<>();
    cores.put("azul", "#0000FF");
    cores.put("verde", "#00FF00");
    cores.put("vermelho", "#FF0000");
    return  cores.getOrDefault(cor, "???");
  }

Nessa versao, você tem um código mais curto (considerando as chaves da primeira versao que tive preguiça de colocar) e o mapeamento fica mais claro.
Pode se argumentar que é mais fácil adicionar novos casos na segunda versao, mas entramos no subjetivo de novo.

No seu caso porém, você nao quer mapear um valor, mas a chamada de um método. Entao precisa criar um Map de String (o nome no arquivo) para um método (getNome(), getCodigo(), etc).
No java 8 fica mais fácil fazer isso pois existe as referências de método (e a interface Supplier). Entao você pode criar um método assim:

      String getValor(String campo) {
          Map<String, Supplier<?>> campos = new HashMap<>();
          campos.put("nome", this::getNome);
          campos.put("codigo", this::getCodigo);
          return  campos.getOrDefault(nome, () -> "???").get().toString();
        }

Estou dizendo que no meu mapa terei Supplier como valor. Supplier é uma funçao que retorna um valor sem precisar receber argumentos. O ? na assinatura é que o tipo pode variar (String, Integer).

O valor “this:getNome” é uma referência ao método getNome dessa classe. Aquele .get() no final do método é a mesma coisa de executar diretamente o getNome (ou getCodigo).
Por último, na última linha, eu forneço um Supplier default, caso nao exista o campo no mapa. Nesse caso você pode retornar a string vazia que mencionou.

1 curtida

Muito boa resposta, irei testar esta utilização assim que possível. Muito obrigado!!

Boa tarde.

Funcionou 100% unica alteração que precisei fazer foi em:

return  campos.getOrDefault(nome, () -> "???").get().toString();

para:

 return  campos.getOrDefault(campo, () -> "???").get().toString();

Muito obrigado!!

Somente fiquei com uma duvida, porque neste caso tem que ser this::getNome e não this.getnome()?

tentei fazer o processo inverso também se exito ou seja enviar o campo e ele chamar o setCodigo ou setNome.