From c699c83e623d5dbbad5f4ad0a382e6076060850a Mon Sep 17 00:00:00 2001 From: "venkats@agiledeveloper.com" Date: Mon, 8 Jan 2024 18:21:00 -0600 Subject: [PATCH 1/2] next article in the series --- .../00_refactoring.md | 1 + ..._converting_foreach_with_transformation.md | 116 ++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 app/pages/learn/01_tutorial/03_getting-to-know-the-language/03_refactoring_to_functional_style/04_converting_foreach_with_transformation.md diff --git a/app/pages/learn/01_tutorial/03_getting-to-know-the-language/03_refactoring_to_functional_style/00_refactoring.md b/app/pages/learn/01_tutorial/03_getting-to-know-the-language/03_refactoring_to_functional_style/00_refactoring.md index 3aebcb3..86a163e 100644 --- a/app/pages/learn/01_tutorial/03_getting-to-know-the-language/03_refactoring_to_functional_style/00_refactoring.md +++ b/app/pages/learn/01_tutorial/03_getting-to-know-the-language/03_refactoring_to_functional_style/00_refactoring.md @@ -22,4 +22,5 @@ In this series we cover the following conversions from the imperative to the fun | [Converting Simple Loops](id:refactoring.simple.loops) | `for()` | `range()` or `rangeClosed()` | | [Converting Loops with Steps](id:refactoring.loops.withsteps) | `for(...i = i + ...)` | `iterate()` with `takeWhile()` | | [Converting foreach with if](id:refactoring.foreach.withif) | `foreach(...) { if... }` | `stream()` with `filter()` | +| [Converting Iteration with transformation](id:refactoring.iteration.withtransformation) | `foreach(...) { ...transformation... }` | `stream()` with `map()` | diff --git a/app/pages/learn/01_tutorial/03_getting-to-know-the-language/03_refactoring_to_functional_style/04_converting_foreach_with_transformation.md b/app/pages/learn/01_tutorial/03_getting-to-know-the-language/03_refactoring_to_functional_style/04_converting_foreach_with_transformation.md new file mode 100644 index 0000000..b3f58ed --- /dev/null +++ b/app/pages/learn/01_tutorial/03_getting-to-know-the-language/03_refactoring_to_functional_style/04_converting_foreach_with_transformation.md @@ -0,0 +1,116 @@ +--- +id: refactoring.iteration.withtransformation +title: Converting Iteration with transformation +slug: learn/refactoring-to-functional-style/iteartionwithtransformation +type: tutorial-group +group: refactoring-to-functional-style +layout: learn/tutorial-group.html +subheader_select: tutorials +main_css_id: learn +toc: +- Transforming while Iterating {transforming} +- From Imperative to Functional Style {imperativetofunctional} +- Picking Elements to Transform {picking} +- Mappings {mappings} +description: "Converting Imperative Iteration with transformation to Functional Style." +last_update: 2024-01-08 +author: ["VenkatSubramaniam"] +--- + +  +## Transforming while Iterating + +In the previous articles in this series we looked at converting loops with `if` or conditional statements in the imperative style to the functional style. In this article we'll see how to convert an imperative style iteration that transforms data to the functional style. In addition, we'll also refactor code that mixes transforming data with code that picks select elements before the transformation. + +Anytime we are transforming data in an imperative style loop, we can use the `map()` function in the functional style. Let's see how. + + +  +## From Imperative to Functional Style + +Here's an example of an iteration, using the `foreach`, that transforms to uppercase a collection of names: + +```java +List names = List.of("Jack", "Paula", "Kate", "Peter"); + +for(String name: names) { + System.out.println(name.toUpperCase()); +} +``` + +Each step through the iteration, the `name` variable is bound to a new value. As the iteration advances from one element to the next in the given collection, each name is transformed to uppercase using the `toUpperCase()` function and the resulting value is printed. We have already seen, in the previous article, how to convert the imperative style `foreach` to the functional style—using the `stream()` internal iteration. If we merely apply what we have seen before, the resulting functional style code would be rather unwieldy, with the lambda passed to `forEach` performing both transformation and printing, like so: + +```java +List names = List.of("Jack", "Paula", "Kate", "Peter"); + +names.forEach(name -> System.out.println(name.toUpperCase())); //Don't do this +``` + +Even though the above functional style code will produce the same results as the imperative style code, the lambda passed to the `forEach()` function is not cohesive, hard to read, and hard to change. + +Before refactoring the imperative style code above to the function style, we should first refactor the imperative style to yet another imperative style implementation to make each line more cohesive, like so: + +```java +List names = List.of("Jack", "Paula", "Kate", "Peter"); + +for(String name: names) { + String nameInUpperCase = name.toUpperCase(); + System.out.println(nameInUpperCase); +} +``` + +From the previous articles in this series, we know that the `for` can turn into a `stream()` and the printing of the value can be done from within the `forEach()`. That leaves us with the transformation, the call to the `toUpperCase()` function. Such transformations can be done using the `map()` operation on the `stream()`. + +```java +List names = List.of("Jack", "Paula", "Kate", "Peter"); + +names.stream() + .map(name -> name.toUpperCase()) + .forEach(nameInUpperCase -> System.out.println(nameInUpperCase)); +``` +The `map()` operation transforms the data to a different value based on the function invoked from within the lambda expression that's passed to `map()`. In this example, each name is transformed to its uppercase value. The transformed value is then printed out from within the lambda expression passed to `forEach()`. + +We can make the code a bit more concise by using method references instead of lambda expressions, like so: + +```java +List names = List.of("Jack", "Paula", "Kate", "Peter"); + +names.stream() + .map(String::toUpperCase) + .forEach(System.out::println); +``` + +Use the `map()` function to transform data while iterating over a collection of data. + +  +## Picking Elements to Transform + +Suppose, in the middle of the iteration, we want to pick some values from the collection based on some condition and apply a transformation only on those elements. For example, what if we want to transform and print only names of length 4? In the imperative style we could do the following: + +```java +List names = List.of("Jack", "Paula", "Kate", "Peter"); + +for(String name: names) { + if(name.length() == 4) { + System.out.println(name.toUpperCase()); + } +} +``` + +We already know that the imperative style `if` can be refactored to the `filter()` function in the functional style. We can perform the transformation, using `map()`, after the `filter()` operation, like so: + +```java +List names = List.of("Jack", "Paula", "Kate", "Peter"); + +names.stream() + .filter(name -> name.length() == 4) + .map(String::toUpperCase) + .forEach(System.out::println); +``` + +The `filter()` function discards data that's not desired and passes on only the values we like to use. The `map()` function transforms the values it sees after the filter. + +  +## Mappings + +Anywhere you see transformation of data within a for loop, use the `map()` function to perform the transformation in the functional style. In addition, if the body of the loop has a `if` statement to selectively some value for transformation, then use the `stream()` API with the call to the `filter()` method before using the `map()` method. From e334f0706bbe1dfc71a659bde4d8c743a27f4edc Mon Sep 17 00:00:00 2001 From: Chad Arimura Date: Mon, 15 Jan 2024 08:54:28 -0800 Subject: [PATCH 2/2] some links back to the series head page --- .../01_converting_simple_loops.md | 2 +- .../02_converting_loops_with_steps.md | 2 +- .../03_converting_foreach_with_if.md | 2 +- .../04_converting_foreach_with_transformation.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/pages/learn/01_tutorial/03_getting-to-know-the-language/03_refactoring_to_functional_style/01_converting_simple_loops.md b/app/pages/learn/01_tutorial/03_getting-to-know-the-language/03_refactoring_to_functional_style/01_converting_simple_loops.md index 604334f..3988370 100644 --- a/app/pages/learn/01_tutorial/03_getting-to-know-the-language/03_refactoring_to_functional_style/01_converting_simple_loops.md +++ b/app/pages/learn/01_tutorial/03_getting-to-know-the-language/03_refactoring_to_functional_style/01_converting_simple_loops.md @@ -23,7 +23,7 @@ The older versions of Java supported the Object-Oriented paradigm mixed with the Imperative style is where we tell what to do and also how to do it. Functional style is declarative in nature, where we tell what to do and delegate the how or the details to the underlying libraries. Imperative style code may be easier to write since most of us are very familiar with it. However, the code becomes verbose, complex, and hard to read. Functional style may be hard at first, mainly because most programmers are less familiar with it. In general, it's easier to read, understand, and change. With practice, it becomes easier to write as well. -In this tutorial series we will take a look at a number of common imperative style code and find a mapping or an equivalent functional style code that we can use instead. As you work with your code based, when you're ready to fix a bug or make an enhancement, you may find it useful to refactor some of the imperative style code to the functional style. You can use this tutorial as a guide to find the imperative to functional style mappings for some common situations. +In this [tutorial series](id:refactoring) we will take a look at a number of common imperative style code and find a mapping or an equivalent functional style code that we can use instead. As you work with your code based, when you're ready to fix a bug or make an enhancement, you may find it useful to refactor some of the imperative style code to the functional style. You can use this tutorial as a guide to find the imperative to functional style mappings for some common situations. In this tutorial we'll focus on simple loops. diff --git a/app/pages/learn/01_tutorial/03_getting-to-know-the-language/03_refactoring_to_functional_style/02_converting_loops_with_steps.md b/app/pages/learn/01_tutorial/03_getting-to-know-the-language/03_refactoring_to_functional_style/02_converting_loops_with_steps.md index 9872e18..687c068 100644 --- a/app/pages/learn/01_tutorial/03_getting-to-know-the-language/03_refactoring_to_functional_style/02_converting_loops_with_steps.md +++ b/app/pages/learn/01_tutorial/03_getting-to-know-the-language/03_refactoring_to_functional_style/02_converting_loops_with_steps.md @@ -20,7 +20,7 @@ author: ["VenkatSubramaniam"]   ## Iterating with Steps -In the previous article in this series we looked at converting simple loops written in the imperative style to the functional style. In this article we'll see how to take on loops that are a bit more complex—when we have to step over some values in an interval. +In the previous article in this [tutorial series](id:refactoring) we looked at converting simple loops written in the imperative style to the functional style. In this article we'll see how to take on loops that are a bit more complex—when we have to step over some values in an interval. When looping over a range of values, one at a time, the `range()` method of `IntStream` came in handy to implement in the functional style. This method returns a stream that will generate one value at a time for values within the specified range. At first thought, to skip some values we may be tempted to use the `filter()` method on the stream. However, there's a simpler solution, the `iterate()` method of `IntStream`. diff --git a/app/pages/learn/01_tutorial/03_getting-to-know-the-language/03_refactoring_to_functional_style/03_converting_foreach_with_if.md b/app/pages/learn/01_tutorial/03_getting-to-know-the-language/03_refactoring_to_functional_style/03_converting_foreach_with_if.md index 9bd6417..4a20eb5 100644 --- a/app/pages/learn/01_tutorial/03_getting-to-know-the-language/03_refactoring_to_functional_style/03_converting_foreach_with_if.md +++ b/app/pages/learn/01_tutorial/03_getting-to-know-the-language/03_refactoring_to_functional_style/03_converting_foreach_with_if.md @@ -20,7 +20,7 @@ author: ["VenkatSubramaniam"]   ## Iterating with foreach -In the previous articles in this series we looked at converting loops written in the imperative style to the functional style. In this article we'll see how to convert an imperative style iteration using `foreach` to the functional style. In addition, we'll also see how to pick select elements using `if` transforms to the functional style. +In the previous articles in this [tutorial series](id:refactoring) we looked at converting loops written in the imperative style to the functional style. In this article we'll see how to convert an imperative style iteration using `foreach` to the functional style. In addition, we'll also see how to pick select elements using `if` transforms to the functional style. Java 5 introduced the very popular `foreach` syntax. For example, to iterate over a collection of `String`s representing names, we'd write something like `for(String name: names)`. Under the hood, the `foreach` is converted, at the bytecode level, to use an `Iterator`—while the iterator tells us there is another element, fetch the next element for processing. In other words, the `foreach` is a nice concise syntax sugar for iteration with a `while` loop over the elements provided by an `Iterator`. We can convert a `foreach` into the functional style quite easily. Let's see how. diff --git a/app/pages/learn/01_tutorial/03_getting-to-know-the-language/03_refactoring_to_functional_style/04_converting_foreach_with_transformation.md b/app/pages/learn/01_tutorial/03_getting-to-know-the-language/03_refactoring_to_functional_style/04_converting_foreach_with_transformation.md index b3f58ed..844cc4b 100644 --- a/app/pages/learn/01_tutorial/03_getting-to-know-the-language/03_refactoring_to_functional_style/04_converting_foreach_with_transformation.md +++ b/app/pages/learn/01_tutorial/03_getting-to-know-the-language/03_refactoring_to_functional_style/04_converting_foreach_with_transformation.md @@ -20,7 +20,7 @@ author: ["VenkatSubramaniam"]   ## Transforming while Iterating -In the previous articles in this series we looked at converting loops with `if` or conditional statements in the imperative style to the functional style. In this article we'll see how to convert an imperative style iteration that transforms data to the functional style. In addition, we'll also refactor code that mixes transforming data with code that picks select elements before the transformation. +In the previous articles in this [tutorial series](id:refactoring) we looked at converting loops with `if` or conditional statements in the imperative style to the functional style. In this article we'll see how to convert an imperative style iteration that transforms data to the functional style. In addition, we'll also refactor code that mixes transforming data with code that picks select elements before the transformation. Anytime we are transforming data in an imperative style loop, we can use the `map()` function in the functional style. Let's see how.