usar - En Java, ¿cuáles son las ventajas de las transmisiones sobre los bucles?
for loop java español (5)
-
Se dio cuenta incorrectamente: las operaciones paralelas usan
Stream
, noOptional
. -
Puede definir métodos que funcionen con flujos: tomarlos como parámetros, devolverlos, etc. No puede definir un método que tome un ciclo como parámetro. Esto permite una operación de transmisión complicada una vez y usarla muchas veces. Tenga en cuenta que Java tiene un inconveniente aquí: sus métodos deben llamarse como
someMethod(stream)
en lugar de stream''sstream.someMethod()
, por lo que mezclarlos complica la lectura: intente ver el orden de las operaciones enmyMethod2(myMethod(stream.transform(...)).filter(...))
Muchos otros lenguajes (C #, Kotlin, Scala, etc.) permiten alguna forma de "métodos de extensión".
-
Incluso cuando solo necesita operaciones secuenciales y no desea reutilizarlas, de modo que pueda usar secuencias o bucles, las operaciones simples en las secuencias pueden corresponder a cambios bastante complejos en los bucles.
Me lo preguntaron en una entrevista y no estoy convencido de haber dado la mejor respuesta que podría tener. Mencioné que puede hacer una búsqueda paralela y que los valores nulos se manejaron de alguna manera que no podía recordar. Ahora me doy cuenta de que estaba pensando en los opcionales. ¿Que me estoy perdiendo aqui? Afirman que es un código mejor o más conciso, pero no estoy seguro de estar de acuerdo.
Considerando cuán sucintamente fue respondida, parece que esta no era una pregunta demasiado amplia después de todo.
Si están haciendo esta pregunta en las entrevistas, y claramente lo están haciendo, ¿para qué serviría desglosarla además de hacer que sea más difícil encontrar una respuesta? Quiero decir, ¿qué estás buscando? Podría desglosar la pregunta y responder a todas las subpreguntas, pero luego crear una pregunta principal con enlaces a todas las preguntas secundarias ... aunque parece bastante tonto. Mientras estamos en eso, por favor dame un ejemplo de una pregunta menos amplia. No sé cómo hacer solo una parte de esta pregunta y aún así obtener una respuesta significativa. Podría hacer exactamente la misma pregunta de una manera diferente. Por ejemplo, podría preguntar "¿Para qué sirven las transmisiones?" o "¿Cuándo usaría una secuencia en lugar de un bucle for?" o "¿Por qué molestarse con las transmisiones en lugar de los bucles?" Sin embargo, todas estas son exactamente la misma pregunta.
... o se considera demasiado amplio porque alguien dio una respuesta multipunto realmente larga? Francamente, cualquiera que lo sepa podría hacer eso con prácticamente cualquier pregunta. Si usted es uno de los autores de la JVM, por ejemplo, probablemente podría hablar de bucles durante todo el día cuando la mayoría de nosotros no podría.
"Edite la pregunta para limitarla a un problema específico con suficientes detalles para identificar una respuesta adecuada. Evite hacer varias preguntas distintas a la vez. Consulte la página Cómo hacer para obtener ayuda para aclarar esta pregunta".
Como se señala a continuación, se ha dado una respuesta adecuada que demuestra que hay una y que es lo suficientemente fácil de proporcionar.
Dejando de lado la diversión sintáctica, los Streams están diseñados para trabajar con conjuntos de datos potencialmente infinitamente grandes, mientras que los arrays, las Colecciones y casi todas las clases de Java SE que implementan Iterable están completamente en la memoria.
Una desventaja de un Stream es que los filtros, mapeos, etc., no pueden arrojar excepciones marcadas. Esto hace que Stream sea una mala elección para, por ejemplo, operaciones de E / S intermedias.
Diría que su
paralelización
es tan fácil de usar.
Intenta iterar sobre millones de entradas en paralelo con un bucle for.
Vamos a muchos cpus, no más rápido;
así que cuanto más fácil sea correr en paralelo, mejor, y con
Stream
s esto es muy fácil.
Lo que me gusta mucho es la verbosidad que ofrecen. Toma poco tiempo entender lo que realmente hacen y producen en lugar de cómo lo hacen.
Es interesante que la pregunta de la entrevista pregunte sobre las ventajas, sin preguntar sobre las desventajas, ya que las hay.
Las transmisiones son un estilo más declarativo . O un estilo más expresivo . Puede considerarse mejor declarar su intención en el código, que describir cómo se hace:
return people
.filter( p -> p.age() < 19)
.collect(toList());
... dice claramente que está filtrando elementos coincidentes de una lista, mientras que:
List<Person> filtered = new ArrayList<>();
for(Person p : people) {
if(p.age() < 19) {
filtered.add(p);
}
}
return filtered;
Dice "estoy haciendo un bucle". El propósito del bucle está enterrado más profundamente en la lógica.
Las corrientes son a menudo más bajas . El mismo ejemplo muestra esto. Terser no siempre es mejor, pero si puedes ser conciso y expresivo al mismo tiempo, mucho mejor.
Las corrientes tienen una fuerte afinidad con las funciones . Java 8 presenta lambdas e interfaces funcionales, que abren toda una caja de juguetes de técnicas poderosas. Las secuencias proporcionan la forma más conveniente y natural de aplicar funciones a secuencias de objetos.
Las corrientes alientan menos mutabilidad . Esto está relacionado con el aspecto de la programación funcional: el tipo de programas que escribe utilizando secuencias tiende a ser el tipo de programas en los que no modifica objetos.
Las corrientes fomentan un acoplamiento más suelto . Su código de manejo de flujo no necesita conocer la fuente del flujo, o su eventual método de terminación.
Las transmisiones pueden expresar sucintamente un comportamiento bastante sofisticado . Por ejemplo:
stream.filter(myfilter).findFirst();
Puede parecer a primera vista como si filtrara todo el flujo, luego devuelve el primer elemento.
Pero, de hecho,
findFirst()
impulsa toda la operación, por lo que se detiene de manera eficiente después de encontrar un elemento.
Las corrientes brindan margen para futuras ganancias de eficiencia . Algunas personas han evaluado y encontrado que las secuencias de un solo subproceso de las listas o matrices en memoria pueden ser más lentas que el bucle equivalente. Esto es plausible porque hay más objetos y gastos generales en juego.
Pero las corrientes escalan. Además del soporte incorporado de Java para las operaciones de flujo en paralelo, hay algunas bibliotecas para reducir el mapa distribuido usando Streams como API, porque el modelo se ajusta.
Desventajas?
Rendimiento
: un bucle
for
través de una matriz es extremadamente liviano tanto en términos de almacenamiento dinámico como de uso de CPU.
Si la velocidad bruta y el ahorro de memoria son una prioridad, el uso de una transmisión es peor.
Familiaridad . El mundo está lleno de programadores de procedimientos experimentados, de muchos orígenes lingüísticos, para quienes los bucles son familiares y las transmisiones son novedosas. En algunos entornos, desea escribir código que sea familiar para ese tipo de persona.
Sobrecarga cognitiva . Debido a su naturaleza declarativa y al aumento de la abstracción de lo que sucede debajo, es posible que deba crear un nuevo modelo mental de cómo el código se relaciona con la ejecución. En realidad, solo necesita hacer esto cuando las cosas salen mal, o si necesita analizar profundamente el rendimiento o los errores sutiles. Cuando "simplemente funciona", simplemente funciona.
Los depuradores están mejorando, pero incluso ahora, cuando está recorriendo el código de flujo en un depurador, puede ser un trabajo más duro que el bucle equivalente, porque un bucle simple está muy cerca de las variables y las ubicaciones de código con las que trabaja un depurador tradicional.
Realiza un bucle sobre una secuencia (matriz, colección, entrada, ...) porque desea aplicar alguna función a los elementos de la secuencia.
Las secuencias le permiten componer funciones en elementos de secuencia y le permiten implementar las funciones más comunes (por ejemplo, mapeo, filtrado, búsqueda, clasificación, recopilación, ...) independientemente de un caso concreto.
Por lo tanto, dada una tarea de bucle en la mayoría de los casos, puede expresarla con menos código usando Streams, es decir, gana legibilidad .