Antes de la funcion forEach, todos los iteradores en JAVA eran activos es decir, involucraban un ciclo for o un while que recorría la colección de datos hasta cumplir con cierta condición. Es decir que recorrer una colección se vería así;
List<String> names = new LinkedList<String>();
for (String name : names)
System.out.println(name);
Con la introducción de forEach como una función en la interfaz Iterable, todas las clases que implementen iterable tiene añadida la función forEach y el siclo anterior se podría simplificar así:
names.forEach(name -> System.out.println(name));
como puedes ver es una sola linea de código y lo mas inusual es este símbolo -> lo que nos indica estamos lidiando con una expresión Lambda, si no sabes nada de expresiones lambda ingresa a este link que tiene un tutorial a prueba de... digamos que for dummies (https://programmingbabel.blogspot.com/2017/09/lambda-expressions-java.html).
La expresión lambda en paréntesis quiere decir que para la variable name ejecute una impresión de linea del valor de name. Como puedes ver se pueden realizar gran cantidad de operaciones sobre todos los miembros de una colección solo con el llamado de este método.
Pero llevemos esto un paso mas adelante, con la llegada de forEach, también vino una nueva clase llamada Stream(Corriente), La idea detrás de Stream no es copiar ni almacenar una colección para eso ya existe la colección, la idea es crear una corriente por la que corren todos los miembros de la colección y sobre los que voy a realizar una operación. para obtener el stream de una colección solo se debe llamar al método .stream() ya tendrás acceso a la corriente de datos proveniente de la colección.
List<String> names = new LinkedList<>();
long count = names.stream().filter(name -> name.startsWith("A")).count();
como puedes ver con .stream() ya tienes el stream, ahora sobre stream puedes realizar varias operaciones en este caso haremos un filtro de todos los elementos que cumplan con la expresión Lambda, name -> name.startsWith("A"). y como el resultado es otro stream podemos llamar otra función de stream que cuente el numero de elementos en el stream resultante.
Ahora te preguntaras porque usar stream si hacerlo con el método clásico seria mas claro.
long count = 0;
for (String name : names)
{
if (name.startsWith("A"))
++count;
}
Bueno hay un buen motivo, paralelismo ejecutar este for implica que secuencial mente vas a recorrer cal colección un elemento tras otro, ahora con stream le puedes decir que haga lo mismo pero con múltiples hilos, stream se encargara de partir el arreglo en varios pedazos asignar cada parte a un hilo y obtener el resultado mucho mas rápido.
Para hacer esta gracia no llamaremos a stream sino a parallelStream(). el ejemplo anterior se vera así
names.parallelStream().filter(name -> name.startsWith("A")).count();
y ya!, con este llamado cada operación sobre el stream se ejecutara con hilos paralelos, es decir que el filtro lo harán varios hilos.
Para ilustrar esta funcionalidad imagina que tienes el deber de contar todos los números mayores de 100 de una colección de diez millones de números, esto lo puedes hacer de 3 formas.
public static void main(String[] args) {
Random r= new Random();
List<Integer> numeros=new ArrayList<>();
for(int i=0;i<10000000;i++){
numeros.add(r.nextInt());
}
// metodo 1
long start = System.currentTimeMillis();
long count = 0;
for (Integer numero: numeros)
{
if (numero>100)
++count;
}
System.out.println(count);
System.out.println("prueba 1 tiempo "System.currentTimeMillis() - start);
//metodo 2
start = System.currentTimeMillis();
System.out.println(numeros.parallelStream().filter(numeros-> numeros>100).count());
System.out.println("prueba 1 tiempo "System.currentTimeMillis() - start);
//metodo 3
start = System.currentTimeMillis();
System.out.println(numeros.parallelStream().filter(numeros-> numeros>100).count());
System.out.println("prueba 1 tiempo "System.currentTimeMillis() - start);}
verifica los tiempos, la eficiencia cambiara dependiendo de la arquitectura de tu maquina, ¿se demoro menos con parallelStream?, ¿donde mas crees que puedas usar stream, forEach y paralelismo?.
si quieres saber mas de Paralelismo este post tiene lo que necesitas (https://programmingbabel.blogspot.com/2017/09/paralelismo-en-java-executors_9.html) y algo mas avanzado (https://programmingbabel.blogspot.com/2017/09/el-fork-join-framework-java.html)
Comentarios
Publicar un comentario