List.toEnumarable()

 As estruturas de dados fornecidos pelo java, se usadas da forma correta são muito boas. Juntando com o poder dos generics e outras malandragens provenientes de nossa imaginação fértil, podemos trabalhar com listas de forma muito flexível e dinâmica.

Quando implementei meu tcc (um sistema desktop para uma empresa de Confecções) não sei por que, vi a necessidade de criar um Framework para me ajudar nesta árdua tarefa e uma das funcionalidades era justamente uma classe para manipular listas de uma forma que achei bem bacana.

Neste sistema, utilizei o JPA. Optei por não usar o Hibernate por não conhecer e também porque queria mesmo ter trabalho.

Utilizando o Netbeans e o JPA, temos a opção de criar “entidades do banco de dados”. Isto é muito útil pois será gerado inteiramente de “grátis” , as classes com todos os atributos da tabela e seus relacionamentos. Daí pra frente, é só separar os homens dos meninos e fazer as coisas segundo os mandamentos de implementação de equals() e hashCode().

Criei uma classe que herda de List, chamada hummm…List. Assim, dentro das minhas classes de dados, eu troco a declaração do pacote List do java, apontando para o meu pacote.

Utilizando o engine do JPA, temos muito a ganhar. Como exemplo, temos as querys que são geradas automaticamente, chamadas de namedquerys, que são pré-compiladas quando o contexto é iniciado, nos dando aumento de performance quando executadas. Também, é mantido um contexto onde ficam guardadas as refências  de objetos que já estão gerenciados (vieram do banco e estão em memória) diminuindo a quantidade de acessos ao banco, dependendo de como está a arquitetura do seu sistema.

Depois de trazidos do banco para a memória, uso um tipo de Comparator para coisas como executar um where, ordenação da lista por campos especificos de cada objeto, tirar uma media de valores ou saber quem é maior ou menor.

Abaixo, coloco as classes de dados.


<code>//imports *
import orquestralist.list.List;</code>

/**
*
* @author marciliosouza
*/
@Entity
@Table(name = "cliente")
@NamedQueries({
@NamedQuery(name = "Cliente.findAll", query = "SELECT c FROM Cliente c"),
@NamedQuery(name = "Cliente.findByIdcliente", query = "SELECT c FROM Cliente c WHERE c.idcliente = :idcliente"),
@NamedQuery(name = "Cliente.findByCnpjcpf", query = "SELECT c FROM Cliente c WHERE c.cnpjcpf = :cnpjcpf"),
@NamedQuery(name = "Cliente.findByIerg", query = "SELECT c FROM Cliente c WHERE c.ierg = :ierg"),
@NamedQuery(name = "Cliente.findByDatacad", query = "SELECT c FROM Cliente c WHERE c.datacad = :datacad"),
@NamedQuery(name = "Cliente.findByLimite", query = "SELECT c FROM Cliente c WHERE c.limite = :limite")})
public class Cliente implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "idcliente")
private Integer idcliente;
@Basic(optional = false)
@Column(name = "cnpjcpf")
private String cnpjcpf;
@Basic(optional = false)
@Column(name = "ierg")
private String ierg;
@Basic(optional = false)
@Column(name = "datacad")
@Temporal(TemporalType.TIMESTAMP)
private Date datacad;
@Basic(optional = false)
@Column(name = "limite")
private long limite;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "cliente")
private List vendaList;

public Cliente() {
}

//gets sets
}

//imports...

/**
*
* @author marciliosouza
*/
@Entity
@Table(name = "produto")
@NamedQueries({
@NamedQuery(name = "Produto.findAll", query = "SELECT p FROM Produto p"),
@NamedQuery(name = "Produto.findByIdproduto", query = "SELECT p FROM Produto p WHERE p.idproduto = :idproduto"),
@NamedQuery(name = "Produto.findByDescricao", query = "SELECT p FROM Produto p WHERE p.descricao = :descricao")})
public class Produto implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "idproduto")
private Integer idproduto;
@Basic(optional = false)
@Column(name = "descricao")
private String descricao;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "produto")
private List vendaitemList;

public Produto() {
}
}

//imports

/**
*
* @author marciliosouza
*/
@Entity
@Table(name = "vendaitem")
@NamedQueries({
@NamedQuery(name = "Vendaitem.findAll", query = "SELECT v FROM Vendaitem v"),
@NamedQuery(name = "Vendaitem.findByIdvendaitem", query = "SELECT v FROM Vendaitem v WHERE v.idvendaitem = :idvendaitem"),
@NamedQuery(name = "Vendaitem.findByQtde", query = "SELECT v FROM Vendaitem v WHERE v.qtde = :qtde"),
@NamedQuery(name = "Vendaitem.findByPrecovenda", query = "SELECT v FROM Vendaitem v WHERE v.precovenda = :precovenda")})
public class Vendaitem implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "idvendaitem")
private Integer idvendaitem;
@Basic(optional = false)
@Column(name = "qtde")
private int qtde;
@Basic(optional = false)
@Column(name = "precovenda")
private BigDecimal precovenda;
@JoinColumn(name = "idvendaitem", referencedColumnName = "idvenda", insertable = false, updatable = false)
@OneToOne(optional = false)
private Venda venda;
@JoinColumn(name = "produto", referencedColumnName = "idproduto")
@ManyToOne(optional = false)
private Produto produto;

public Vendaitem() {
}

//gets e sets

}

//imports
import orquestralist.list.List;

/**
*
* @author marciliosouza
*/
@Entity
@Table(name = "venda")
@NamedQueries({
@NamedQuery(name = "Venda.findAll", query = "SELECT v FROM Venda v"),
@NamedQuery(name = "Venda.findByIdvenda", query = "SELECT v FROM Venda v WHERE v.idvenda = :idvenda"),
@NamedQuery(name = "Venda.findByData", query = "SELECT v FROM Venda v WHERE v.data = :data"),
@NamedQuery(name = "Venda.findByVlrtotal", query = "SELECT v FROM Venda v WHERE v.vlrtotal = :vlrtotal")})
public class Venda implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "idvenda")
private Integer idvenda;
@Basic(optional = false)
@Column(name = "data")
@Temporal(TemporalType.TIMESTAMP)
private Date data;
@Basic(optional = false)
@Column(name = "vlrtotal")
private BigDecimal vlrtotal;
@JoinColumn(name = "cliente", referencedColumnName = "idcliente")
@ManyToOne(optional = false)
private Cliente cliente;
@OneToOne(cascade = CascadeType.ALL, mappedBy = "venda")
private List vendaitem;

public Venda() {
}

}

Agora, alguns usos Lista:

public List<Venda> example(Cliente cli)
    {
        return cli.getVendaList().where(new ICompare<Venda>() {

            public boolean compare(Venda t) {
                return t.getVlrtotal().compareTo(BigDecimal.valueOf(500)) > 0;
            }
        });
    }


</pre>
cli.getVendaList().get(0)
                .getVendaitem().where(new ICompare<Vendaitem>() {            public boolean compare(Vendaitem t) {
                return t.getProduto().getDescricao().equals("Produto1");
            }
        });

[sourcecode]

[sourcecode language="java"]
cli.getVendaList().distinct();
[sourcecode]

Obtém o total dos itens do Pedido

[sourcecode language="java"]

cli.getVendaList().get(0).getVendaitem()
                .sum(new IGetValue<Vendaitem>() {

            public Number getValue(Vendaitem t) {
                return t.getPrecovenda().multiply(BigDecimal.valueOf(t.getQtde()));
            }
        });

Analisando a classe Cliente, vemos que ela tem um List<Venda>.
Na mesma classe, trocamos a declaralção do pacote para
orquestra.list, e utilizamos a classe List "with" aditivos.
Estes metodos utilitários (where por exemplo) sempre retorna uma lista
tipada mas nunca altera a lista Original.
Para o metodo where, implementamos o metodo compare e o mesmo será
executado para todos os objetos da lista, retornando uma nova lista
com os objetos que retornaram true no metodo compare().
Há outros usos, como tirar uma média como o exemplo abaixo. A interface
IGetValue<Venda> retornará o campo que será usado para o cálculo.

Outro ponto importante aqui é o uso de Generics que nos permite
especificar diretamente os campos que queremos sem precisarmos de
conversão, usar strings (que é o caso de muitos Frameworks) ou
Annotations.
Retorna a media de valores de vendas para o cliente.

    public Number mediaVlrVenda(Cliente cli)
    {
        return cli.getVendaList().avg(new IGetValue<Venda>() {
            public Number getValue(Venda t) {
                return t.getVlrtotal();
            }
        });
    }

Retorna a venda com maior valor.

    public Number mediaVlrVenda(Cliente cli)
    {
        return cli.getVendaList().max(new Comparator<Venda>() {

            public int compare(Venda o1, Venda o2) {
                return o1.getVlrtotal().compareTo(o2.getVlrtotal());
            }
        });
}

Executa um metodo em cada objeto da Lista de itens que esta dentro da

Lista de Vendas e depois a ordena por data de emissão:


        list.forEach(new Action<Venda>() {

            public void action(Venda t) {

                t.getVendaitem().forEach(new Action<Vendaitem>() {
                    public void action(Vendaitem t) {
                        t.setPrecovenda(BigDecimal.ZERO);
                    }
                });
            }
        }).orderBy(new Comparator<Venda>() {

            public int compare(Venda o1, Venda o2) {
                return o1.getData().compareTo(o2.getData());
            }
        });

Resumindo, o que pretendo com este post, é tentar mostrar o quanto
listas podem ser extensíveis. Aqui, mostrei poucos exemplos, mas podemos
implementar diversos outros metódos dentro da List para facilitar sua
manipulação.

2 Respostas para “List.toEnumarable()”

  1. Alejandro Disse:

    Bom, muito bom… é eu escuto vc falando disso todos os dias aqui na mesa do lado. rsrsrs

    Blog ta legal.. ta começando com artigos de qualidade.

    Parabén.

  2. Caio Disse:

    Mto bem estruturado!
    Pra quem curte arroz feijão e java… prato cheio!

    Não esquece de colocar Tag’s e dxa no Google!
    Ainda que haja palhaço, não há show sem público !

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Sair / Alterar )

Imagem do Twitter

You are commenting using your Twitter account. Sair / Alterar )

Foto do Facebook

You are commenting using your Facebook account. Sair / Alterar )

Connecting to %s


Seguir

Obtenha todo post novo entregue na sua caixa de entrada.