El uso de Java Stream sum nos lo encontramos muchas veces en nuestro código de Java para sumar un conjunto de elementos. Sin embargo a veces nos olvidamos que los Streams han venido para ser usados en la plataforma Java en general y se pueden aplicar a muchas situaciones. Vamos a ver un ejemplo en el cual los apliquemos a objetos de negocio. Para ello vamos a partir de los conceptos de Factura y Linea de Factura.
Estos conceptos están relacionados y es muy habitual que la clase Factura contenga un método total que nos calcule el importe total de todas las lineas. Veamos el código:
package com.arquitecturajava.ejemplo2;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
public class Factura {
private int numero;
private String concepto;
private List<LineaFactura> lineas = new ArrayList<LineaFactura>();
public void addLinea(LineaFactura lf) {
lineas.add(lf);
}
public int getNumero() {
return numero;
}
public void setNumero(int numero) {
this.numero = numero;
}
public String getConcepto() {
return concepto;
}
public void setConcepto(String concepto) {
this.concepto = concepto;
}
public List<LineaFactura> getLineas() {
return lineas;
}
public void setLineas(List<LineaFactura> lineas) {
this.lineas = lineas;
}
public double total() {
double total = 0;
for (LineaFactura l : lineas) {
total += l.getImporte();
}
return total;
}
}
package com.arquitecturajava.ejemplo1;
public class LineaFactura {
private int numero;
private String concepto;
private double importe;
public int getNumero() {
return numero;
}
public void setNumero(int numero) {
this.numero = numero;
}
public String getConcepto() {
return concepto;
}
public void setConcepto(String concepto) {
this.concepto = concepto;
}
public double getImporte() {
return importe;
}
public void setImporte(double importe) {
this.importe = importe;
}
public LineaFactura(int numero, String concepto, double importe) {
super();
this.numero = numero;
this.concepto = concepto;
this.importe = importe;
}
}
Java Stream Sum
El código es correcto.¿Ahora bien podemos construir algo más flexible?. En muchas ocasiones cuando realizamos una compra y obtenemos la factura nos gusta mirar en que conceptos nos hemos gastado más dinero. Así pues podríamos usar Java Overload y sobrecargar el método total de la Factura para calcular el total apoyándonos en un Predicate.
public double total() {
double total = 0;
for (LineaFactura l : lineas) {
total += l.getImporte();
}
return total;
}
public double total(Predicate<LineaFactura> plinea) {
return lineas.stream().filter(plinea).mapToDouble(l -> l.getImporte()).sum();
}
Así ganamos en flexibilidad:
Veamos un programa main con el cual obtener tanto el total como el total de un producto concreto.
package com.arquitecturajava.ejemplo2;
public class Principal {
public static void main(String[] args) {
Factura f= new Factura();
f.setNumero(1);
f.setConcepto("miscompras");
f.addLinea(new LineaFactura(1, "turron", 3));
f.addLinea(new LineaFactura(1, "turron", 3));
f.addLinea(new LineaFactura(1, "turron", 3));
f.addLinea(new LineaFactura(1, "jamon", 5));
f.addLinea(new LineaFactura(1, "jamon", 4));
System.out.println(f.total());
System.out.println(f.total(l->l.getConcepto().equals("turron")));
}
}
Acabamos de calcular el gasto total y el que hemos hecho en turrón y vemos el resultado en la consola.
Otros artículos relacionados: