{"id":319439,"date":"2023-02-06T07:24:33","date_gmt":"2023-02-06T06:24:33","guid":{"rendered":"https:\/\/blog.jetbrains.com\/?post_type=idea&#038;p=319439"},"modified":"2023-02-13T19:05:58","modified_gmt":"2023-02-13T18:05:58","slug":"pattern-matching-in-java-5-examples-for-busy-developers","status":"publish","type":"idea","link":"https:\/\/blog.jetbrains.com\/en\/idea\/2023\/02\/pattern-matching-in-java-5-examples-for-busy-developers","title":{"rendered":"Pattern Matching in Java &#8211; 5 Examples for Busy Developers"},"content":{"rendered":"<p>As a busy developer, it is difficult to keep up with new features and deeply understand where and how you can use them.<\/p>\n<p>In this blog post, I\u2019ll cover 5 places where you can use pattern matching in Java without diving into the finer details. When you think you are ready to explore further, check out the links included in this blog post.<\/p>\n<p>Let&#8217;s get started!<\/p>\n<p><iframe loading=\"lazy\" src=\"https:\/\/www.youtube.com\/embed\/a2hIvJt6F84\" width=\"560\" height=\"315\" frameborder=\"0\" allowfullscreen=\"allowfullscreen\"><\/iframe><\/p>\n<h2>1. Improve code readability by converting long if-else constructs to switch<\/h2>\n<p>First, let\u2019s address the most important question \u2013 why do we care about this conversion?<\/p>\n<p>One of the main benefits is that the code is more concise and easier to read and understand. Since long if-else statements which usually don\u2019t fit in a single screen and might involve vertical scrolling, it is difficult to understand the code that executes for all of the if comparisons. Also, the syntax of the if conditions can be unclear, because each if condition could have another set of conditions.<\/p>\n<p>Often when you browse a code base, you notice code that is similar to the code shown below. For a long if-else construct, that conditionally assigns value to a local variable. Take a look at the code below. I\u2019ll help you navigate it by highlighting certain sections a bit later:<\/p>\n<p><span style=\"color: #1e1e1e; font-family: monospace, monospace; font-size: 1em; white-space: pre-wrap;\"><\/span><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">    \nprivate static String getValueText(Object value) {\n    final String newExpression;\n    if (value instanceof String) {\n        final String string = (String)value;\n        newExpression = '\"' + StringUtil.escapeStringCharacters(string) + '\"';\n    }\n    else if (value instanceof Character) {\n        newExpression = '\\'' + StringUtil.escapeStringCharacters(value.toString()) + '\\'';\n    }\n    else if (value instanceof Long) {\n        newExpression = value.toString() + 'L';\n    }\n    else if (value instanceof Double) {\n        final double v = (Double)value;\n        if (Double.isNaN(v)) {\n            newExpression = \"java.lang.Double.NaN\";\n        }\n        else if (Double.isInfinite(v)) {\n            if (v &gt; 0.0) {\n                newExpression = \"java.lang.Double.POSITIVE_INFINITY\";\n            }\n            else {\n                newExpression = \"java.lang.Double.NEGATIVE_INFINITY\";\n            }\n        }\n        else {\n            newExpression = Double.toString(v);\n        }\n    }\n    else if (value instanceof Float) {\n        final float v = (Float) value;\n        if (Float.isNaN(v)) {\n            newExpression = \"java.lang.Float.NaN\";\n        }\n        else if (Float.isInfinite(v)) {\n            if (v &gt; 0.0F) {\n                newExpression = \"java.lang.Float.POSITIVE_INFINITY\";\n            }\n            else {\n                newExpression = \"java.lang.Float.NEGATIVE_INFINITY\";\n            }\n        }\n        else {\n            newExpression = Float.toString(v) + 'f';\n        }\n    }\n    else if (value == null) {\n        newExpression = \"null\";\n    }\n    else {\n        newExpression = String.valueOf(value);\n    }\n    return newExpression;\n}\n<\/pre>\n<p>Let\u2019s highlight the code to focus on. In the following image, notice that method <code>getValueText<\/code> compares whether the value of the variable <code>value<\/code> it is of a certain data type, such as <code>String<\/code>, <code>Character<\/code>, <code>Long<\/code>, <code>Double<\/code> or others:<\/p>\n<p><\/p>\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2023\/02\/long-if-else-1.png\" alt=\"\"\/><\/figure>\n\n\n<p><\/p>\n<p><span style=\"font-weight: 400;\">To understand the other parts of this if-else construct, let\u2019s focus on the variable, <\/span><code>newExpression<\/code>. Notice that this variable is being assigned a value for all the possible values of the variable <code>value<\/code>:<\/p>\n<p><\/p>\n\n\n<\/p>\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2023\/02\/long-if-else-2.png\" alt=\"\"><\/figure>\n<p>\n\n\n<p><\/p>\n<p><span style=\"font-weight: 400;\">Interestingly, all but two code blocks corresponding to the if-conditions are longer than the other if blocks, which are usually just a single line of code:<\/span><\/p>\n<p><\/p>\n\n\n<\/p>\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2023\/02\/long-if-else-3.png\" alt=\"\"><\/figure>\n<p>\n\n\n<p><\/p>\n<p>Let\u2019s extract these two longer code blocks to separate methods and then proceed with converting the if-else construct to switch.<\/p>\n<p>To extract code to another method, select the code, invoke Context actions using Alt+Enter or (Option+Enter for macOS), and select the \u2018extract method\u2019 option. You can choose from the suggested names for the new method, or enter a name of your choice. To select logical pieces of code, my favorite shortcut is Ctrl+W (or Ctrl+Shift+W to shrink selection). After the method extraction, follow IntelliJ IDEA\u2019s leads by noticing the keywords with yellow backgrounds and invoke context actions (Alt+enter). To convert this if-else to switch, I invoked context actions on \u2018if\u2019 and selected \u2018convert \u2018if\u2019 to \u2018switch\u2019:<\/p>\n\n\n<\/p>\n<figure class=\"wp-block-image alignnone wp-image-16062\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2023\/02\/1.gif\" alt=\"\"><\/figure>\n<p>\n\n\n<p><\/p>\n<p>Here\u2019s the switch construct in the method <code>getValueText<\/code> that is concise and easier to understand:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">private static String getValueText(Object value) {\n    final String newExpression = switch (value) {\n        case String string -&gt; '\"' + StringUtil.escapeStringCharacters(string) + '\"';\n        case Character character -&gt; '\\'' + StringUtil.escapeStringCharacters(value.toString()) + '\\'';\n        case Long aLong -&gt; value.toString() + 'L';\n        case Double aDouble -&gt; getNewExpression(aDouble);\n        case Float aFloat -&gt; getNewExpression(aFloat);\n        case null -&gt; \"null\";\n        default -&gt; String.valueOf(value);\n    };\n    return newExpression;\n}\n<\/pre>\n<p>Does this make you wonder why you didn\u2019t use switch expressions as often in your code as if-else constructs? There are several reasons for it. The switch construct has been enhanced in recent Java releases \u2013 they can return values (switch expressions) and they are no longer limited to comparing values for a limited primitive data type, wrapper classes, and others like <code>String<\/code> or enum. Also, their case labels can include patterns and conditions.<\/p>\n<p>With pattern matching and switch, you can also handle null values by using null as a case label. Also, each case label declares a pattern variable regardless of whether they are used in the corresponding code block. If you are concerned about the missing break labels, they are not required when you use the arrow styles with switch.<\/p>\n<p>However, this feature is still in the preview stage, which implies you shouldn\u2019t use it in your production code because it might change in a future Java version. Please follow <a href=\"https:\/\/blog.jetbrains.com\/en\/idea\/2022\/11\/java-19-and-intellij-idea#IntelliJ_IDEA_Configuration\">this link<\/a> to check on the configurations if you are not familiar with them.<\/p>\n<p><span style=\"font-weight: 400;\">Not all if-else statements can be converted to switch constructs. You can use the if-else constructs to define complex conditions that might use a combination of variables, constants, or method calls. Such complex comparisons are not yet supported by switch constructs.&nbsp;<\/span><\/p>\n<p>For a detailed coverage on Pattern Matching, please check out <a href=\"https:\/\/blog.jetbrains.com\/en\/idea\/2021\/09\/java-17-and-intellij-idea#What_is_pattern_matching\">this blog post<\/a>.<\/p>\n<h4>Running the \u201cif can be replaced with switch\u201d inspection on your code base<\/h4>\n<p>It can be time-consuming to look for if-else constructs in your code and check if they can be replaced with switch. You can run the inspection \u2018if can be replaced with switch\u2019 on all the classes in your codebase or its subset, as covered in <a href=\"https:\/\/blog.jetbrains.com\/en\/idea\/2021\/09\/java-17-and-intellij-idea#Running_the_if_can_be_replaced_with_switch_inspection_on_your_code_base\">this blog post<\/a>.<\/p>\n<p>Let\u2019s work with our next example, which uses pattern matching for instanceof, a production feature in Java.<\/p>\n<h2>2. Write concise code using PatternMatching with instanceof<\/h2>\n<p>Using pattern matching for the <code>instanceof<\/code> operator has been available as a production feature since Java version 16 and is usable in production code.<\/p>\n<p>To use this feature, I\u2019ll just follow IntelliJ IDEA\u2019s lead and invoke context actions on the <code>if<\/code>&nbsp;keyword, which is highlighted with a yellow background.<\/p>\n<p>Imagine you have a class, say, <code>Monitor<\/code>. Here\u2019s is one of the common examples you can find across codebases to implement its <code>equals<\/code> method:<\/p>\n<div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">public class Monitor {\n    String model;\n    double price;\n\n    @Override\n    public boolean equals(Object object) {\n        if (object instanceof Monitor) {\n            Monitor other = (Monitor) object;\n            return model.equals(other.model) &amp;&amp; price == other.price;\n        }\n        return false;\n    }\n}\n<\/pre>\n<p>The following gif shows how you could use pattern matching by invoking context actions on the variable named <code>other<\/code>, highlighted using a yellow background, and then selecting the option \u2018replace \u2018other\u2019 with pattern variable\u2019. Refactoring the resultant code by invoking context actions on the if statement can make this code even more concise. The final code is easier to read and understand \u2013 return true if all three mentioned conditions are true.<\/p>\n<figure class=\"wp-block-image alignnone wp-image-16062\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2023\/02\/2.gif\" alt=\"\"><\/figure>\n<\/div>\n<p>What happens if instead of a regular class, you are working with an instance of a Record? For the Records, pattern matching for instanceof can deconstruct a Record instance by defining pattern variables for the Record components. In the following example, <code>Citizen(String name, int age)<\/code> used with the <code>instanceof<\/code> operator is a Record pattern:<\/p>\n<figure class=\"wp-block-image alignnone wp-image-16062\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2023\/02\/4.gif\" alt=\"\"><\/figure>\n<p><\/p>\n<p>It\u2019s easy to miss the power of such features when we start with simple code examples like the two previous ones. Let\u2019s quickly look at another example of using Pattern matching with the instanceof operator, where removing the declaration of a local variable leads to other refactoring or improvement possibilities. In short, combining this feature with other refactoring or code improvement techniques can help you write better code (just follow IntelliJ IDEA\u2019s leads!):<\/p>\n<figure class=\"wp-block-image alignnone wp-image-16062\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2023\/02\/3.gif\" alt=\"\"><\/figure>\n<p><\/p>\n<h2>3. Ignore states that don\u2019t make sense<\/h2>\n<p><span style=\"font-size: revert;\">An if-else construct might not be the best choice to iterate over the values of a type that has an exhaustive set of values, like an enum or subtypes of a sealed class. For example, imagine you have an enum that defines a fix set of values, as follows:<\/span><\/p>\n<div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">enum SingleUsePlastic {\n    BOTTLE, SPOON, CARRY_BAG;\n}<\/pre>\n<p><span style=\"font-size: revert;\">Even though you know an instance of the type <code>SingleUsePlastic<\/code> can have either of the three values, that is, <code>BOTTLE<\/code>, <code>SPOON<\/code> and <code>CARRY_BAG<\/code>, the following code wouldn\u2019t compile for final local variable <code>replacement<\/code>:<\/span><\/p>\n<\/div>\n<div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">public class Citizen {\n    String getReplacements(SingleUsePlastic plastic) {\n        final String replacement;\n        if (plastic == SingleUsePlastic.BOTTLE) {\n            replacement = \"Booth 4: Pick up a glass bottle\";\n        } else if (plastic == SingleUsePlastic.SPOON) {\n            replacement = \"Pantry: Pick up a steel spoon\";\n        } else if (plastic == SingleUsePlastic.CARRY_BAG) {\n            replacement = \"Booth 5: Pick up a cloth bag\";\n        } \n        return replacement;\n    }\n}<\/pre>\n<p><span style=\"font-size: revert;\">To make it compile, you\u2019ll need to add an else clause at the end that doesn\u2019t make sense.<\/span><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">public class Citizen {\n    String getReplacements(SingleUsePlastic plastic) {\n        final String replacement;\n        if (plastic == SingleUsePlastic.BOTTLE) {\n            replacement = \"Booth 4: Pick up a glass bottle\";\n        } else if (plastic == SingleUsePlastic.SPOON) {\n            replacement = \"Pantry: Pick up a steel spoon\";\n        } else if (plastic == SingleUsePlastic.CARRY_BAG) {\n            replacement = \"Booth 5: Pick up a cloth bag\";\n        } else {\n            replacement = \"\";\n        }\n        return replacement;\n    }\n}<\/pre>\n<p><span style=\"font-size: revert;\">With a switch construct, you don\u2019t need to code a <code>default<\/code> part for values that don\u2019t exist:<\/span><\/p>\n<\/div>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">public class Citizen {\n    String getReplacements(SingleUsePlastic plastic) {\n        final String replacement = switch (plastic) {\n            case BOTTLE -&gt; \"Booth 4: Pick up a glass bottle\";\n            case SPOON -&gt; \"Pantry: Pick up a steel spoon\";\n            case CARRY_BAG -&gt; \"Booth 5: Pick up a cloth bag\";\n        };\n        return replacement;\n    }\n}<\/pre>\n<p>Similarly, if you define a sealed class, you can use a switch construct to iterate over its exhaustive list of subclasses without defining a default clause:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">sealed interface Lego {}\nfinal class SquareLego implements Lego {}\nnon-sealed class RectangleLogo implements Lego {}\nsealed class CharacterLego implements Lego permits PandaLego {}\nfinal class PandaLego extends CharacterLego {}\n\npublic class MyLegoGame {\n    int processLego(Lego lego) {\n        return switch (lego) {\n            case SquareLego squareLego -&gt; 100;\n            case RectangleLego rectangleLego-&gt; 200;\n            case CharacterLego characterLego -&gt; 300;\n        };\n    }\n}<\/pre>\n<p>If you are not familiar with sealed classes and wish to deep dive on this topic, you can access <a href=\"https:\/\/blog.jetbrains.com\/en\/idea\/2021\/09\/java-17-and-intellij-idea#Need_for_creating_restricted_hierarchies\">this blog post<\/a>.<\/p>\n<h2>4. Powerful and concise data processing<\/h2>\n<p>You can create powerful, yet concise and expressive code to process your data by using a combination of record patterns, switch expressions, and sealed classes. Here\u2019s an example of a sealed interface <code>TwoDimensional<\/code>, which is implemented by Records <code>Point<\/code>, <code>Line<\/code>, <code>Triangle<\/code> and <code>Square<\/code>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">sealed interface TwoDimensional {}\nrecord Point    (int x, \n                 int y) implements TwoDimensional { }\nrecord Line     (Point start, \n                 Point end) implements TwoDimensional { }\nrecord Triangle (Point pointA, \n                 Point pointB, \n\t\t\t\t Point PointC) implements TwoDimensional { }\nrecord Square   (Point pointA, \n                 Point pointB, \n\t\t\t     Point PointC, \n\t\t\t     Point pointD) implements TwoDimensional { }\n<\/pre>\n<p>The following method defines a recursive method process that uses a switch construct to return the sum of x and y coordinates of all the points in a two dimensional figure like a <code>Line<\/code>, <code>Triangle<\/code> or <code>Square<\/code>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">static int process(TwoDimensional twoDim) {\n    return switch (twoDim) {\n        case Point(int x, int y) -&gt; x + y;\n        case Line(Point a, Point b) -&gt; process(a) + process(b);\n        case Triangle(Point a, Point b, Point c) -&gt; process(a) + process(b) + process(c);\n        case Square(Point a, Point b, Point c, Point d) -&gt; process(a) + process(b) + process(c) + process(d);\n    };\n}\n<\/pre>\n<p>IntelliJ IDEA also displays the recursive call icon in the gutter for this method:<\/p>\n<p><\/p>\n\n\n<\/p>\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2023\/02\/recursion.png\" alt=\"\"><\/figure>\n<p>\n\n\n<p><\/p>\n<h2>5. Separation of computation and side effect<\/h2>\n<p>You\u2019d often notice code that combines a computation and a side effect (such as printing to console) in the same code block. For example, the following code uses an if-else block and <code>instanceof<\/code> operator to determine the type of a variable and outputs a value conditionally in each if code block.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">void printObject(Object obj) {\n    if (obj instanceof String s) {\n        System.out.println(\"String: \\\"\" + s + \"\\\"\");\n    } else if (obj instanceof Collection&lt;?&gt; c) {\n        System.out.println(\"Collection (size = \" + c.size() + \")\");\n    } else {\n        System.out.println(\"Other object: \" + obj);\n    }\n}\n<\/pre>\n<p>The following gif shows, how you can convert this if-else block to a switch construct and then use a new inspection on switch \u2013 Push down for \u2018switch\u2019 expressions, followed by extraction of a variable to separate computation and its side effects:<\/p>\n<figure class=\"wp-block-image alignnone wp-image-16062\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2023\/02\/5-1.gif\" alt=\"\"><\/figure>\n<p><\/p>\n<h2>Summary<\/h2>\n<p>In this blog post, we covered 5 places where busy developers can use Pattern Matching in Java. If you are interested in learning more about these features or how IntelliJ IDEA helps you use them, refer to the links that I included while covering these examples.<\/p>\n<p>Let me know what other topics you\u2019d like me to cover in my next blog post.<\/p>\n<p>Until then, happy coding!<\/p>","protected":false},"author":921,"featured_media":320082,"comment_status":"closed","ping_status":"closed","template":"","categories":[4759,5088],"tags":[40,155],"cross-post-tag":[],"acf":[],"_links":{"self":[{"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/idea\/319439"}],"collection":[{"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/idea"}],"about":[{"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/types\/idea"}],"author":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/users\/921"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/comments?post=319439"}],"version-history":[{"count":10,"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/idea\/319439\/revisions"}],"predecessor-version":[{"id":334150,"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/idea\/319439\/revisions\/334150"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/media\/320082"}],"wp:attachment":[{"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/media?parent=319439"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/categories?post=319439"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/tags?post=319439"},{"taxonomy":"cross-post-tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/cross-post-tag?post=319439"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}