{"id":19720282,"url":"https://github.com/cristianbonilla/functional-programming","last_synced_at":"2025-08-12T00:06:48.945Z","repository":{"id":122030092,"uuid":"180048415","full_name":"CristianBonilla/functional-programming","owner":"CristianBonilla","description":"A partir de la versión 8 de java la programación funcional se aplica con un estilo idiomático. Para entender la programación funcional es necesario volver a versiones anteriores.","archived":false,"fork":false,"pushed_at":"2019-04-11T01:52:55.000Z","size":3617,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-27T23:38:02.260Z","etag":null,"topics":["functional-programming","java-8","java-8-lambda","oriented-object-programming","pluralsight","streams-api"],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"epl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/CristianBonilla.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-04-08T01:41:40.000Z","updated_at":"2023-03-28T12:14:10.000Z","dependencies_parsed_at":null,"dependency_job_id":"5941641a-16aa-45b3-b124-78b4a0838a88","html_url":"https://github.com/CristianBonilla/functional-programming","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/CristianBonilla/functional-programming","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CristianBonilla%2Ffunctional-programming","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CristianBonilla%2Ffunctional-programming/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CristianBonilla%2Ffunctional-programming/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CristianBonilla%2Ffunctional-programming/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CristianBonilla","download_url":"https://codeload.github.com/CristianBonilla/functional-programming/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CristianBonilla%2Ffunctional-programming/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":269976794,"owners_count":24506467,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-11T02:00:10.019Z","response_time":75,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["functional-programming","java-8","java-8-lambda","oriented-object-programming","pluralsight","streams-api"],"created_at":"2024-11-11T23:11:00.656Z","updated_at":"2025-08-12T00:06:48.922Z","avatar_url":"https://github.com/CristianBonilla.png","language":"Java","readme":"# Programación funcional en java\n\nUna de las características de la programación funcional está en que funcionan como valores. Esto significa tres cosas.\n\n* **Almacenar funciones en variables.**\n* **Pasar funciones en los parámetros.**\n* **Funciones de retorno de otras funciones.**\n\nPara entender la programación funcional es necesario volver a las versiones anteriores cuando la programación orientada a objetos en java 6 era muy crucial, siendo que los objetos y tipos primitivos son valores, podemos pasar objetos que tienen métodos, pero no métodos por sí mismos, en java 8 o posterior elimina está restricción.\n\n## Desarrollo de un motor de cálculo\n\nComienza con las ventas previstas, los costos fijos y los costos incrementales. El motor combina estos para predecir el beneficio de un año. Las cantidades que nos interesan están definidas por un valor esperado para cada mes de enero a diciembre. Las ventas varían según la temporada, por la que el departamento de operaciones minoristas ha especificado una predicción diferente para cada mes. Los costos incrementales son aproximados por esta línea. Los costos fijos son constantes. El motor restará ambos costos de las ventas para predecir ganancias.\n\n* Ventas previstas.\n* Costos fijos.\n* Costos incrementales.\n\n## Expresiones lambda\n\nSi se quieren modelar costos incrementales en función del tiempo. Hay un tipo estándar en Java 8 para una función desde int a double. Para crear uno con una expresión lambda se declara el parámetro poniéndole un nombre, luego una flecha con un guion y finalmente se usa el parámetro en una expresión.\n\n```java\nIntToDoubleFunction incrementalCosts = time -\u003e 5.1 + 0.5 * time;\n```\n\nEl mecanismo es una interfaz de un solo método. Las lambdas de java 8 son muy parecidas a la taquigrafía para una implementación anónima de una interfaz con un solo método.\nPara hacer una función de un objeto a otro, se puede usar la interfaz de función genérica suministrada en java 8, el primer tipo el parámetro y el segundo el tipo de retorno.\n\n```java\nFunction\u003cString, Integer\u003e wordCount = (String s) -\u003e s.split(\"\").length;\n```\n\nSe pueden hacer expresiones lambda con múltiples parámetros y el útlimo con el tipo de retorno con BiFunction.\nSe pueden hacer lambdas con más de una expresión en el cuerpo, luego poner las llaves alrededor y usar la palabra clave return.\n\n```java\nBiFunction\u003cString, Integer, Boolean\u003e exceedsMaxLength = (s, maxLength) -\u003e {\n    int actualLength = s.length();\n    return actualLength \u003e maxLength;\n};\n```\n\n### Patrón de estrategia (Strategy)\n\nSi volvemos al modo orientado a objetos y el parámetro de constructor como un objeto, estamos pasando un objeto que sabe cómo realizar un cálculo. Este es un patrón de diseño OO documentado. El patrón de estrategia es una pieza muy pequeña de programación funcional, Dado que una estrategia realiza un cálculo y no accede ni actualiza el mundo exterior, sus datos ingresan. Es un patrón funcional. Con java 8 el patrón de estrategia es mucho menos dificultoso, antes se tenia que usar clases internas anónimas. Las expresiones lambda son más cortas y eficientes, ni siquiera es necesario crear una interfaz funcional para pasarla, se puede usar la función estándar provista en java 8.\n\n![Alt text](/FunctionalProgramming/assets/functionalPattern.png?raw=true \"Strategy Pattern\")\n\n### Diferencias subyacentes de java 6 y java 8\n\nLa diferencia entre java 6 y java 8 es más por la forma en que se ve el código, Java 8 sabe y se preocupa por las expresiones lambda y hace algunas optimizaciones. En la versión java 6, si este método principal se llamara más de una vez, se crearía una instancia de un proveedor cada vez para cada uno de estos. En java 8 el compilador reconoce que el proveedor de CalculateCosts es el mismo cada vez y reutiliza la misma instancia, el proveedor CalculateRevenue también es una constante, para el beneficio una constante no funcionará porque los valores de costos e ingresos serían diferentes cada vez. Esos valores se capturan y almacenan dentro de la lambda cada vez que se crea. Significa que este tercer proveedor siempre obtiene una nueva instancia, incluso en java 8.\n\nJava 8 Constante\n\n```java\nfinal Double costs = timed(\"Costs calculation\", TimingDemo::calculateCosts);\n```\n\nJava 8 Constante\n\n```java\nfinal Double revenue = timed(\"Revenue calculation\", TimingDemo::calculateRevenue);\n```\n\nNueva instancia\n\n```java\nfinal Double profit = timed(\"Profit calculation\",\n    () -\u003e calculateProfit(costs, revenue),\n    logger::info);\n```\n\n### Colecciones\n\nEn java estamos acostumbrados a usar la iteración externa, pero un estilo funcional seria la iteración interna. En la librería Guava usando java 6 se logra con funciones iterables o con fluidez, por lo que podemos encadenar las llamadas, por operaciones internas como filtro, transformación o de unión, para ser combinadas en una sola iteración y devolver un solo valor. En java 8 la funcionalidad de fluidez iterable es proporcionada por stream, en la nueva biblioteca de colecciones, una lista puede proporcionarnos una secuencia y la secuencia proporciona los métodos de iteración internos que deseamos.\n\n**Librería Guava** | **Java 8**\n--- | --- |\n`FluentIterable` | `Stream`\n*filter* | *filter*\n*transform* | *map*\n*Joiner* | *reduce*\n\n### Streams\n\nLos streams pueden ser perezosos (LazyLoading) o paralelos. Hay diferentes tipos de métodos a los que puede recurrir y las consecuencias que tienen esos métodos. Pueden hacer cálculos en datos que estén dentro de una secuencia. Un flujo es un contexto para operar con datos. El poder de la programación funcional y el procesamiento de secuencias para permitir que el programa procese los datos que no caben en la memoria.\n\n```java\nStream\u003cString\u003e descriptions = Arrays.asList(descriptions)\n  .stream()\n  .filter(description -\u003e !descriptions.isEmpty())\n  .reduce((a, n) -\u003e a + \" \u0026 \" + n);\n```\n\n* **Operadores de terminal:** Son aquellos operadores que se activan cuando el procesamiento de la secuencia debe realizarse.\n\n```java\nlong count = Arrays.asList(descriptions)\n  .stream()\n  .count();\n\nboolean total = Arrays.asList(descriptions)\n  .stream()\n  .anyMatch(total -\u003e total \u003e 100.00);\n```\n\n* **Operadores intermedios:** Cuando se invocan en una secuencia, devuelven una secuencia a la que podemos continuar llamando.\n\n```java\nSupplier\u003cStream\u003cItem\u003e\u003e itemStream = () -\u003e sales.stream()\n    .flatMap(sale -\u003e sale.items.stream());\n\nlong itemCount = itemStream.get().count();\n```\n\n### Optional\n\nEl contexto es más eficaz que el nulo porque no tenemos que ir a cavar, podemos dejar que la opción haga la comprobación nula cada vez que queramos llamar a una función en el valor interno y eso se envía como un contexto opcional como una cuerda.\n\n```java\nString itemName = \"carrot\";\n\nOptional\u003cSale\u003e findSaleOf = sales.stream()\n  .filter(sale -\u003e sale.items.stream()\n    .anyMatch(item -\u003e item.identity.equals(itemName)))\n  .findFirst();\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcristianbonilla%2Ffunctional-programming","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcristianbonilla%2Ffunctional-programming","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcristianbonilla%2Ffunctional-programming/lists"}