<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Posts on vlad·flore · tech</title>
        <link>https://vladflore.tech/posts/</link>
        <description>Recent content in Posts on vlad·flore · tech</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>en</language>
        <lastBuildDate>Sat, 14 Mar 2026 00:00:00 +0000</lastBuildDate>
        <atom:link href="https://vladflore.tech/posts/index.xml" rel="self" type="application/rss+xml" />
        
        <item>
            <title>Git Animated 5</title>
            <link>https://vladflore.tech/posts/2026/03/git-animated-5/</link>
            <pubDate>Sat, 14 Mar 2026 00:00:00 +0000</pubDate>
            
            <guid>https://vladflore.tech/posts/2026/03/git-animated-5/</guid>
            <description>&lt;p&gt;This is the fifth and last video in the &lt;strong&gt;Git Animated&lt;/strong&gt; series.
If you are interested in the other ones, check the links below:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://vladflore.tech/posts/2021/08/git-animated-1/&#34;&gt;part one&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://vladflore.tech/posts/2021/08/git-animated-2/&#34;&gt;part two&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://vladflore.tech/posts/2021/09/git-animated-3/&#34;&gt;part three&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://vladflore.tech/posts/2021/12/git-animated-4/&#34;&gt;part four&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this video we look at &lt;strong&gt;cherry-pick&lt;/strong&gt;, a powerful Git command that lets you apply the changes introduced by a specific commit from one branch onto another, without merging or rebasing the entire branch. Think of it as picking a single commit — like a cherry — and grafting it onto a different branch.&lt;/p&gt;</description>
            <content type="html"><![CDATA[<p>This is the fifth and last video in the <strong>Git Animated</strong> series.
If you are interested in the other ones, check the links below:</p>
<ul>
<li><a href="https://vladflore.tech/posts/2021/08/git-animated-1/">part one</a></li>
<li><a href="https://vladflore.tech/posts/2021/08/git-animated-2/">part two</a></li>
<li><a href="https://vladflore.tech/posts/2021/09/git-animated-3/">part three</a></li>
<li><a href="https://vladflore.tech/posts/2021/12/git-animated-4/">part four</a></li>
</ul>
<p>In this video we look at <strong>cherry-pick</strong>, a powerful Git command that lets you apply the changes introduced by a specific commit from one branch onto another, without merging or rebasing the entire branch. Think of it as picking a single commit — like a cherry — and grafting it onto a different branch.</p>
<p>In the animation, we start on <code>master</code> with commits <code>M0</code> and <code>M1</code>, then create a <code>feature</code> branch and add three commits <code>F0</code>, <code>F1</code>, and <code>F2</code> to it. We then switch back to <code>master</code> and add one more commit <code>M2</code>. At this point the two branches have diverged. Instead of merging or rebasing the whole <code>feature</code> branch, we cherry-pick only commit <code>F1</code> onto <code>master</code>. Git takes the diff introduced by <code>F1</code> and replays it on top of <code>M2</code>, producing a new commit that carries the same changes but has a different hash and a different parent.</p>
<p>Notice that the <code>feature</code> branch is left untouched, and commits <code>F0</code> and <code>F2</code> are not brought over — only <code>F1</code> is. This is what makes cherry-pick so useful: you can selectively integrate individual commits across branches, for example to backport a bug fix to a release branch without pulling in unrelated work.</p>
<p>For your convenience, here are the Git commands which appear in the video:</p>
<pre tabindex="0"><code>git commit -m &#39;M0&#39;
git commit -m &#39;M1&#39;
git branch feature
git checkout feature
git commit -m &#39;F0&#39;
git commit -m &#39;F1&#39;
git commit -m &#39;F2&#39;
git checkout master
git commit -m &#39;M2&#39;
git cherry-pick F1
</code></pre><p>Here is the video(there is no audio):</p>
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
      <iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/9RbcP7AfV4U?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"></iframe>
    </div>

<!-- raw HTML omitted -->
<p>Feel free to drop me a comment or e-mail with your constructive criticism. It will be much appreciated!</p>
<p>Enjoy!</p>
]]></content>
        </item>
        
        <item>
            <title>Algorithms Narrated</title>
            <link>https://vladflore.tech/posts/2026/02/algorithms-narrated/</link>
            <pubDate>Fri, 06 Feb 2026 00:00:00 +0000</pubDate>
            
            <guid>https://vladflore.tech/posts/2026/02/algorithms-narrated/</guid>
            <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Building on the &lt;a href=&#34;https://vladflore.tech/posts/2021/08/git-animated-1/&#34;&gt;Git Animated&lt;/a&gt; series, I&amp;rsquo;ve started a new project called &amp;ldquo;Algorithms Narrated&amp;rdquo;. This series presents solutions to various algorithmic problems—think &lt;em&gt;LeetCode&lt;/em&gt;—by narrating the thought process and steps involved in solving them.&lt;/p&gt;
&lt;h2 id=&#34;about-the-series&#34;&gt;About The Series&lt;/h2&gt;

    &lt;img src=&#34;https://vladflore.tech/images/algorithms-narrated.jpeg&#34;  alt=&#34;Algorithms Narrated&#34;  class=&#34;left&#34;  style=&#34;border-radius: 16px;&#34;  /&gt;


&lt;p&gt;Each video shows the Java code and problem statement together with examples and the time complexity of the solution.&lt;/p&gt;
&lt;p&gt;All videos are added to the &lt;a href=&#34;https://www.youtube.com/playlist?list=PLgrzxhDrZj_KN3Tu_o9RaMqu9XOfmicps&#34; target=&#34;_blank&#34;&gt;Algorithms Narrated playlist&lt;/a&gt; on my &lt;a href=&#34;https://www.youtube.com/@vladflore&#34; target=&#34;_blank&#34;&gt;YouTube channel&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Subscribe to stay updated, and if you find them helpful, please like and share the series.&lt;/p&gt;</description>
            <content type="html"><![CDATA[<h2 id="introduction">Introduction</h2>
<p>Building on the <a href="https://vladflore.tech/posts/2021/08/git-animated-1/">Git Animated</a> series, I&rsquo;ve started a new project called &ldquo;Algorithms Narrated&rdquo;. This series presents solutions to various algorithmic problems—think <em>LeetCode</em>—by narrating the thought process and steps involved in solving them.</p>
<h2 id="about-the-series">About The Series</h2>

    <img src="/images/algorithms-narrated.jpeg"  alt="Algorithms Narrated"  class="left"  style="border-radius: 16px;"  />


<p>Each video shows the Java code and problem statement together with examples and the time complexity of the solution.</p>
<p>All videos are added to the <a href="https://www.youtube.com/playlist?list=PLgrzxhDrZj_KN3Tu_o9RaMqu9XOfmicps" target="_blank">Algorithms Narrated playlist</a> on my <a href="https://www.youtube.com/@vladflore" target="_blank">YouTube channel</a>.</p>
<p>Subscribe to stay updated, and if you find them helpful, please like and share the series.</p>
<p>Happy coding!</p>
]]></content>
        </item>
        
        <item>
            <title>Compiling and Running a Maven Project with Different Java Versions</title>
            <link>https://vladflore.tech/posts/2026/01/compiling-and-running-a-maven-project-with-different-java-versions/</link>
            <pubDate>Tue, 13 Jan 2026 00:00:00 +0000</pubDate>
            
            <guid>https://vladflore.tech/posts/2026/01/compiling-and-running-a-maven-project-with-different-java-versions/</guid>
            <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s explore how to use multiple versions of Java in a Maven project By this, I mean seemingly &lt;em&gt;compiling&lt;/em&gt; and &lt;em&gt;running&lt;/em&gt; a project with different Java versions.&lt;/p&gt;
&lt;p&gt;I will be using Java 17, 21 and 25 for this demo. Make sure you have them installed on your machine. You can use &lt;a href=&#34;https://sdkman.io/&#34; target=&#34;_blank&#34;&gt;SDKMAN!&lt;/a&gt; to manage multiple Java versions easily. Additionally, ensure &lt;a href=&#34;https://maven.apache.org/&#34; target=&#34;_blank&#34;&gt;Maven&lt;/a&gt; is installed.&lt;/p&gt;
&lt;p&gt;As always, there are multiple ways to achieve this. Here, I will demonstrate one approach using &lt;a href=&#34;https://maven.apache.org/guides/mini/guide-using-toolchains.html&#34; target=&#34;_blank&#34;&gt;Maven Toolchains&lt;/a&gt;.&lt;/p&gt;</description>
            <content type="html"><![CDATA[<h2 id="introduction">Introduction</h2>
<p>Let&rsquo;s explore how to use multiple versions of Java in a Maven project By this, I mean seemingly <em>compiling</em> and <em>running</em> a project with different Java versions.</p>
<p>I will be using Java 17, 21 and 25 for this demo. Make sure you have them installed on your machine. You can use <a href="https://sdkman.io/" target="_blank">SDKMAN!</a> to manage multiple Java versions easily. Additionally, ensure <a href="https://maven.apache.org/" target="_blank">Maven</a> is installed.</p>
<p>As always, there are multiple ways to achieve this. Here, I will demonstrate one approach using <a href="https://maven.apache.org/guides/mini/guide-using-toolchains.html" target="_blank">Maven Toolchains</a>.</p>
<h2 id="configure-maven-toolchains">Configure Maven Toolchains</h2>
<p>First, create a <code>toolchains.xml</code> file in your Maven configuration directory (<code>~/.m2/</code> on Unix-based systems or <code>%USERPROFILE%\.m2\</code> on Windows). This file will define the different Java versions you want to use.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#75715e">&lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34;?&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;toolchains&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;toolchain&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;type&gt;</span>jdk<span style="color:#f92672">&lt;/type&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;provides&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&lt;version&gt;</span>17<span style="color:#f92672">&lt;/version&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;/provides&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;configuration&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&lt;jdkHome&gt;</span>/Users/vladflore/.sdkman/candidates/java/17.0.12-oracle<span style="color:#f92672">&lt;/jdkHome&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;/configuration&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;/toolchain&gt;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;toolchain&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;type&gt;</span>jdk<span style="color:#f92672">&lt;/type&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;provides&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&lt;version&gt;</span>21<span style="color:#f92672">&lt;/version&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;/provides&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;configuration&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&lt;jdkHome&gt;</span>/Users/vladflore/.sdkman/candidates/java/21.0.3-oracle<span style="color:#f92672">&lt;/jdkHome&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;/configuration&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;/toolchain&gt;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;toolchain&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;type&gt;</span>jdk<span style="color:#f92672">&lt;/type&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;provides&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&lt;version&gt;</span>25<span style="color:#f92672">&lt;/version&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;/provides&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;configuration&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&lt;jdkHome&gt;</span>/Users/vladflore/.sdkman/candidates/java/25.0.1-open<span style="color:#f92672">&lt;/jdkHome&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;/configuration&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;/toolchain&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/toolchains&gt;</span>
</span></span></code></pre></div><p>This configuration specifies three different JDK versions and their respective installation paths.</p>
<h2 id="set-up-maven-project">Set Up Maven Project</h2>
<p>I will be using a new Maven project for this demonstration.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>&gt; mvn archetype:generate -DgroupId<span style="color:#f92672">=</span>tech.vladflore.app -DartifactId<span style="color:#f92672">=</span>multijava -DarchetypeArtifactId<span style="color:#f92672">=</span>maven-archetype-quickstart -DarchetypeGroupId<span style="color:#f92672">=</span>org.apache.maven.archetypes -DinteractiveMode<span style="color:#f92672">=</span>false <span style="color:#f92672">&amp;&amp;</span> cd multijava
</span></span></code></pre></div><p>Add this code in the <code>App.java</code> file located in <code>src/main/java/tech/vladflore/app/</code>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">package</span> tech.vladflore.app;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">App</span> {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">main</span>(String<span style="color:#f92672">[]</span> args) {
</span></span><span style="display:flex;"><span>        System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(Runtime.<span style="color:#a6e22e">version</span>());
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Now, let&rsquo;s see how to compile this project with different Java versions using Maven Toolchains.</p>
<p>Update the <code>pom.xml</code> file by including the Maven Toolchains plugin.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#f92672">&lt;plugin&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;groupId&gt;</span>org.apache.maven.plugins<span style="color:#f92672">&lt;/groupId&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;artifactId&gt;</span>maven-toolchains-plugin<span style="color:#f92672">&lt;/artifactId&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;version&gt;</span>3.2.0<span style="color:#f92672">&lt;/version&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;executions&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;execution&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&lt;goals&gt;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&lt;goal&gt;</span>toolchain<span style="color:#f92672">&lt;/goal&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&lt;/goals&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;/execution&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;/executions&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;configuration&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;toolchains&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&lt;jdk&gt;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&lt;version&gt;</span>${java.compiler.version}<span style="color:#f92672">&lt;/version&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&lt;/jdk&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;/toolchains&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;/configuration&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/plugin&gt;</span>
</span></span></code></pre></div><p>The <code>java.compiler.version</code> property will be set when running Maven commands.</p>
<p>Do not forget to add it to the properties section of your <code>pom.xml</code>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#f92672">&lt;properties&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;maven.compiler.release&gt;</span>${java.compiler.version}<span style="color:#f92672">&lt;/maven.compiler.release&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/properties&gt;</span>
</span></span></code></pre></div><p>We use <code>maven.compiler.release</code> because it ensures both bytecode level and API compatibility.</p>
<h2 id="compiling-with-different-java-versions">Compiling with Different Java Versions</h2>
<p>At this point, we can compile the project using different Java versions. We can check the Java version used during compilation by running <code>javap</code> on the compiled class file and inspecting the version.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>&gt; mvn clean compile -Djava.compiler.version<span style="color:#f92672">=</span><span style="color:#ae81ff">17</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>&gt; cd target/classes
</span></span><span style="display:flex;"><span>&gt; javap -verbose tech.vladflore.app.App | grep major
</span></span></code></pre></div><p>This should output <code>major version: 61</code>, which corresponds to Java 17.</p>
<p>Let&rsquo;s try with the other version as well.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>&gt; mvn clean compile -Djava.compiler.version<span style="color:#f92672">=</span><span style="color:#ae81ff">21</span>
</span></span><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span>&gt; cd target/classes
</span></span><span style="display:flex;"><span>&gt; javap -verbose tech.vladflore.app.App | grep major
</span></span><span style="display:flex;"><span>major version: <span style="color:#ae81ff">65</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>&gt; mvn clean compile -Djava.compiler.version<span style="color:#f92672">=</span><span style="color:#ae81ff">25</span>
</span></span><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span>&gt; cd target/classes
</span></span><span style="display:flex;"><span>&gt; javap -verbose tech.vladflore.app.App | grep major
</span></span><span style="display:flex;"><span>major version: <span style="color:#ae81ff">69</span>
</span></span></code></pre></div><p>So far so good! We have successfully compiled the project with different Java versions.</p>
<h2 id="running-with-different-java-versions">Running with Different Java Versions</h2>
<p>If I were to run the project now, i.e. run the only Java class I have, I would get the same output regardless of the compilation version, as it would use the default Java version set in my environment.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>&gt; mvn clean compile -Djava.compiler.version<span style="color:#f92672">=</span><span style="color:#ae81ff">17</span> exec:java -Dexec.mainClass<span style="color:#f92672">=</span>tech.vladflore.app.App
</span></span><span style="display:flex;"><span>&gt; mvn clean compile -Djava.compiler.version<span style="color:#f92672">=</span><span style="color:#ae81ff">21</span> exec:java -Dexec.mainClass<span style="color:#f92672">=</span>tech.vladflore.app.App
</span></span><span style="display:flex;"><span>&gt; mvn clean compile -Djava.compiler.version<span style="color:#f92672">=</span><span style="color:#ae81ff">25</span> exec:java -Dexec.mainClass<span style="color:#f92672">=</span>tech.vladflore.app.App
</span></span></code></pre></div><p>They would all output the same Java version, i.e. <code>25.0.1+8-27</code>, because that is the default Java version on my machine.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>&gt; java --version
</span></span><span style="display:flex;"><span>openjdk 25.0.1 2025-10-21
</span></span><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span>&gt; ls -l <span style="color:#e6db74">&#34;</span>$JAVA_HOME<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>/Users/vladflore/.sdkman/candidates/java/current -&gt; 25.0.1-open
</span></span><span style="display:flex;"><span>&gt; sdk current java
</span></span><span style="display:flex;"><span>Using java version 25.0.1-open
</span></span></code></pre></div><p>How do we run the project with different Java versions then?</p>
<p>One way is to use the <code>JAVA_HOME</code> environment variable to point to the desired Java version before running the project.</p>
<p>We can do this either by exporting the <code>JAVA_HOME</code> variable in the shell or by letting sdkman handle it for us.</p>
<p>Another way is to use the <code>exec-maven-plugin</code> <a href="https://www.mojohaus.org/exec-maven-plugin/" target="_blank">plugin</a>.</p>
<p>Add this to your <code>pom.xml</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#f92672">&lt;plugin&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;groupId&gt;</span>org.codehaus.mojo<span style="color:#f92672">&lt;/groupId&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;artifactId&gt;</span>exec-maven-plugin<span style="color:#f92672">&lt;/artifactId&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;version&gt;</span>3.1.0<span style="color:#f92672">&lt;/version&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;configuration&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;executable&gt;</span>${java.runtime.home}/bin/java<span style="color:#f92672">&lt;/executable&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;arguments&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&lt;argument&gt;</span>-cp<span style="color:#f92672">&lt;/argument&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&lt;argument&gt;</span>${project.build.outputDirectory}<span style="color:#f92672">&lt;/argument&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&lt;argument&gt;</span>${main.class}<span style="color:#f92672">&lt;/argument&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;/arguments&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;/configuration&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/plugin&gt;</span>
</span></span></code></pre></div><p>The <code>java.runtime.home</code> and <code>main.class</code> properties will be set when running Maven commands.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>&gt; mvn clean compile -Djava.compiler.version<span style="color:#f92672">=</span><span style="color:#ae81ff">17</span> exec:exec -Djava.runtime.home<span style="color:#f92672">=</span>/Users/vladflore/.sdkman/candidates/java/17.0.12-oracle -Dmain.class<span style="color:#f92672">=</span>tech.vladflore.app.App
</span></span></code></pre></div><p>This compiles and runs the project with Java 17.</p>
<p>Let&rsquo;s compile with 17 and run with 25.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>&gt; mvn clean compile -Djava.compiler.version<span style="color:#f92672">=</span><span style="color:#ae81ff">17</span> exec:exec -Djava.runtime.home<span style="color:#f92672">=</span>/Users/vladflore/.sdkman/candidates/java/25.0.1-open -Dmain.class<span style="color:#f92672">=</span>tech.vladflore.app.App
</span></span></code></pre></div><p>Let&rsquo;s compile with 25 and run with 17.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>&gt; mvn clean compile -Djava.compiler.version<span style="color:#f92672">=</span><span style="color:#ae81ff">25</span> exec:exec -Djava.runtime.home<span style="color:#f92672">=</span>/Users/vladflore/.sdkman/candidates/java/17.0.12-oracle -Dmain.class<span style="color:#f92672">=</span>tech.vladflore.app.App
</span></span><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span>💥💥💥
</span></span></code></pre></div><p>We get the following error:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>Error: LinkageError occurred <span style="color:#66d9ef">while</span> loading main class tech.vladflore.app.App
</span></span><span style="display:flex;"><span>java.lang.UnsupportedClassVersionError: tech/vladflore/app/App has been compiled by a more recent version of the Java Runtime <span style="color:#f92672">(</span>class file version 69.0<span style="color:#f92672">)</span>, this version of the Java Runtime only recognizes class file versions up to 61.0
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>ERROR<span style="color:#f92672">]</span> Command execution failed.
</span></span></code></pre></div><p>which is expected since we are trying to run a class compiled with a newer Java version on an older Java runtime.</p>
<h2 id="conclusion">Conclusion</h2>
<p>In this post, we explored how to manage multiple Java versions in a Maven project using Maven Toolchains for compilation and the <code>exec-maven-plugin</code> for running the application with different Java runtimes. This approach allows developers to test and run their applications across various Java versions seamlessly.</p>
]]></content>
        </item>
        
        <item>
            <title>Git bisect</title>
            <link>https://vladflore.tech/posts/2026/01/git-bisect/</link>
            <pubDate>Thu, 08 Jan 2026 00:00:00 +0000</pubDate>
            
            <guid>https://vladflore.tech/posts/2026/01/git-bisect/</guid>
            <description>&lt;h2 id=&#34;meet-git-bisect&#34;&gt;Meet &lt;code&gt;git bisect&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;When you have a large codebase and a bug has been introduced somewhere in the history, finding the exact commit that introduced the bug can be challenging. This is where &lt;code&gt;git bisect&lt;/code&gt; comes in handy. It automates the process of binary searching through your commit history to find the offending commit.&lt;/p&gt;
&lt;h3 id=&#34;how-it-works&#34;&gt;How it works&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;start the bisect process by running &lt;code&gt;git bisect start&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;find a known bad commit (the one with the bug) and mark it as bad using &lt;code&gt;git bisect bad &amp;lt;bad-commit-hash&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;find a known good commit (the one without the bug) and mark it as good using &lt;code&gt;git bisect good &amp;lt;good-commit-hash&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Git will now checkout a commit halfway between the good and bad commits. You need to test this commit to see if the bug is present&lt;/li&gt;
&lt;li&gt;if the bug is present, mark the commit as bad using &lt;code&gt;git bisect bad&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;if the bug is not present, mark the commit as good using &lt;code&gt;git bisect good&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;repeat the testing and marking process until Git narrows down to the exact commit that introduced the bug&lt;/li&gt;
&lt;li&gt;once the bad commit is found, you can end the bisect process by running &lt;code&gt;git bisect reset&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This might sound a bit tedious, but it can save you a lot of time compared to manually checking each commit. Additionally, you can automate the testing and marking process using &lt;code&gt;git bisect run &amp;lt;script&amp;gt;&lt;/code&gt;, where &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; is a script that tests the code and returns an exit code indicating whether the commit is good or bad.&lt;/p&gt;</description>
            <content type="html"><![CDATA[<h2 id="meet-git-bisect">Meet <code>git bisect</code></h2>
<p>When you have a large codebase and a bug has been introduced somewhere in the history, finding the exact commit that introduced the bug can be challenging. This is where <code>git bisect</code> comes in handy. It automates the process of binary searching through your commit history to find the offending commit.</p>
<h3 id="how-it-works">How it works</h3>
<ul>
<li>start the bisect process by running <code>git bisect start</code></li>
<li>find a known bad commit (the one with the bug) and mark it as bad using <code>git bisect bad &lt;bad-commit-hash&gt;</code></li>
<li>find a known good commit (the one without the bug) and mark it as good using <code>git bisect good &lt;good-commit-hash&gt;</code></li>
<li>Git will now checkout a commit halfway between the good and bad commits. You need to test this commit to see if the bug is present</li>
<li>if the bug is present, mark the commit as bad using <code>git bisect bad</code></li>
<li>if the bug is not present, mark the commit as good using <code>git bisect good</code></li>
<li>repeat the testing and marking process until Git narrows down to the exact commit that introduced the bug</li>
<li>once the bad commit is found, you can end the bisect process by running <code>git bisect reset</code></li>
</ul>
<p>This might sound a bit tedious, but it can save you a lot of time compared to manually checking each commit. Additionally, you can automate the testing and marking process using <code>git bisect run &lt;script&gt;</code>, where <code>&lt;script&gt;</code> is a script that tests the code and returns an exit code indicating whether the commit is good or bad.</p>
<h3 id="example">Example</h3>
<p>Make sure you have Maven and Java installed. My setup is as follows:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>mvn --version
</span></span><span style="display:flex;"><span>Apache Maven 3.9.11 ...
</span></span><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span>Java version: 25.0.1, vendor: Oracle Corporation, runtime: /Users/vladflore/.sdkman/candidates/java/25.0.1-open
</span></span><span style="display:flex;"><span>...
</span></span></code></pre></div><blockquote>
<p><strong>Note:</strong>
You can use SDKMAN to easily manage multiple versions of Java and Maven on your machine. Check it out at <a href="https://sdkman.io/" target="_blank">sdkman.io</a>.</p>
</blockquote>
<p>Let&rsquo;s create a simple Java project using Maven:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>mvn archetype:generate <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>  -DgroupId<span style="color:#f92672">=</span>tech.vladflore.app <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>  -DartifactId<span style="color:#f92672">=</span>bisect <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>  -DarchetypeArtifactId<span style="color:#f92672">=</span>maven-archetype-quickstart <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>  -DarchetypeGroupId<span style="color:#f92672">=</span>org.apache.maven.archetypes <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span>  -DinteractiveMode<span style="color:#f92672">=</span>false
</span></span></code></pre></div><p>Open it in your favorite IDE and implement a simple binary search algorithm in <code>App.java</code>. Then, write some unit tests in <code>AppTest.java</code>.</p>
<p>In <code>App.java</code>, implement the binary search algorithm:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">package</span> tech.vladflore.app;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">App</span> {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">int</span> <span style="color:#a6e22e">binarySearch</span>(<span style="color:#66d9ef">int</span><span style="color:#f92672">[]</span> arr, <span style="color:#66d9ef">int</span> target) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (arr <span style="color:#f92672">==</span> <span style="color:#66d9ef">null</span> <span style="color:#f92672">||</span> arr.<span style="color:#a6e22e">length</span> <span style="color:#f92672">==</span> 0) {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">return</span> <span style="color:#f92672">-</span>1;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">int</span> left <span style="color:#f92672">=</span> 0;
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">int</span> right <span style="color:#f92672">=</span> arr.<span style="color:#a6e22e">length</span> <span style="color:#f92672">-</span> 1;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">while</span> (left <span style="color:#f92672">&lt;=</span> right) {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">int</span> mid <span style="color:#f92672">=</span> left <span style="color:#f92672">+</span> (right <span style="color:#f92672">-</span> left) <span style="color:#f92672">/</span> 2;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">if</span> (arr<span style="color:#f92672">[</span>mid<span style="color:#f92672">]</span> <span style="color:#f92672">==</span> target) {
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">return</span> mid;
</span></span><span style="display:flex;"><span>            } <span style="color:#66d9ef">else</span> <span style="color:#66d9ef">if</span> (arr<span style="color:#f92672">[</span>mid<span style="color:#f92672">]</span> <span style="color:#f92672">&lt;</span> target) {
</span></span><span style="display:flex;"><span>                left <span style="color:#f92672">=</span> mid <span style="color:#f92672">+</span> 1;
</span></span><span style="display:flex;"><span>            } <span style="color:#66d9ef">else</span> {
</span></span><span style="display:flex;"><span>                right <span style="color:#f92672">=</span> mid <span style="color:#f92672">-</span> 1;
</span></span><span style="display:flex;"><span>            }
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#f92672">-</span>1;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>In <code>AppTest.java</code>, write unit tests for the binary search method:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">package</span> tech.vladflore.app;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">import static</span> org.junit.jupiter.api.Assertions.assertEquals;
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> org.junit.jupiter.api.Test;
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> org.junit.jupiter.params.ParameterizedTest;
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> org.junit.jupiter.params.provider.CsvSource;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">AppTest</span> {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">@Test</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">testBinarySearch_ElementFound</span>() {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">int</span><span style="color:#f92672">[]</span> arr <span style="color:#f92672">=</span> {1, 3, 5, 7, 9, 11, 13};
</span></span><span style="display:flex;"><span>        assertEquals(3, App.<span style="color:#a6e22e">binarySearch</span>(arr, 7));
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">@Test</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">testBinarySearch_ElementNotFound</span>() {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">int</span><span style="color:#f92672">[]</span> arr <span style="color:#f92672">=</span> {1, 3, 5, 7, 9, 11, 13};
</span></span><span style="display:flex;"><span>        assertEquals(<span style="color:#f92672">-</span>1, App.<span style="color:#a6e22e">binarySearch</span>(arr, 6));
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">@Test</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">testBinarySearch_FirstElement</span>() {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">int</span><span style="color:#f92672">[]</span> arr <span style="color:#f92672">=</span> {1, 3, 5, 7, 9, 11, 13};
</span></span><span style="display:flex;"><span>        assertEquals(0, App.<span style="color:#a6e22e">binarySearch</span>(arr, 1));
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">@Test</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">testBinarySearch_LastElement</span>() {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">int</span><span style="color:#f92672">[]</span> arr <span style="color:#f92672">=</span> {1, 3, 5, 7, 9, 11, 13};
</span></span><span style="display:flex;"><span>        assertEquals(6, App.<span style="color:#a6e22e">binarySearch</span>(arr, 13));
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">@Test</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">testBinarySearch_SingleElement_Found</span>() {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">int</span><span style="color:#f92672">[]</span> arr <span style="color:#f92672">=</span> {5};
</span></span><span style="display:flex;"><span>        assertEquals(0, App.<span style="color:#a6e22e">binarySearch</span>(arr, 5));
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">@Test</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">testBinarySearch_SingleElement_NotFound</span>() {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">int</span><span style="color:#f92672">[]</span> arr <span style="color:#f92672">=</span> {5};
</span></span><span style="display:flex;"><span>        assertEquals(<span style="color:#f92672">-</span>1, App.<span style="color:#a6e22e">binarySearch</span>(arr, 3));
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">@Test</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">testBinarySearch_EmptyArray</span>() {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">int</span><span style="color:#f92672">[]</span> arr <span style="color:#f92672">=</span> {};
</span></span><span style="display:flex;"><span>        assertEquals(<span style="color:#f92672">-</span>1, App.<span style="color:#a6e22e">binarySearch</span>(arr, 5));
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">@Test</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">testBinarySearch_NullArray</span>() {
</span></span><span style="display:flex;"><span>        assertEquals(<span style="color:#f92672">-</span>1, App.<span style="color:#a6e22e">binarySearch</span>(<span style="color:#66d9ef">null</span>, 5));
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">@Test</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">testBinarySearch_LargeArray</span>() {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">int</span><span style="color:#f92672">[]</span> arr <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#66d9ef">int</span><span style="color:#f92672">[</span>1000<span style="color:#f92672">]</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">int</span> i <span style="color:#f92672">=</span> 0; i <span style="color:#f92672">&lt;</span> arr.<span style="color:#a6e22e">length</span>; i<span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>            arr<span style="color:#f92672">[</span>i<span style="color:#f92672">]</span> <span style="color:#f92672">=</span> i <span style="color:#f92672">*</span> 2;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>        assertEquals(500, App.<span style="color:#a6e22e">binarySearch</span>(arr, 1000));
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">@ParameterizedTest</span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">@CsvSource</span>({
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;1, 0&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;3, 1&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;5, 2&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;7, 3&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;9, 4&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;11, 5&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;13, 6&#34;</span>
</span></span><span style="display:flex;"><span>    })
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">testBinarySearch_ParameterizedAllElements</span>(<span style="color:#66d9ef">int</span> target, <span style="color:#66d9ef">int</span> expectedIndex) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">int</span><span style="color:#f92672">[]</span> arr <span style="color:#f92672">=</span> {1, 3, 5, 7, 9, 11, 13};
</span></span><span style="display:flex;"><span>        assertEquals(expectedIndex, App.<span style="color:#a6e22e">binarySearch</span>(arr, target));
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Run <code>mvn clean test</code> to ensure all tests pass.</p>
<p>Commit everything.</p>
<p>Right now the git history should show one commit.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>git log --oneline
</span></span><span style="display:flex;"><span>827ee9a9aa5451626aec62849bd11f1f440b457b <span style="color:#f92672">(</span>HEAD -&gt; main<span style="color:#f92672">)</span> First commit
</span></span></code></pre></div><p>For the current implementation to work, the array must be sorted in ascending order. Let&rsquo;s implement the invariant that the array is sorted before performing the binary search. Create a new commit with this change.
Add this in <code>App.java</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">int</span> i <span style="color:#f92672">=</span> 0; i <span style="color:#f92672">&lt;</span> arr.<span style="color:#a6e22e">length</span> <span style="color:#f92672">-</span> 1; i<span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (arr<span style="color:#f92672">[</span>i<span style="color:#f92672">]</span> <span style="color:#f92672">&gt;</span> arr<span style="color:#f92672">[</span>i <span style="color:#f92672">+</span> 1<span style="color:#f92672">]</span>) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">throw</span> <span style="color:#66d9ef">new</span> IllegalArgumentException(<span style="color:#e6db74">&#34;Array must be sorted in ascending order&#34;</span>);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>And the test for it in <code>AppTest.java</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#a6e22e">@Test</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">testBinarySearch_UnsortedArray_ThrowsException</span>() {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">int</span><span style="color:#f92672">[]</span> arr <span style="color:#f92672">=</span> {5, 3, 7, 1, 9};
</span></span><span style="display:flex;"><span>    Assertions.<span style="color:#a6e22e">assertThrows</span>(IllegalArgumentException.<span style="color:#a6e22e">class</span>, () <span style="color:#f92672">-&gt;</span> {
</span></span><span style="display:flex;"><span>        App.<span style="color:#a6e22e">binarySearch</span>(arr, 7);
</span></span><span style="display:flex;"><span>    });
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Right now the git history should show two commits.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>git log --oneline
</span></span><span style="display:flex;"><span>9a81359b0c2e67b26ffbb9e51ea3cc2ccaa5a38c <span style="color:#f92672">(</span>HEAD -&gt; main<span style="color:#f92672">)</span> Implement invariant
</span></span><span style="display:flex;"><span>827ee9a9aa5451626aec62849bd11f1f440b457b First commit
</span></span></code></pre></div><p>Now, let&rsquo;s introduce a bug in the implementation of the binary search algorithm.</p>
<p>Change the condition in the while loop from <code>left &lt;= right</code> to <code>left &lt; right</code> in <code>App.java</code>, and commit the change.</p>
<p>Now the git history should show three commits.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>git log --oneline
</span></span><span style="display:flex;"><span>e7431eacefd1fafbd46e3b276b687e08e5fa987a <span style="color:#f92672">(</span>HEAD -&gt; main<span style="color:#f92672">)</span> Introduce bug
</span></span><span style="display:flex;"><span>9a81359b0c2e67b26ffbb9e51ea3cc2ccaa5a38c Implement invariant
</span></span><span style="display:flex;"><span>827ee9a9aa5451626aec62849bd11f1f440b457b First commit
</span></span></code></pre></div><p>Let&rsquo;s add some more commits to make the history longer. All of them would be bad commits. Use the following <code>git</code> command to add three more empty commits (⚠️ do not do this in a real project):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span><span style="color:#66d9ef">for</span> i in <span style="color:#f92672">{</span>2..4<span style="color:#f92672">}</span>; <span style="color:#66d9ef">do</span> git commit --allow-empty -m <span style="color:#e6db74">&#34;Bad commit </span>$i<span style="color:#e6db74">&#34;</span>; <span style="color:#66d9ef">done</span>
</span></span></code></pre></div><p>Now the git history should show six commits.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>git log --oneline
</span></span><span style="display:flex;"><span>345d5f1ace5b93665583ec5d6e33c6a92c5cec95 <span style="color:#f92672">(</span>HEAD -&gt; main<span style="color:#f92672">)</span> Bad commit <span style="color:#ae81ff">4</span>
</span></span><span style="display:flex;"><span>2dbac1937ed41b26103c022b6579bd855932a8d1 Bad commit <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span>46f9a561f097690f86bbb1cf52a94f23294d7f41 Bad commit <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>e7431eacefd1fafbd46e3b276b687e08e5fa987a Introduce bug
</span></span><span style="display:flex;"><span>9a81359b0c2e67b26ffbb9e51ea3cc2ccaa5a38c Implement invariant
</span></span><span style="display:flex;"><span>827ee9a9aa5451626aec62849bd11f1f440b457b First commit
</span></span></code></pre></div><p>We want to find the commit that introduced the bug, i.e. <code>e7431ea</code>. We could do this manually, by following the steps outlined above, or we could use <code>git bisect run</code> to automate the process. For this we need some script that would run the tests and return exit code <code>0</code> if all tests pass, or <code>1</code> if any test fails. Create a file named <code>test.sh</code> with the following content:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e">#!/bin/bash
</span></span></span><span style="display:flex;"><span>mvn clean test
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>exit_code<span style="color:#f92672">=</span>$?
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> $exit_code -ne <span style="color:#ae81ff">0</span> <span style="color:#f92672">]</span>;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>  exit <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">fi</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>exit <span style="color:#ae81ff">0</span>
</span></span></code></pre></div><p>Make the script executable by running <code>chmod +x test.sh</code>.</p>
<p>Now, run the following:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>git bisect start
</span></span><span style="display:flex;"><span>git bisect bad HEAD
</span></span><span style="display:flex;"><span>git bisect good 9a81359b0c2e67b26ffbb
</span></span><span style="display:flex;"><span>git bisect run ./test.sh
</span></span></code></pre></div><p>Git will now automatically checkout commits, run the tests using the provided script, and mark commits as good or bad based on the exit code of the script. After a few iterations, it will identify the commit that introduced the bug.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>e7431eacefd1fafbd46e3b276b687e08e5fa987a is the first bad commit
</span></span><span style="display:flex;"><span>commit e7431eacefd1fafbd46e3b276b687e08e5fa987a
</span></span><span style="display:flex;"><span>Author: Vlad Flore &lt;flore.vlad@gmail.com&gt;
</span></span><span style="display:flex;"><span>Date:   Wed Jan <span style="color:#ae81ff">7</span> 17:03:19 <span style="color:#ae81ff">2026</span> +0100
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    Introduce bug
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span>bisect found first bad commit
</span></span></code></pre></div><p>So now we know that the commit <code>e7431ea</code> is the one that introduced the bug. To end the bisect session and return to the original HEAD, run:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>git bisect reset
</span></span></code></pre></div><p>We can compare the identified bad commit with the previous good commit to see what changed:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>git diff 9a81359 e7431ea | cat
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>diff --git a/src/main/java/tech/vladflore/app/App.java b/src/main/java/tech/vladflore/app/App.java
</span></span><span style="display:flex;"><span>index 4084581..588b0aa <span style="color:#ae81ff">100644</span>
</span></span><span style="display:flex;"><span>--- a/src/main/java/tech/vladflore/app/App.java
</span></span><span style="display:flex;"><span>+++ b/src/main/java/tech/vladflore/app/App.java
</span></span><span style="display:flex;"><span>@@ -16,7 +16,7 @@ public class App <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>         int left <span style="color:#f92672">=</span> 0;
</span></span><span style="display:flex;"><span>         int right <span style="color:#f92672">=</span> arr.length - 1;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>-        <span style="color:#66d9ef">while</span> <span style="color:#f92672">(</span>left &lt;<span style="color:#f92672">=</span> right<span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>+        <span style="color:#66d9ef">while</span> <span style="color:#f92672">(</span>left &lt; right<span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>             int mid <span style="color:#f92672">=</span> left + <span style="color:#f92672">(</span>right - left<span style="color:#f92672">)</span> / 2;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>             <span style="color:#66d9ef">if</span> <span style="color:#f92672">(</span>arr<span style="color:#f92672">[</span>mid<span style="color:#f92672">]</span> <span style="color:#f92672">==</span> target<span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
</span></span></code></pre></div><p>And here is our bug!</p>
<h3 id="conclusion">Conclusion</h3>
<p><code>git bisect</code> is a powerful tool that can save you a lot of time when trying to find the commit that introduced a bug. By automating the binary search process, it allows you to quickly narrow down the range of commits to investigate, making it easier to identify and fix issues in your codebase.</p>
]]></content>
        </item>
        
        <item>
            <title>Java 25</title>
            <link>https://vladflore.tech/posts/2026/01/java-25/</link>
            <pubDate>Wed, 07 Jan 2026 00:00:00 +0000</pubDate>
            
            <guid>https://vladflore.tech/posts/2026/01/java-25/</guid>
            <description>&lt;h2 id=&#34;meet-java-25&#34;&gt;Meet Java 25&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://openjdk.org/projects/jdk/25/&#34; target=&#34;_blank&#34;&gt;JDK 25&lt;/a&gt; reached General Availability on 16 September 2025.&lt;/p&gt;
&lt;p&gt;Java 25 continues the trend toward safer concurrency, reduced boilerplate, and better ergonomics—especially for modern, cloud-native and virtual-thread-heavy applications.&lt;/p&gt;
&lt;p&gt;Some of the most notable features include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Scoped Values&lt;/li&gt;
&lt;li&gt;Module Import Declarations&lt;/li&gt;
&lt;li&gt;Compact Source Files and Instance Main Methods&lt;/li&gt;
&lt;li&gt;Flexible Constructor Bodies&lt;/li&gt;
&lt;li&gt;Compact Object Headers&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are many more features and improvements in this release, but in this post, I will highlight just a few, for a comprehensive list, check out the &lt;a href=&#34;https://openjdk.org/projects/jdk/25/&#34; target=&#34;_blank&#34;&gt;official JDK 25 release notes&lt;/a&gt;.&lt;/p&gt;</description>
            <content type="html"><![CDATA[<h2 id="meet-java-25">Meet Java 25</h2>
<p><a href="https://openjdk.org/projects/jdk/25/" target="_blank">JDK 25</a> reached General Availability on 16 September 2025.</p>
<p>Java 25 continues the trend toward safer concurrency, reduced boilerplate, and better ergonomics—especially for modern, cloud-native and virtual-thread-heavy applications.</p>
<p>Some of the most notable features include:</p>
<ul>
<li>Scoped Values</li>
<li>Module Import Declarations</li>
<li>Compact Source Files and Instance Main Methods</li>
<li>Flexible Constructor Bodies</li>
<li>Compact Object Headers</li>
</ul>
<p>There are many more features and improvements in this release, but in this post, I will highlight just a few, for a comprehensive list, check out the <a href="https://openjdk.org/projects/jdk/25/" target="_blank">official JDK 25 release notes</a>.</p>
<h3 id="scoped-values">Scoped Values</h3>
<p><a href="https://openjdk.org/jeps/506" target="_blank">JEP 506</a></p>
<p>Scoped Values provide a way to share immutable context data across a well-defined execution scope, without relying on thread-local storage. They are designed for modern Java, especially in the presence of virtual threads and structured concurrency.</p>
<p>Typical use cases include propagating request-scoped data such as user identity, trace IDs, or transaction metadata—without explicitly passing parameters through every method call.</p>
<blockquote>
<p><strong>The big picture:</strong></p>
<p><code>ThreadLocal</code> → thread-bound mutable state (legacy, problematic with virtual threads)</p>
<p><code>ScopedValue</code> → scope-bound immutable context (modern, safe, structured)</p>
</blockquote>
<p>Let&rsquo;s look at a simple example of how Scoped Values work and contrast them with ThreadLocal. The example below demonstrates how to implement <em>tracing</em> of operations using both approaches.</p>
<blockquote>
<p><strong>About tracing:</strong></p>
<p>Tracing is a technique used to monitor and log the execution of operations within an application. It helps in understanding the flow of requests, diagnosing issues, and analyzing performance by recording key events and data points during the execution of code. It relies on passing context information, like <code>trace ID</code>s and/or <code>span ID</code>s, through various layers of the application.</p>
</blockquote>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">import</span> java.time.Instant;
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> java.util.UUID;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">TracingDemo</span> {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">record</span> <span style="color:#a6e22e">TraceContext</span>(String traceId, String spanId) {}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">final</span> ScopedValue<span style="color:#f92672">&lt;</span>TraceContext<span style="color:#f92672">&gt;</span> TRACE <span style="color:#f92672">=</span> ScopedValue.<span style="color:#a6e22e">newInstance</span>();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">main</span>(String<span style="color:#f92672">[]</span> args) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">new</span> TracingDemo().<span style="color:#a6e22e">handleRequest</span>();
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">handleRequest</span>() {
</span></span><span style="display:flex;"><span>    TraceContext root <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> TraceContext(newTraceId(), <span style="color:#e6db74">&#34;root&#34;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    ScopedValue.<span style="color:#a6e22e">where</span>(TRACE, root).<span style="color:#a6e22e">run</span>(
</span></span><span style="display:flex;"><span>            () <span style="color:#f92672">-&gt;</span> {
</span></span><span style="display:flex;"><span>              log(<span style="color:#e6db74">&#34;Handling request&#34;</span>);
</span></span><span style="display:flex;"><span>              queryDatabase();
</span></span><span style="display:flex;"><span>              callExternalService();
</span></span><span style="display:flex;"><span>              log(<span style="color:#e6db74">&#34;Request completed&#34;</span>);
</span></span><span style="display:flex;"><span>            }
</span></span><span style="display:flex;"><span>    );
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">queryDatabase</span>() {
</span></span><span style="display:flex;"><span>    withSpan(
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;db&#34;</span>,
</span></span><span style="display:flex;"><span>        () <span style="color:#f92672">-&gt;</span> {
</span></span><span style="display:flex;"><span>          sleep(300);
</span></span><span style="display:flex;"><span>          log(<span style="color:#e6db74">&#34;Querying database&#34;</span>);
</span></span><span style="display:flex;"><span>        });
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">callExternalService</span>() {
</span></span><span style="display:flex;"><span>    withSpan(
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;http&#34;</span>,
</span></span><span style="display:flex;"><span>        () <span style="color:#f92672">-&gt;</span> {
</span></span><span style="display:flex;"><span>          sleep(500);
</span></span><span style="display:flex;"><span>          log(<span style="color:#e6db74">&#34;Calling external service&#34;</span>);
</span></span><span style="display:flex;"><span>        });
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">withSpan</span>(String spanName, Runnable task) {
</span></span><span style="display:flex;"><span>    TraceContext parent <span style="color:#f92672">=</span> TRACE.<span style="color:#a6e22e">get</span>();
</span></span><span style="display:flex;"><span>    TraceContext child <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> TraceContext(parent.<span style="color:#a6e22e">traceId</span>(), spanName);
</span></span><span style="display:flex;"><span>    ScopedValue.<span style="color:#a6e22e">where</span>(TRACE, child).<span style="color:#a6e22e">run</span>(task);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">log</span>(String message) {
</span></span><span style="display:flex;"><span>    TraceContext ctx <span style="color:#f92672">=</span> TRACE.<span style="color:#a6e22e">get</span>();
</span></span><span style="display:flex;"><span>    System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">printf</span>(
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;%s [trace=%s span=%s] %s%n&#34;</span>, Instant.<span style="color:#a6e22e">now</span>(), ctx.<span style="color:#a6e22e">traceId</span>(), ctx.<span style="color:#a6e22e">spanId</span>(), message);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">static</span> String <span style="color:#a6e22e">newTraceId</span>() {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#e6db74">&#34;trace-&#34;</span> <span style="color:#f92672">+</span> UUID.<span style="color:#a6e22e">randomUUID</span>();
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">sleep</span>(<span style="color:#66d9ef">long</span> millis) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">try</span> {
</span></span><span style="display:flex;"><span>      Thread.<span style="color:#a6e22e">sleep</span>(millis);
</span></span><span style="display:flex;"><span>    } <span style="color:#66d9ef">catch</span> (InterruptedException e) {
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">throw</span> <span style="color:#66d9ef">new</span> RuntimeException(e);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Running the code above with <code>java --enable-preview TracingDemo.java</code> produces output similar to the following:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>2026-01-02T14:01:18.638861Z <span style="color:#f92672">[</span>trace<span style="color:#f92672">=</span>trace-4c3f324f-bc37-4141-a0dc-8062c31423ea span<span style="color:#f92672">=</span>root<span style="color:#f92672">]</span> Handling request
</span></span><span style="display:flex;"><span>2026-01-02T14:01:18.943390Z <span style="color:#f92672">[</span>trace<span style="color:#f92672">=</span>trace-4c3f324f-bc37-4141-a0dc-8062c31423ea span<span style="color:#f92672">=</span>db<span style="color:#f92672">]</span> Querying database
</span></span><span style="display:flex;"><span>2026-01-02T14:01:19.452530Z <span style="color:#f92672">[</span>trace<span style="color:#f92672">=</span>trace-4c3f324f-bc37-4141-a0dc-8062c31423ea span<span style="color:#f92672">=</span>http<span style="color:#f92672">]</span> Calling external service
</span></span><span style="display:flex;"><span>2026-01-02T14:01:19.453604Z <span style="color:#f92672">[</span>trace<span style="color:#f92672">=</span>trace-4c3f324f-bc37-4141-a0dc-8062c31423ea span<span style="color:#f92672">=</span>root<span style="color:#f92672">]</span> Request completed
</span></span></code></pre></div><p>Note that the <code>traceId</code> remains consistent across the different operations, while the <code>spanId</code> changes to reflect the current operation being performed. This demonstrates how Scoped Values can effectively propagate context information through various layers of an application without <em>explicit parameter passing</em>.</p>
<p>Contrasting this with a <code>ThreadLocal</code> approach would involve more boilerplate code. Here&rsquo;s how the same tracing functionality would look using <code>ThreadLocal</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">import</span> java.time.Instant;
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> java.util.UUID;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">TracingDemo</span> {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">record</span> <span style="color:#a6e22e">TraceContext</span>(String traceId, String spanId) {}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">final</span> ThreadLocal<span style="color:#f92672">&lt;</span>TraceContext<span style="color:#f92672">&gt;</span> TRACE <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> ThreadLocal<span style="color:#f92672">&lt;&gt;</span>(); <span style="color:#75715e">// [!code highlight]</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">main</span>(String<span style="color:#f92672">[]</span> args) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">new</span> TracingDemo().<span style="color:#a6e22e">handleRequest</span>();
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">handleRequest</span>() {
</span></span><span style="display:flex;"><span>    TraceContext root <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> TraceContext(newTraceId(), <span style="color:#e6db74">&#34;root&#34;</span>);
</span></span><span style="display:flex;"><span>    TRACE.<span style="color:#a6e22e">set</span>(root); <span style="color:#75715e">// [!code highlight]</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">try</span> {
</span></span><span style="display:flex;"><span>      log(<span style="color:#e6db74">&#34;Handling request&#34;</span>);
</span></span><span style="display:flex;"><span>      queryDatabase();
</span></span><span style="display:flex;"><span>      callExternalService();
</span></span><span style="display:flex;"><span>      log(<span style="color:#e6db74">&#34;Request completed&#34;</span>);
</span></span><span style="display:flex;"><span>    } <span style="color:#66d9ef">finally</span> {
</span></span><span style="display:flex;"><span>      <span style="color:#75715e">// ⚠️ must remember to clean up, or else trace leaks!</span>
</span></span><span style="display:flex;"><span>      TRACE.<span style="color:#a6e22e">remove</span>(); <span style="color:#75715e">// [!code highlight]</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">queryDatabase</span>() {
</span></span><span style="display:flex;"><span>    withSpan(
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;db&#34;</span>,
</span></span><span style="display:flex;"><span>        () <span style="color:#f92672">-&gt;</span> {
</span></span><span style="display:flex;"><span>          sleep(300);
</span></span><span style="display:flex;"><span>          log(<span style="color:#e6db74">&#34;Querying database&#34;</span>);
</span></span><span style="display:flex;"><span>        });
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">callExternalService</span>() {
</span></span><span style="display:flex;"><span>    withSpan(
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;http&#34;</span>,
</span></span><span style="display:flex;"><span>        () <span style="color:#f92672">-&gt;</span> {
</span></span><span style="display:flex;"><span>          sleep(500);
</span></span><span style="display:flex;"><span>          log(<span style="color:#e6db74">&#34;Calling external service&#34;</span>);
</span></span><span style="display:flex;"><span>        });
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">withSpan</span>(String spanName, Runnable task) {
</span></span><span style="display:flex;"><span>    TraceContext parent <span style="color:#f92672">=</span> TRACE.<span style="color:#a6e22e">get</span>();
</span></span><span style="display:flex;"><span>    TraceContext child <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> TraceContext(parent.<span style="color:#a6e22e">traceId</span>(), spanName);
</span></span><span style="display:flex;"><span>    TRACE.<span style="color:#a6e22e">set</span>(child); <span style="color:#75715e">// [!code highlight]</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">try</span> {
</span></span><span style="display:flex;"><span>      task.<span style="color:#a6e22e">run</span>();
</span></span><span style="display:flex;"><span>    } <span style="color:#66d9ef">finally</span> {
</span></span><span style="display:flex;"><span>      <span style="color:#75715e">// ⚠️ must remember to restore previous context</span>
</span></span><span style="display:flex;"><span>      TRACE.<span style="color:#a6e22e">set</span>(parent); <span style="color:#75715e">// [!code highlight]</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">log</span>(String message) {
</span></span><span style="display:flex;"><span>    TraceContext ctx <span style="color:#f92672">=</span> TRACE.<span style="color:#a6e22e">get</span>();
</span></span><span style="display:flex;"><span>    System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">printf</span>(
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;%s [trace=%s span=%s] %s%n&#34;</span>, Instant.<span style="color:#a6e22e">now</span>(), ctx.<span style="color:#a6e22e">traceId</span>(), ctx.<span style="color:#a6e22e">spanId</span>(), message);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">static</span> String <span style="color:#a6e22e">newTraceId</span>() {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#e6db74">&#34;trace-&#34;</span> <span style="color:#f92672">+</span> UUID.<span style="color:#a6e22e">randomUUID</span>();
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">sleep</span>(<span style="color:#66d9ef">long</span> millis) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">try</span> {
</span></span><span style="display:flex;"><span>      Thread.<span style="color:#a6e22e">sleep</span>(millis);
</span></span><span style="display:flex;"><span>    } <span style="color:#66d9ef">catch</span> (InterruptedException e) {
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">throw</span> <span style="color:#66d9ef">new</span> RuntimeException(e);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This approach produces the same output as the Scoped Values example, but can be more error-prone:</p>
<ul>
<li>forgotten cleanup → trace leaks</li>
<li>exceptions break restoration</li>
<li>parallel execution loses context</li>
<li>virtual threads make it worse</li>
<li>nested spans are fragile</li>
</ul>
<p>Takeaway: Scoped Values make contextual data propagation explicit, safe, and composable—without the lifecycle hazards of ThreadLocal.</p>
<h3 id="module-import-declarations">Module Import Declarations</h3>
<p><a href="https://openjdk.org/jeps/511" target="_blank">JEP 511</a></p>
<p>This feature introduces a new way to import all of the packages exported by a module using a single import statement. Two immediate benefits of this feature are:</p>
<ul>
<li>avoid the noise of multiple type-import-on-demand declarations (e.g., <code>import com.foo.bar.*</code>)</li>
<li>beginner-friendly way to start using core Java APIs and third-party libraries and fundamental Java classes without having to learn where they are located in a package hierarchy.</li>
</ul>
<p>The syntax for a module import declaration is: <code>import module &lt;module-name&gt;;</code></p>
<p>Let&rsquo;s look at an example of how to use module import declarations.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">import</span> module java.<span style="color:#a6e22e">base</span>; <span style="color:#75715e">// [!code highlight]</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">ModuleImportDemo</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">main</span>(String<span style="color:#f92672">[]</span> args) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> strings <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> String<span style="color:#f92672">[]</span> {<span style="color:#e6db74">&#34;apple&#34;</span>, <span style="color:#e6db74">&#34;berry&#34;</span>, <span style="color:#e6db74">&#34;citrus&#34;</span>};
</span></span><span style="display:flex;"><span>    Function<span style="color:#f92672">&lt;</span>String, String<span style="color:#f92672">&gt;</span> firstLetterUppercase <span style="color:#f92672">=</span> s <span style="color:#f92672">-&gt;</span> s.<span style="color:#a6e22e">toUpperCase</span>().<span style="color:#a6e22e">substring</span>(0, 1);
</span></span><span style="display:flex;"><span>    Map<span style="color:#f92672">&lt;</span>String, String<span style="color:#f92672">&gt;</span> map <span style="color:#f92672">=</span>
</span></span><span style="display:flex;"><span>        Stream.<span style="color:#a6e22e">of</span>(strings).<span style="color:#a6e22e">collect</span>(Collectors.<span style="color:#a6e22e">toMap</span>(firstLetterUppercase, Function.<span style="color:#a6e22e">identity</span>()));
</span></span><span style="display:flex;"><span>    IO.<span style="color:#a6e22e">println</span>(map);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Without the module import declaration, you would need to either import each type individually or use type-import-on-demand declarations, i.e.:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">import</span> java.util.Map;
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> java.util.function.Function;
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> java.util.stream.Collectors;
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> java.util.stream.Stream;
</span></span></code></pre></div><p>or</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">import</span> java.util.*;
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> java.util.function.*;
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> java.util.stream.*;
</span></span></code></pre></div><p>For compact source files, the <code>java.base</code> module is <em>implicitly</em> imported, which means that the example above could be written like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#75715e">// Compact source file with implicit java.base module import</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">main</span>() {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> strings <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> String<span style="color:#f92672">[]</span> {<span style="color:#e6db74">&#34;apple&#34;</span>, <span style="color:#e6db74">&#34;berry&#34;</span>, <span style="color:#e6db74">&#34;citrus&#34;</span>};
</span></span><span style="display:flex;"><span>    Function<span style="color:#f92672">&lt;</span>String, String<span style="color:#f92672">&gt;</span> firstLetterUppercase <span style="color:#f92672">=</span> s <span style="color:#f92672">-&gt;</span> s.<span style="color:#a6e22e">toUpperCase</span>().<span style="color:#a6e22e">substring</span>(0, 1);
</span></span><span style="display:flex;"><span>    Map<span style="color:#f92672">&lt;</span>String, String<span style="color:#f92672">&gt;</span> map <span style="color:#f92672">=</span>
</span></span><span style="display:flex;"><span>        Stream.<span style="color:#a6e22e">of</span>(strings).<span style="color:#a6e22e">collect</span>(Collectors.<span style="color:#a6e22e">toMap</span>(firstLetterUppercase, Function.<span style="color:#a6e22e">identity</span>()));
</span></span><span style="display:flex;"><span>    IO.<span style="color:#a6e22e">println</span>(map);
</span></span><span style="display:flex;"><span>  }
</span></span></code></pre></div><p>In case of ambiguous imports, adding a single-type-import declaration resolves the ambiguousity:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">import</span> module java.<span style="color:#a6e22e">sql</span>;
</span></span><span style="display:flex;"><span><span style="color:#75715e">// import module java.base; -&gt; not needed as it&#39;s implicitly imported in compact source files</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// without the single-type-import declaration below, Date would be ambiguous</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> java.util.Date;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">main</span>() {
</span></span><span style="display:flex;"><span>    IO.<span style="color:#a6e22e">println</span>(<span style="color:#66d9ef">new</span> Date());
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h3 id="compact-source-files-and-instance-main-methods">Compact Source Files and Instance Main Methods</h3>
<p><a href="https://openjdk.org/jeps/512" target="_blank">JEP 512</a></p>
<p>The goal of this feature is to make Java more approachable for small programs, scripts, and learning scenarios—without removing the option to write fully structured code.</p>
<p>Do not fret if the terms &ldquo;compact source files&rdquo; and &ldquo;instance main methods&rdquo; are new to you and maybe somewhat confusing. In essence, this feature introduces a more concise way to write Java programs by allowing you to omit boilerplate code such as class declarations and static <code>main</code> methods.</p>
<p>Basically, we can get from this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#75715e">// in a file named HelloWorld.java</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">HelloWorld</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">main</span>(String<span style="color:#f92672">[]</span> args) {
</span></span><span style="display:flex;"><span>        System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(<span style="color:#e6db74">&#34;Hello, World!&#34;</span>);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>to this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#75715e">// in a file with any name, as long as the name is a valid Java class name</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// this is a ⚠️ compact source file</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">main</span>() { <span style="color:#75715e">// &lt;-- this is the ⚠️ instance main method</span>
</span></span><span style="display:flex;"><span>    System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(<span style="color:#e6db74">&#34;Hello, World!&#34;</span>);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Both versions can be run by either compiling them with <code>javac</code> and then running with <code>java</code>, or by running them directly with the source-code launcher.</p>
<p>A &ldquo;half-way&rdquo; version is to write the code like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Jep512</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">main</span>() { <span style="color:#75715e">// &lt;-- this is the ⚠️ instance main method</span>
</span></span><span style="display:flex;"><span>    System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(<span style="color:#e6db74">&#34;Hello, World!&#34;</span>);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This can be run the same as before.</p>
<p>Last two versions can be slightly modified to accept command-line arguments, as well. From <code>void main()</code> to <code>void main(String[] args)</code>.
Furthermore, the <code>println</code> statement can be simplified to just <code>IO.println(&quot;Hello, World!&quot;);</code>.</p>
<p>Let&rsquo;s look at another example:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#75715e">// in a file named args_printer.java</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">main</span>(String<span style="color:#f92672">[]</span> args) {
</span></span><span style="display:flex;"><span>  IO.<span style="color:#a6e22e">println</span>(Arrays.<span style="color:#a6e22e">toString</span>(args));
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This just works! But, why? How come <code>String</code>, <code>IO</code> and <code>Arrays</code> are available without any imports? The answer is that compact source files <em>implicitly</em> import the <code>java.base</code> module, which <em>exports</em> the <code>java.lang</code> and <code>java.util</code> packages, wherein those types are located.</p>
<p>We could have written it like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">main</span>(java.<span style="color:#a6e22e">lang</span>.<span style="color:#a6e22e">String</span><span style="color:#f92672">[]</span> args) {
</span></span><span style="display:flex;"><span>  java.<span style="color:#a6e22e">lang</span>.<span style="color:#a6e22e">IO</span>.<span style="color:#a6e22e">println</span>(java.<span style="color:#a6e22e">util</span>.<span style="color:#a6e22e">Arrays</span>.<span style="color:#a6e22e">toString</span>(args));
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>To check which packages are exported by the <code>java.base</code> module, you can run the following command:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>java --describe-module java.base | grep exports | grep -E <span style="color:#e6db74">&#34;java\.(lang|util)&#34;</span>
</span></span></code></pre></div><p>which produces the following output:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>exports java.lang
</span></span><span style="display:flex;"><span><span style="color:#75715e"># ... other exported packages ...</span>
</span></span><span style="display:flex;"><span>exports java.util
</span></span><span style="display:flex;"><span><span style="color:#75715e"># ... other exported packages ...</span>
</span></span></code></pre></div><h3 id="flexible-constructor-bodies">Flexible Constructor Bodies</h3>
<p><a href="https://openjdk.org/jeps/513" target="_blank">JEP 513</a></p>
<p>This feature allows statements to appear <em>before</em> an explicit constructor invocation, i.e., <code>super(...)</code> or <code>this(...)</code>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">import</span> module java.<span style="color:#a6e22e">base</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">JEP513</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">main</span>() {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> emp1 <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> Employee(<span style="color:#e6db74">&#34;John&#34;</span>, <span style="color:#e6db74">&#34;Doe&#34;</span>, 42, <span style="color:#e6db74">&#34;Engineering&#34;</span>);
</span></span><span style="display:flex;"><span>    IO.<span style="color:#a6e22e">println</span>(emp1);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Person</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">final</span> String firstName;
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">final</span> String lastName;
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">final</span> <span style="color:#66d9ef">int</span> age;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  Person(String firstName, String lastName, <span style="color:#66d9ef">int</span> age) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">firstName</span> <span style="color:#f92672">=</span> firstName;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">lastName</span> <span style="color:#f92672">=</span> lastName;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">age</span> <span style="color:#f92672">=</span> age;
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Employee</span> <span style="color:#66d9ef">extends</span> Person {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">final</span> String department;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  Employee(String firstName, String lastName, <span style="color:#66d9ef">int</span> age, String department) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>List.<span style="color:#a6e22e">of</span>(<span style="color:#e6db74">&#34;HR&#34;</span>, <span style="color:#e6db74">&#34;Sales&#34;</span>, <span style="color:#e6db74">&#34;Engineering&#34;</span>).<span style="color:#a6e22e">contains</span>(department)) {
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">throw</span> <span style="color:#66d9ef">new</span> IllegalArgumentException(<span style="color:#e6db74">&#34;&#39;%s&#39; department not valid.&#34;</span>.<span style="color:#a6e22e">formatted</span>(department));
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">department</span> <span style="color:#f92672">=</span> department;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">super</span>(firstName, lastName, age); <span style="color:#75715e">// [!code highlight]</span>
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">@Override</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">public</span> String <span style="color:#a6e22e">toString</span>() {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#e6db74">&#34;Employee(firstName=%s, lastName=%s, age=%d, department=%s)&#34;</span>
</span></span><span style="display:flex;"><span>        .<span style="color:#a6e22e">formatted</span>(<span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">firstName</span>, <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">lastName</span>, <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">age</span>, <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">department</span>);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h3 id="compact-object-headers">Compact Object Headers</h3>
<p><a href="https://openjdk.org/jeps/519" target="_blank">JEP 519</a></p>
<p>The main idea here is to reduce the memory footprint of Java objects by optimizing the layout of object headers in memory. Various experiments demonstrate that enabling compact object headers improves performance:</p>
<ul>
<li>22% less heap space</li>
<li>8% less CPU time</li>
<li>15% less garbage collections with G1 and Parallel collectors</li>
</ul>
<p>The feature can be enabled with the JVM option <code>-XX:+CompactObjectHeaders</code>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ java -XX:+UseCompactObjectHeaders MyProgram.java
</span></span></code></pre></div><h2 id="conclusion">Conclusion</h2>
<p>Java 25 continues the shift toward safer concurrency, lower ceremony, and better performance—without abandoning Java’s core strengths. Features like Scoped Values and compact source files show a clear focus on modern workloads and developer ergonomics.</p>
]]></content>
        </item>
        
        <item>
            <title>Let&#39;s make some calls</title>
            <link>https://vladflore.tech/posts/2025/05/lets-make-some-calls/</link>
            <pubDate>Sat, 03 May 2025 00:00:00 +0000</pubDate>
            
            <guid>https://vladflore.tech/posts/2025/05/lets-make-some-calls/</guid>
            <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;One of the most important things in programming is making HTTP calls to talk with some API. Java has very good support for this, and in this post, we will see how to call some HTTP endpoints using Java&amp;rsquo;s &lt;code&gt;HttpClient&lt;/code&gt; class. This class is part of the &lt;em&gt;Java 11&lt;/em&gt; standard library, so you don&amp;rsquo;t need any external dependencies to use it.&lt;/p&gt;
&lt;h2 id=&#34;a-closer-look-at-the-http-client&#34;&gt;A closer look at the HTTP client&lt;/h2&gt;
&lt;p&gt;Besides the &lt;code&gt;HttpClient&lt;/code&gt; class, there are a few other classes that we will use in this post:&lt;/p&gt;</description>
            <content type="html"><![CDATA[<h2 id="introduction">Introduction</h2>
<p>One of the most important things in programming is making HTTP calls to talk with some API. Java has very good support for this, and in this post, we will see how to call some HTTP endpoints using Java&rsquo;s <code>HttpClient</code> class. This class is part of the <em>Java 11</em> standard library, so you don&rsquo;t need any external dependencies to use it.</p>
<h2 id="a-closer-look-at-the-http-client">A closer look at the HTTP client</h2>
<p>Besides the <code>HttpClient</code> class, there are a few other classes that we will use in this post:</p>
<ul>
<li><code>HttpRequest</code>: This class represents an HTTP request</li>
<li><code>HttpResponse</code>: This class represents an HTTP response</li>
<li><code>HttpRequest.BodyPublishers</code>: This class contains static methods to create request bodies</li>
<li><code>HttpResponse.BodyHandlers</code>: This class contains static methods to create response bodies</li>
</ul>
<p>The new HTTP APIs can be found in the <code>java.net.http</code> package.</p>
<p>It&rsquo;s important to note that the new HTTP client is intended to replace the legacy <code>HttpURLConnection</code> class, which is still part of Java but considered outdated. The modern <code>HttpClient</code> not only simplifies making HTTP requests, but also adds powerful features like asynchronous calls, native WebSocket support, and HTTP/2 compatibility—making it a more robust and developer-friendly option overall.</p>
<p>The endpoint we will be using for the following examples is the <a href="https://jsonplaceholder.typicode.com/" target="_blank">JSONPlaceholder</a> API, which is a free online REST API that you can use for testing and prototyping.</p>
<p>The steps are similar for all the requests we will be making:</p>
<ol>
<li>Create an <code>HttpClient</code> instance; can be reused for multiple requests</li>
<li>Create an <code>HttpRequest</code> instance</li>
<li>Send the request and get the response</li>
<li>Process the response, i.e. either return the raw body or parse it into a Java object</li>
</ol>
<h2 id="creating-an-http-client">Creating an HTTP client</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">import</span> java.net.http.HttpClient;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">try</span> (<span style="color:#66d9ef">var</span> client <span style="color:#f92672">=</span> HttpClient.<span style="color:#a6e22e">newHttpClient</span>()) {
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Use the client to make requests</span>
</span></span><span style="display:flex;"><span>} <span style="color:#66d9ef">catch</span> (IOException <span style="color:#f92672">|</span> InterruptedException e) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">throw</span> <span style="color:#66d9ef">new</span> RuntimeException(e);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Since <code>HttpClient</code> implements <code>java.lang.AutoCloseable</code> we need to close the resource when we are done with it, the easiest way to do this is by wrapping the instantiation with a <code>try-with-resources</code> block.</p>
<h2 id="creating-an-http-request">Creating an HTTP request</h2>
<h3 id="get-request">GET request</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">final</span> String GET_SINGLE_ENDPOINT <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;https://jsonplaceholder.typicode.com/posts/1&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> request <span style="color:#f92672">=</span> HttpRequest.<span style="color:#a6e22e">newBuilder</span>()
</span></span><span style="display:flex;"><span>        .<span style="color:#a6e22e">uri</span>(<span style="color:#66d9ef">new</span> URI(GET_SINGLE_ENDPOINT))
</span></span><span style="display:flex;"><span>        .<span style="color:#a6e22e">GET</span>()
</span></span><span style="display:flex;"><span>        .<span style="color:#a6e22e">build</span>();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>HttpResponse<span style="color:#f92672">&lt;</span>String<span style="color:#f92672">&gt;</span> response <span style="color:#f92672">=</span> client.<span style="color:#a6e22e">send</span>(request, HttpResponse.<span style="color:#a6e22e">BodyHandlers</span>.<span style="color:#a6e22e">ofString</span>());
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>String responseBody <span style="color:#f92672">=</span> response.<span style="color:#a6e22e">body</span>();
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span> responseStatusCode <span style="color:#f92672">=</span> response.<span style="color:#a6e22e">statusCode</span>();
</span></span></code></pre></div><p>To fetch all the posts, instead of a single post, we can do the following:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">final</span> String GET_ALL_ENDPOINT <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;https://jsonplaceholder.typicode.com/posts&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> request <span style="color:#f92672">=</span> HttpRequest.<span style="color:#a6e22e">newBuilder</span>().<span style="color:#a6e22e">uri</span>(<span style="color:#66d9ef">new</span> URI(GET_ALL_ENDPOINT)).<span style="color:#a6e22e">GET</span>().<span style="color:#a6e22e">build</span>();
</span></span><span style="display:flex;"><span>HttpResponse<span style="color:#f92672">&lt;</span>String<span style="color:#f92672">&gt;</span> response <span style="color:#f92672">=</span> client.<span style="color:#a6e22e">send</span>(request, HttpResponse.<span style="color:#a6e22e">BodyHandlers</span>.<span style="color:#a6e22e">ofString</span>());
</span></span><span style="display:flex;"><span>String responseBody <span style="color:#f92672">=</span> response.<span style="color:#a6e22e">body</span>();
</span></span></code></pre></div><p>If the raw response body is a JSON string, we can use a library like <a href="https://github.com/FasterXML/jackson" target="_blank">Jackson</a> or <a href="https://github.com/google/gson" target="_blank">Gson</a> to parse it into a Java object.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">import</span> com.fasterxml.jackson.databind.ObjectMapper;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> objectMapper <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> ObjectMapper();
</span></span><span style="display:flex;"><span>Post<span style="color:#f92672">[]</span> posts <span style="color:#f92672">=</span> objectMapper.<span style="color:#a6e22e">readValue</span>(responseBody, Post<span style="color:#f92672">[]</span>.<span style="color:#a6e22e">class</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> gson <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> Gson();
</span></span><span style="display:flex;"><span>Post<span style="color:#f92672">[]</span> posts <span style="color:#f92672">=</span> gson.<span style="color:#a6e22e">fromJson</span>(responseBody, Post<span style="color:#f92672">[]</span>.<span style="color:#a6e22e">class</span>);
</span></span></code></pre></div><p>Make sure to add the Jackson or Gson dependency to your <code>pom.xml</code> file:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#f92672">&lt;dependency&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;groupId&gt;</span>com.fasterxml.jackson.core<span style="color:#f92672">&lt;/groupId&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;artifactId&gt;</span>jackson-databind<span style="color:#f92672">&lt;/artifactId&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;version&gt;</span>2.17.2<span style="color:#f92672">&lt;/version&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/dependency&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;dependency&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;groupId&gt;</span>com.google.code.gson<span style="color:#f92672">&lt;/groupId&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;artifactId&gt;</span>gson<span style="color:#f92672">&lt;/artifactId&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;version&gt;</span>2.13.1<span style="color:#f92672">&lt;/version&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/dependency&gt;</span>
</span></span></code></pre></div><p>For the following code examples, making the request and getting the raw body is the same.</p>
<h3 id="post-request">POST request</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#66d9ef">private</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">final</span> String POST_ENDPOINT <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;https://jsonplaceholder.typicode.com/posts&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> body <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;&#34;&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        {
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        &#34;title&#34;: &#34;foo&#34;,
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        &#34;body&#34;: &#34;bar&#34;,
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        &#34;userId&#34;: 1
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        }
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        &#34;&#34;&#34;</span>;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> request <span style="color:#f92672">=</span> HttpRequest.<span style="color:#a6e22e">newBuilder</span>()
</span></span><span style="display:flex;"><span>        .<span style="color:#a6e22e">uri</span>(<span style="color:#66d9ef">new</span> URI(POST_ENDPOINT))
</span></span><span style="display:flex;"><span>        .<span style="color:#a6e22e">POST</span>(HttpRequest.<span style="color:#a6e22e">BodyPublishers</span>.<span style="color:#a6e22e">ofString</span>(body))
</span></span><span style="display:flex;"><span>        .<span style="color:#a6e22e">headers</span>(<span style="color:#e6db74">&#34;Content-Type&#34;</span>, <span style="color:#e6db74">&#34;application/json&#34;</span>)
</span></span><span style="display:flex;"><span>        .<span style="color:#a6e22e">build</span>();
</span></span></code></pre></div><p>For a POST with no body, simply use <code>HttpRequest.BodyPublishers.noBody()</code>.</p>
<h3 id="put-request">PUT request</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#66d9ef">private</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">final</span> String PUT_ENDPOINT <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;https://jsonplaceholder.typicode.com/posts/1&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> body <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;&#34;&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        {
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        &#34;id&#34;:1,
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        &#34;title&#34;: &#34;FOO&#34;,
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        &#34;body&#34;: &#34;BAR&#34;,
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        &#34;userId&#34;: 1
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        }
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        &#34;&#34;&#34;</span>;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> request <span style="color:#f92672">=</span> HttpRequest.<span style="color:#a6e22e">newBuilder</span>()
</span></span><span style="display:flex;"><span>        .<span style="color:#a6e22e">uri</span>(URI.<span style="color:#a6e22e">create</span>(PUT_ENDPOINT))
</span></span><span style="display:flex;"><span>        .<span style="color:#a6e22e">PUT</span>(HttpRequest.<span style="color:#a6e22e">BodyPublishers</span>.<span style="color:#a6e22e">ofString</span>(body))
</span></span><span style="display:flex;"><span>        .<span style="color:#a6e22e">headers</span>(<span style="color:#e6db74">&#34;Content-Type&#34;</span>, <span style="color:#e6db74">&#34;application/json&#34;</span>)
</span></span><span style="display:flex;"><span>        .<span style="color:#a6e22e">build</span>();
</span></span></code></pre></div><h3 id="patch-request">PATCH request</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#66d9ef">private</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">final</span> String PATCH_ENDPOINT <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;https://jsonplaceholder.typicode.com/posts/1&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> body <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;&#34;&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        {
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        &#34;title&#34; : &#34;dummy title&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        }
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        &#34;&#34;&#34;</span>;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> request <span style="color:#f92672">=</span> HttpRequest.<span style="color:#a6e22e">newBuilder</span>()
</span></span><span style="display:flex;"><span>        .<span style="color:#a6e22e">uri</span>(<span style="color:#66d9ef">new</span> URI(PATCH_ENDPOINT))
</span></span><span style="display:flex;"><span>        .<span style="color:#a6e22e">method</span>(<span style="color:#e6db74">&#34;PATCH&#34;</span>, HttpRequest.<span style="color:#a6e22e">BodyPublishers</span>.<span style="color:#a6e22e">ofString</span>(body))
</span></span><span style="display:flex;"><span>        .<span style="color:#a6e22e">headers</span>(<span style="color:#e6db74">&#34;Content-Type&#34;</span>, <span style="color:#e6db74">&#34;application/json&#34;</span>)
</span></span><span style="display:flex;"><span>        .<span style="color:#a6e22e">build</span>();
</span></span></code></pre></div><h3 id="delete-request">DELETE request</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#66d9ef">private</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">final</span> String DELETE_ENDPOINT <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;https://jsonplaceholder.typicode.com/posts/1&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> request <span style="color:#f92672">=</span> HttpRequest.<span style="color:#a6e22e">newBuilder</span>()
</span></span><span style="display:flex;"><span>        .<span style="color:#a6e22e">uri</span>(<span style="color:#66d9ef">new</span> URI(DELETE_ENDPOINT))
</span></span><span style="display:flex;"><span>        .<span style="color:#a6e22e">DELETE</span>()
</span></span><span style="display:flex;"><span>        .<span style="color:#a6e22e">build</span>();
</span></span></code></pre></div><h2 id="making-asynchronous-calls">Making asynchronous calls</h2>
<p>Making asynchronous calls is very similar to making synchronous calls. The only difference is that we need to use the <code>sendAsync</code> method instead of the <code>send</code> method, and deal with the <code>CompletableFuture</code> that is returned.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#66d9ef">private</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">makeAsyncRequest</span>(HttpClient client, HttpRequest request) {
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// send the request asynchronously</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> future <span style="color:#f92672">=</span> client.<span style="color:#a6e22e">sendAsync</span>(request, HttpResponse.<span style="color:#a6e22e">BodyHandlers</span>.<span style="color:#a6e22e">ofString</span>())
</span></span><span style="display:flex;"><span>            <span style="color:#75715e">// process the response</span>
</span></span><span style="display:flex;"><span>            .<span style="color:#a6e22e">thenApply</span>(App::handleResponse)
</span></span><span style="display:flex;"><span>            <span style="color:#75715e">// consume the response, by printing the first 5 posts</span>
</span></span><span style="display:flex;"><span>            .<span style="color:#a6e22e">thenAccept</span>(posts <span style="color:#f92672">-&gt;</span> Arrays.<span style="color:#a6e22e">stream</span>(posts).<span style="color:#a6e22e">limit</span>(5).<span style="color:#a6e22e">forEach</span>(System.<span style="color:#a6e22e">out</span>::println));
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// wait for the future to complete, before proceeding with the program</span>
</span></span><span style="display:flex;"><span>    future.<span style="color:#a6e22e">join</span>();
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">private</span> <span style="color:#66d9ef">static</span> Post<span style="color:#f92672">[]</span> <span style="color:#a6e22e">handleResponse</span>(HttpResponse<span style="color:#f92672">&lt;</span>String<span style="color:#f92672">&gt;</span> response) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">int</span> statusCode <span style="color:#f92672">=</span> response.<span style="color:#a6e22e">statusCode</span>();
</span></span><span style="display:flex;"><span>    System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(<span style="color:#e6db74">&#34;response.statusCode() = &#34;</span> <span style="color:#f92672">+</span> statusCode);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (statusCode <span style="color:#f92672">==</span> 200) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">try</span> {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">new</span> ObjectMapper().<span style="color:#a6e22e">readValue</span>(response.<span style="color:#a6e22e">body</span>(), Post<span style="color:#f92672">[]</span>.<span style="color:#a6e22e">class</span>);
</span></span><span style="display:flex;"><span>        } <span style="color:#66d9ef">catch</span> (JsonProcessingException e) {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">throw</span> <span style="color:#66d9ef">new</span> RuntimeException(e);
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    } <span style="color:#66d9ef">else</span> {
</span></span><span style="display:flex;"><span>        System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(<span style="color:#e6db74">&#34;Unsuccessful response.&#34;</span>);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">new</span> Post<span style="color:#f92672">[]</span>{};
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="specifying-other-options">Specifying other options</h2>
<p>When building the <em>client</em>, we can specify various options, such as:</p>
<ul>
<li>the <em>proxy</em> to use: <code>.proxy(ProxySelector.getDefault())</code></li>
<li>the <em>redirect policy</em>: <code>.followRedirects(HttpClient.Redirect.ALWAYS)</code></li>
<li>the <em>authenticator</em>: <code>.authenticator(auth)</code></li>
<li>the <em>executor</em>: <code>.executor(Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()))</code></li>
</ul>
<p>When building the <em>request</em>, we can specify various options, such as:</p>
<ul>
<li>the <em>timeout</em>: <code>.timeout(Duration.ofSeconds(1))</code></li>
<li>the <em>headers</em>: <code>.header(&quot;Content-Type&quot;, &quot;application/json&quot;)</code></li>
<li>the <em>protocol version</em>: <code>.version(HttpClient.Version.HTTP_2)</code></li>
<li>the <em>body publishers</em>: <code>.POST(HttpRequest.BodyPublishers.ofString(body))</code></li>
</ul>
<p>There are a couple of other body publishers that we can use, such as:</p>
<ul>
<li><code>HttpRequest.BodyPublishers.ofFile()</code>: body content taken from the file</li>
<li><code>HttpRequest.BodyPublishers.ofInputStream()</code>: body content taken from an input stream</li>
<li><code>HttpRequest.BodyPublishers.ofByteArray()</code>: body content taken from the byte array</li>
</ul>
<p>When <em>sending the request</em> we can specify how the response body should be handled, such as:</p>
<ul>
<li><code>HttpResponse.BodyHandlers.ofString()</code>: returns the response body as a string</li>
<li><code>HttpResponse.BodyHandlers.ofByteArray()</code>: returns the response body as a byte array</li>
<li><code>HttpResponse.BodyHandlers.ofFile()</code>: returns the response body as a file</li>
<li><code>HttpResponse.BodyHandlers.ofInputStream()</code>: returns the response body as an input stream</li>
<li><code>HttpResponse.BodyHandlers.ofPublisher()</code>: returns the response body as a publisher</li>
<li><code>HttpResponse.BodyHandlers.ofLines()</code>: returns the response body as a stream of lines</li>
</ul>
<h3 id="authentication">Authentication</h3>
<p>When creating the client, we can specify an <code>Authenticator</code> to use for authentication. The <code>Authenticator</code> is a class that provides a way to authenticate requests. We can extend it, and override the <code>getPasswordAuthentication</code> method to provide the credentials.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">import</span> java.net.Authenticator;
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> java.net.PasswordAuthentication;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">MyAuthenticator</span> <span style="color:#66d9ef">extends</span> Authenticator {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">@Override</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">protected</span> PasswordAuthentication <span style="color:#a6e22e">getPasswordAuthentication</span>() {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">new</span> PasswordAuthentication(
</span></span><span style="display:flex;"><span>                <span style="color:#e6db74">&#34;username&#34;</span>,
</span></span><span style="display:flex;"><span>                <span style="color:#e6db74">&#34;password&#34;</span>.<span style="color:#a6e22e">toCharArray</span>()
</span></span><span style="display:flex;"><span>        );
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Alternatively, we can set the <code>Authorization</code> header in the request, and use a basic authentication scheme or a bearer token.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#75715e">// for the basic authentication scheme</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> auth <span style="color:#f92672">=</span> Base64.<span style="color:#a6e22e">getEncoder</span>().<span style="color:#a6e22e">encodeToString</span>(<span style="color:#e6db74">&#34;username:password&#34;</span>.<span style="color:#a6e22e">getBytes</span>());
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> getRequest <span style="color:#f92672">=</span> HttpRequest.<span style="color:#a6e22e">newBuilder</span>(<span style="color:#66d9ef">new</span> URI(<span style="color:#e6db74">&#34;&lt;endpoint&gt;&#34;</span>))
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// set a bearer token</span>
</span></span><span style="display:flex;"><span>        .<span style="color:#a6e22e">header</span>(<span style="color:#e6db74">&#34;Authorization&#34;</span>, <span style="color:#e6db74">&#34;Bearer &lt;token&gt;&#34;</span>)
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// or set a basic authentication scheme</span>
</span></span><span style="display:flex;"><span>        .<span style="color:#a6e22e">header</span>(<span style="color:#e6db74">&#34;Authorization&#34;</span>, <span style="color:#e6db74">&#34;Basic &#34;</span> <span style="color:#f92672">+</span> auth)
</span></span><span style="display:flex;"><span>        .<span style="color:#a6e22e">GET</span>()
</span></span><span style="display:flex;"><span>        .<span style="color:#a6e22e">build</span>();
</span></span></code></pre></div><h2 id="conclusion">Conclusion</h2>
<p>In this post, we have seen how to make HTTP calls using Java&rsquo;s <code>HttpClient</code> class. We have seen how to create a client, create a request, and send the request. We have also seen how to make asynchronous calls and specify various options for the client and the request.</p>
]]></content>
        </item>
        
        <item>
            <title>Java &gt; 17 &amp;&amp; &lt;= 24</title>
            <link>https://vladflore.tech/posts/2025/04/java-17-24/</link>
            <pubDate>Tue, 29 Apr 2025 00:00:00 +0000</pubDate>
            
            <guid>https://vladflore.tech/posts/2025/04/java-17-24/</guid>
            <description>&lt;h2 id=&#34;meet-java-24&#34;&gt;Meet Java 24&lt;/h2&gt;
&lt;p&gt;Java 24 is &lt;em&gt;not&lt;/em&gt; a &lt;em&gt;LTS version&lt;/em&gt;. The last LTS version was Java 21, released in September 2023.&lt;/p&gt;
&lt;p&gt;In this post, I will tackle some of the new features and improvements that Java 24 brings to the table. Note that some of them might have been introduced in previous versions, but for the sake of completeness, I will include them here.&lt;/p&gt;
&lt;p&gt;In my &lt;a href=&#34;https://vladflore.tech/posts/2022/07/java-17/&#34;&gt;post about Java 17&lt;/a&gt;, I mentioned some of the noteworthy features introduced in that version, in this post I will focus on the new features introduced since then.&lt;/p&gt;</description>
            <content type="html"><![CDATA[<h2 id="meet-java-24">Meet Java 24</h2>
<p>Java 24 is <em>not</em> a <em>LTS version</em>. The last LTS version was Java 21, released in September 2023.</p>
<p>In this post, I will tackle some of the new features and improvements that Java 24 brings to the table. Note that some of them might have been introduced in previous versions, but for the sake of completeness, I will include them here.</p>
<p>In my <a href="https://vladflore.tech/posts/2022/07/java-17/">post about Java 17</a>, I mentioned some of the noteworthy features introduced in that version, in this post I will focus on the new features introduced since then.</p>
<p>Note that I will not cover all the features, but only the ones I find interesting. For a complete list of features feel free to check the <a href="https://openjdk.org/projects/jdk/" target="_blank">JDK Project page</a>.</p>
<h2 id="java-18">Java 18</h2>
<h3 id="utf-8-by-default">UTF-8 by default</h3>
<p>This can be summarized as:</p>
<blockquote>
<p><em>Specify UTF-8 as the default charset of the standard Java APIs. With this change, APIs that depend upon the default charset will behave consistently across all implementations, operating systems, locales, and configurations.</em></p>
<p>&ndash; <!-- raw HTML omitted --><a href="https://openjdk.org/jeps/400" target="_blank">JEP 400: UTF-8 by Default</a><!-- raw HTML omitted --></p>
</blockquote>
<p>The implementation of <code>Charset.defaultCharset()</code> will return the UTF-8 charset by default, unless overridden with the system property <code>file.encoding</code>. If the value is <code>COMPAT</code>, the default charset is derived from the <code>native.encoding</code> system property, which depends on the locale and charset of the underlying operating system.</p>
<p>A quick way to see the default charset of the current JDK is with the following command:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>java -XshowSettings:properties -version 2&gt;&amp;<span style="color:#ae81ff">1</span> | grep file.encoding
</span></span></code></pre></div><h3 id="simple-web-server">Simple Web Server</h3>
<p>The Simple Web Server is a minimal HTTP server for serving a single directory hierarchy, and it can be used via the dedicated command-line tool <code>jwebserver</code> or programmatically via its API.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>jwebserver
</span></span><span style="display:flex;"><span>Binding to loopback by default. For all interfaces use <span style="color:#e6db74">&#34;-b 0.0.0.0&#34;</span> or <span style="color:#e6db74">&#34;-b ::&#34;</span>.
</span></span><span style="display:flex;"><span>Serving &lt;directory&gt; and subdirectories on 127.0.0.1 port <span style="color:#ae81ff">8000</span>
</span></span><span style="display:flex;"><span>URL http://127.0.0.1:8000/
</span></span></code></pre></div><p>The same can be achieved programmatically with the following code:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> server <span style="color:#f92672">=</span> SimpleFileServer.<span style="color:#a6e22e">createFileServer</span>(<span style="color:#66d9ef">new</span> InetSocketAddress(8080),
</span></span><span style="display:flex;"><span>        Path.<span style="color:#a6e22e">of</span>(<span style="color:#e6db74">&#34;/&#34;</span>),
</span></span><span style="display:flex;"><span>        OutputLevel.<span style="color:#a6e22e">VERBOSE</span>);
</span></span><span style="display:flex;"><span>server.<span style="color:#a6e22e">start</span>();
</span></span></code></pre></div><p>For more information, check the <a href="https://openjdk.org/jeps/408" target="_blank">JEP 408: Simple Web Server</a>.</p>
<h3 id="code-snippets-in-javadoc">Code Snippets in JavaDoc</h3>
<p><a href="https://openjdk.org/jeps/413" target="_blank">JEP 413: Code Snippets in Java API Documentation</a> introduces a new tag, <code>@snippet</code>, that allows you to include code snippets in your JavaDoc comments.</p>
<p>Here are some examples of how to use it. The JavaDoc comment of the class <code>A</code> includes an inline code snippet, and two external code snippets. The external code snippets are the entire class <code>B</code> and the named region of the class <code>B</code> called <code>say-howdy</code>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#75715e">/**
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"> *
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"> * {@snippet :
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"> *
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"> * System.out.println(&#34;This is a polite class.&#34;);
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"> *
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"> * }
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"> *
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"> * {@snippet class = B}
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"> *
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"> * {@snippet class = B region = say-howdy}
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"> *
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"> */</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">A</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">main</span>(String<span style="color:#f92672">[]</span> args) {
</span></span><span style="display:flex;"><span>        System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(<span style="color:#e6db74">&#34;Hello, A!&#34;</span>);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">B</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">main</span>(String<span style="color:#f92672">[]</span> args) {
</span></span><span style="display:flex;"><span>        System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(<span style="color:#e6db74">&#34;Hello, B!&#34;</span>);
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// @start region = say-howdy</span>
</span></span><span style="display:flex;"><span>        System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(<span style="color:#e6db74">&#34;Howdy, B!&#34;</span>);
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// @end</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>In order to generate the JavaDoc with the code snippets, we need to run the following command:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>javadoc -d docs --snippet-path . A.java
</span></span></code></pre></div><p>This will generate the JavaDoc in the <code>docs</code> directory. Note the <code>--snippet-path</code> option, which specifies the path to the code snippets, in this case the current source directory.</p>
<p>This is how it looks like:</p>

    <img src="/images/javadoc.jpeg"  alt="Java Doc of class A"  class="center"  style="border-radius: 8px;"  />


<h2 id="java-19">Java 19</h2>
<p>Not to be dismissive of the work done in Java 19, but I will not cover it here, as it does not introduce any final features and of personal interest. Feel free to check the <a href="https://openjdk.org/projects/jdk/19/" target="_blank">Java 19 release notes</a> for more information.</p>
<h2 id="java-20">Java 20</h2>
<p>Idem. Please check the <a href="https://openjdk.org/projects/jdk/20/" target="_blank">Java 20 release notes</a> for more information.</p>
<h2 id="java-21">Java 21</h2>
<p>This is a LTS version, released in September 2023. Check the <a href="https://openjdk.org/projects/jdk/21/" target="_blank">Java 21 release notes</a>.</p>
<h3 id="sequenced-collections">Sequenced Collections</h3>
<p><a href="https://openjdk.org/jeps/431" target="_blank">JEP 431: Sequenced Collections</a> introduces new interfaces to represent collections with a defined encounter order. This means that each such collection has a well-defined first element, second element, and so on, up to the last element.</p>
<p>The new interfaces are:</p>
<ul>
<li><code>SequencedCollection</code> -&gt; a collection with a defined encounter order</li>
<li><code>SequencedSet</code> -&gt; a set with a defined encounter order</li>
<li><code>SequencedMap</code> -&gt; a map with a defined encounter order</li>
</ul>
<p>The diagrams below show how the new interfaces fit into the existing collections type hierarchy.</p>
<pre class="mermaid">graph TD
    Collection --- Set
    Collection --- SequencedCollection
    Collection --- Queue

    Set --- SequencedSet
    SequencedSet --- SortedSet
    SortedSet --- NavigableSet
    SequencedSet --- LinkedHashSet
    Set --- SortedSet

    SequencedCollection --- List
    SequencedCollection --- Deque
    SequencedCollection --- SequencedSet

    Queue --- Deque

    Map --- SequencedMap
    SequencedMap --- SortedMap
    SequencedMap --- LinkedHashMap
    SortedMap --- NavigableMap

    classDef highlight stroke:orange,stroke-width:2px;
    class SequencedCollection highlight;
    class SequencedSet highlight;
    class SequencedMap highlight;
</pre>
<h3 id="record-patterns">Record Patterns</h3>
<p>Record patterns enable the deconstruction of records into their components. This allows you to extract the values of a record in a more concise way. Check the following example:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#66d9ef">record</span> <span style="color:#a6e22e">Point</span>(<span style="color:#66d9ef">int</span> x, <span style="color:#66d9ef">int</span> y) {}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">record</span> <span style="color:#a6e22e">Circle</span>(Point center, <span style="color:#66d9ef">int</span> radius) <span style="color:#66d9ef">implements</span> Shape {}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">record</span> <span style="color:#a6e22e">Line</span>(Point start, Point end) <span style="color:#66d9ef">implements</span> Shape {}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">sealed</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">Shape</span> permits Circle, Line {}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">private</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">printShape</span>(Shape s) {
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// the old way</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (s <span style="color:#66d9ef">instanceof</span> Circle) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> circle <span style="color:#f92672">=</span> (Circle) s;
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> txt <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;Center: (%d, %d) Radius: %d&#34;</span>.<span style="color:#a6e22e">formatted</span>(
</span></span><span style="display:flex;"><span>                circle.<span style="color:#a6e22e">center</span>().<span style="color:#a6e22e">x</span>(),
</span></span><span style="display:flex;"><span>                circle.<span style="color:#a6e22e">center</span>().<span style="color:#a6e22e">y</span>(),
</span></span><span style="display:flex;"><span>                circle.<span style="color:#a6e22e">radius</span>());
</span></span><span style="display:flex;"><span>        System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(txt);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// the new way using record patterns</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (s <span style="color:#66d9ef">instanceof</span> <span style="color:#a6e22e">Circle</span>(Point(<span style="color:#66d9ef">int</span> x, <span style="color:#66d9ef">int</span> y), <span style="color:#66d9ef">int</span> radius)) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> txt <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;Center: (%d, %d) Radius: %d&#34;</span>.<span style="color:#a6e22e">formatted</span>(x, y, radius);
</span></span><span style="display:flex;"><span>        System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(txt);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// same as before, but using `var`</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (s <span style="color:#66d9ef">instanceof</span> <span style="color:#a6e22e">Circle</span>(Point(<span style="color:#66d9ef">var</span> x, <span style="color:#66d9ef">var</span> y), <span style="color:#66d9ef">var</span> radius)) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> txt <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;Center: (%d, %d) Radius: %d&#34;</span>.<span style="color:#a6e22e">formatted</span>(x, y, radius);
</span></span><span style="display:flex;"><span>        System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(txt);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// an exaustive(note that `Shape` is sealed) switch expression that makes use of record patterns</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> txt1 <span style="color:#f92672">=</span> <span style="color:#66d9ef">switch</span> (s) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">case</span> Circle(Point(<span style="color:#66d9ef">var</span> x, <span style="color:#66d9ef">var</span> y), <span style="color:#66d9ef">var</span> radius) <span style="color:#f92672">-&gt;</span> <span style="color:#e6db74">&#34;Center: (%d, %d) Radius: %d&#34;</span>.<span style="color:#a6e22e">formatted</span>(x, y, radius);
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">case</span> Line(Point(<span style="color:#66d9ef">var</span> startX, <span style="color:#66d9ef">var</span> startY), Point(<span style="color:#66d9ef">var</span> endX, <span style="color:#66d9ef">var</span> endY)) <span style="color:#f92672">-&gt;</span>
</span></span><span style="display:flex;"><span>            <span style="color:#e6db74">&#34;Start: (%d, %d) End: (%d, %d)&#34;</span>.<span style="color:#a6e22e">formatted</span>(startX, startY, endX, endY);
</span></span><span style="display:flex;"><span>    };
</span></span><span style="display:flex;"><span>    System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(txt1);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> circle <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> Circle(<span style="color:#66d9ef">new</span> Point(1, 2), 3);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> line <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> Line(<span style="color:#66d9ef">new</span> Point(7, 7), <span style="color:#66d9ef">new</span> Point(77, 77));
</span></span><span style="display:flex;"><span>printShape(circle);
</span></span><span style="display:flex;"><span>printShape(line);
</span></span></code></pre></div><p>Running the above code will produce the following output:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>Center: <span style="color:#f92672">(</span>1, 2<span style="color:#f92672">)</span> Radius: <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span>Center: <span style="color:#f92672">(</span>1, 2<span style="color:#f92672">)</span> Radius: <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span>Center: <span style="color:#f92672">(</span>1, 2<span style="color:#f92672">)</span> Radius: <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span>Center: <span style="color:#f92672">(</span>1, 2<span style="color:#f92672">)</span> Radius: <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span>Start: <span style="color:#f92672">(</span>7, 7<span style="color:#f92672">)</span> End: <span style="color:#f92672">(</span>77, 77<span style="color:#f92672">)</span>
</span></span></code></pre></div><h3 id="pattern-matching-for-switch">Pattern Matching for Switch</h3>
<p>The example above, besides showing the new record patterns, also shows the new pattern matching for switch expressions. This allows you to use patterns in switch expressions, making them more powerful and expressive.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> txt1 <span style="color:#f92672">=</span> <span style="color:#66d9ef">switch</span> (s) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">case</span> Circle(Point(<span style="color:#66d9ef">var</span> x, <span style="color:#66d9ef">var</span> y), <span style="color:#66d9ef">var</span> radius) <span style="color:#f92672">-&gt;</span> <span style="color:#e6db74">&#34;Center: (%d, %d) Radius: %d&#34;</span>.<span style="color:#a6e22e">formatted</span>(x, y, radius);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">case</span> Line(Point(<span style="color:#66d9ef">var</span> startX, <span style="color:#66d9ef">var</span> startY), Point(<span style="color:#66d9ef">var</span> endX, <span style="color:#66d9ef">var</span> endY)) <span style="color:#f92672">-&gt;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;Start: (%d, %d) End: (%d, %d)&#34;</span>.<span style="color:#a6e22e">formatted</span>(startX, startY, endX, endY);
</span></span><span style="display:flex;"><span>};
</span></span></code></pre></div><p>Let&rsquo;s see another example:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">import</span> java.util.regex.Pattern;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">AboutSwitchPatternMatching</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">main</span>(String<span style="color:#f92672">[]</span> args) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> colors <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;red, blue, green,yellow, RED, Blue, grEEn, YELLow&#34;</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> pattern <span style="color:#f92672">=</span> Pattern.<span style="color:#a6e22e">compile</span>(<span style="color:#e6db74">&#34;,\\s*&#34;</span>);
</span></span><span style="display:flex;"><span>        pattern.<span style="color:#a6e22e">splitAsStream</span>(colors).<span style="color:#a6e22e">map</span>(AboutSwitchPatternMatching::translateColorToGerman)
</span></span><span style="display:flex;"><span>                .<span style="color:#a6e22e">forEach</span>(System.<span style="color:#a6e22e">out</span>::println);
</span></span><span style="display:flex;"><span>        System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(translateColorToGerman(<span style="color:#66d9ef">null</span>));
</span></span><span style="display:flex;"><span>        System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(translateColorToGerman(<span style="color:#e6db74">&#34;purple&#34;</span>));
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">static</span> String <span style="color:#a6e22e">translateColorToGerman</span>(String colorInEnglish) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">switch</span> (colorInEnglish) {
</span></span><span style="display:flex;"><span>            <span style="color:#75715e">// string matching ignoring case</span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">case</span> String s when s.<span style="color:#a6e22e">equalsIgnoreCase</span>(<span style="color:#e6db74">&#34;red&#34;</span>) <span style="color:#f92672">-&gt;</span> <span style="color:#e6db74">&#34;rot&#34;</span>;
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">case</span> String s when s.<span style="color:#a6e22e">equalsIgnoreCase</span>(<span style="color:#e6db74">&#34;blue&#34;</span>) <span style="color:#f92672">-&gt;</span> <span style="color:#e6db74">&#34;blau&#34;</span>;
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">case</span> String s when s.<span style="color:#a6e22e">equalsIgnoreCase</span>(<span style="color:#e6db74">&#34;green&#34;</span>) <span style="color:#f92672">-&gt;</span> <span style="color:#e6db74">&#34;gruen&#34;</span>;
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">case</span> String s when s.<span style="color:#a6e22e">equalsIgnoreCase</span>(<span style="color:#e6db74">&#34;yellow&#34;</span>) <span style="color:#f92672">-&gt;</span> <span style="color:#e6db74">&#34;gelb&#34;</span>;
</span></span><span style="display:flex;"><span>            <span style="color:#75715e">// `null` case must be handled separately</span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">case</span> <span style="color:#66d9ef">null</span> <span style="color:#f92672">-&gt;</span> <span style="color:#e6db74">&#34;Unsupported color:&#34;</span> <span style="color:#f92672">+</span> colorInEnglish;
</span></span><span style="display:flex;"><span>            <span style="color:#75715e">// to make `switch` exhaustive, we need a `default` case</span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">default</span> <span style="color:#f92672">-&gt;</span> <span style="color:#e6db74">&#34;Unsupported color:&#34;</span> <span style="color:#f92672">+</span> colorInEnglish;
</span></span><span style="display:flex;"><span>            <span style="color:#75715e">// Note: the two lines above can be combined into one:</span>
</span></span><span style="display:flex;"><span>            <span style="color:#75715e">// case null, default -&gt; &#34;Unsupported color:&#34; + colorInEnglish;</span>
</span></span><span style="display:flex;"><span>        };
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>While the example above works fine, using <code>enum</code>s will improve the code substantially.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#66d9ef">enum</span> Color {
</span></span><span style="display:flex;"><span>    RED, BLUE, GREEN, YELLOW, PURPLE
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#75715e">// the main code changes slightly</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> colors <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;red, blue, green,yellow, RED, Blue, grEEn, YELLow&#34;</span>;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> pattern <span style="color:#f92672">=</span> Pattern.<span style="color:#a6e22e">compile</span>(<span style="color:#e6db74">&#34;,\\s*&#34;</span>);
</span></span><span style="display:flex;"><span>pattern.<span style="color:#a6e22e">splitAsStream</span>(colors)
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// otherwise mapping to `Color` will fail for some values</span>
</span></span><span style="display:flex;"><span>        .<span style="color:#a6e22e">map</span>(String::toUpperCase)
</span></span><span style="display:flex;"><span>        .<span style="color:#a6e22e">map</span>(Color::valueOf)
</span></span><span style="display:flex;"><span>        .<span style="color:#a6e22e">map</span>(AboutSwitchPatternMatching::translateColorToGerman)
</span></span><span style="display:flex;"><span>        .<span style="color:#a6e22e">forEach</span>(System.<span style="color:#a6e22e">out</span>::println);
</span></span><span style="display:flex;"><span>System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(translateColorToGerman(<span style="color:#66d9ef">null</span>));
</span></span><span style="display:flex;"><span>System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(translateColorToGerman(Color.<span style="color:#a6e22e">PURPLE</span>));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">private</span> <span style="color:#66d9ef">static</span> String <span style="color:#a6e22e">translateColorToGerman</span>(Color colorInEnglish) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">switch</span> (colorInEnglish) {
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// this is now an exhaustive `switch`</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">case</span> Color.<span style="color:#a6e22e">RED</span> <span style="color:#f92672">-&gt;</span> <span style="color:#e6db74">&#34;rot&#34;</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">case</span> Color.<span style="color:#a6e22e">BLUE</span> <span style="color:#f92672">-&gt;</span> <span style="color:#e6db74">&#34;blau&#34;</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">case</span> Color.<span style="color:#a6e22e">GREEN</span> <span style="color:#f92672">-&gt;</span> <span style="color:#e6db74">&#34;gruen&#34;</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">case</span> Color.<span style="color:#a6e22e">YELLOW</span> <span style="color:#f92672">-&gt;</span> <span style="color:#e6db74">&#34;gelb&#34;</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">case</span> Color.<span style="color:#a6e22e">PURPLE</span> <span style="color:#f92672">-&gt;</span> <span style="color:#e6db74">&#34;lila&#34;</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">case</span> <span style="color:#66d9ef">null</span> <span style="color:#f92672">-&gt;</span> <span style="color:#e6db74">&#34;Unsupported color:&#34;</span> <span style="color:#f92672">+</span> colorInEnglish;
</span></span><span style="display:flex;"><span>    };
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Another important point to keep in mind is <em>case label dominance</em>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span>Object str <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;this is a string&#34;</span>;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> res <span style="color:#f92672">=</span> <span style="color:#66d9ef">switch</span> (str) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">case</span> CharSequence cs <span style="color:#f92672">-&gt;</span> <span style="color:#e6db74">&#34;A sequence of length: &#34;</span> <span style="color:#f92672">+</span> cs.<span style="color:#a6e22e">length</span>();
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">case</span> String s <span style="color:#f92672">-&gt;</span> <span style="color:#e6db74">&#34;A string: &#34;</span> <span style="color:#f92672">+</span> s; <span style="color:#75715e">// COMPILATION ERROR: this case label is dominated by one of the preceding case labels, i.e. a `String` is a `CharSequence`</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">default</span> <span style="color:#f92672">-&gt;</span> <span style="color:#e6db74">&#34;Something else&#34;</span>;
</span></span><span style="display:flex;"><span>};
</span></span><span style="display:flex;"><span>System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(res);
</span></span></code></pre></div><p>Switching the order of the case labels fixes the compilation error.</p>
<p>Note that changing the definition of <code>str</code>, from <code>Object</code> to <code>String</code>, leads to other compilation errors, <em>duplicate unconditional pattern</em>, for the second case label, and <em>switch has both an unconditional pattern and a default label</em>, for the default label. We now need to remove the default label, and one of the remaining two case labels. By this time, our switch would have only one case label.</p>
<h3 id="virtual-threads">Virtual Threads</h3>
<p><a href="https://openjdk.org/jeps/444" target="_blank">JEP 444: Virtual Threads</a> introduces Virtual Threads, maybe the most important feature in Java 21. Make sure to go through the JEP, as I will not cover all the aspects.</p>
<blockquote>
<p>Virtual threads are lightweight threads that dramatically reduce the effort of writing, maintaining, and observing high-throughput concurrent applications.</p>
<p>&ndash; <!-- raw HTML omitted --><a href="https://openjdk.org/jeps/444" target="_blank">JEP 444: Virtual Threads</a><!-- raw HTML omitted --></p>
</blockquote>
<p>Before seeing some code let&rsquo;s go through some buzzwords related to this feature:</p>
<ul>
<li><em>virtual thread</em> -&gt; an instance of <code>java.lang.Thread</code> that is not tied to a particular <em>OS thread</em></li>
<li><em>M:N scheduling</em> -&gt; virtual threads employ M:N scheduling, where a large number (M) of virtual threads is scheduled to run on a smaller number (N) of OS threads. Other types of scheduling include 1:1, for platform threads, and M:1 for Java&rsquo;s <em>green threads</em>, that all shared one OS thread</li>
<li><em>structured concurrency</em> -&gt; tries to simplify multithreading programming, by treating multiple tasks running in different threads as a single unit of work</li>
<li><em>platform thread</em> -&gt; an instance of <code>java.lang.Thread</code> implemented in the traditional way, as a thin wrapper around an OS thread</li>
<li><em>carrier thread</em> -&gt; the platform thread to which the scheduler assigns a virtual thread is called the virtual thread&rsquo;s carrier. A VT can be scheduled on different carriers over the course of its lifetime</li>
<li><em>mounting</em> and <em>unmounting</em> -&gt; to run code in a virtual thread, the JDK&rsquo;s virtual thread scheduler assigns the virtual thread for execution on a platform thread by mounting the virtual thread on a platform thread. A VT can unmount from its carrier, at which point the platform thread is free and can carry a different VT</li>
<li><em>pinning</em> -&gt; a VT is pinned to its carrier when it executes code insider a synchronized block or method, or when it executes a native method or a foreign function. This can hinder scalability, but it does not make an application incorrect</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">import</span> java.util.concurrent.Executors;
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> java.util.concurrent.ThreadFactory;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">AboutVirtualThreads</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">main</span>(String<span style="color:#f92672">[]</span> args) <span style="color:#66d9ef">throws</span> InterruptedException {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// the work to be done</span>
</span></span><span style="display:flex;"><span>        Runnable r <span style="color:#f92672">=</span> () <span style="color:#f92672">-&gt;</span> {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">var</span> tName <span style="color:#f92672">=</span> Thread.<span style="color:#a6e22e">currentThread</span>().<span style="color:#a6e22e">getName</span>();
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">var</span> isVirtual <span style="color:#f92672">=</span> Thread.<span style="color:#a6e22e">currentThread</span>().<span style="color:#a6e22e">isVirtual</span>();
</span></span><span style="display:flex;"><span>            System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(<span style="color:#e6db74">&#34;Hello from &#34;</span> <span style="color:#f92672">+</span> tName <span style="color:#f92672">+</span> <span style="color:#e6db74">&#34;. Am I virtual? &#34;</span> <span style="color:#f92672">+</span> isVirtual);
</span></span><span style="display:flex;"><span>        };
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// using a builder via the `.ofVirtual()`</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> t1 <span style="color:#f92672">=</span> Thread.<span style="color:#a6e22e">ofVirtual</span>().<span style="color:#a6e22e">name</span>(<span style="color:#e6db74">&#34;my-virtual-thread-1&#34;</span>).<span style="color:#a6e22e">start</span>(r);
</span></span><span style="display:flex;"><span>        t1.<span style="color:#a6e22e">join</span>();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// convenient method for creating a VT and scheduling it to execute</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> t2 <span style="color:#f92672">=</span> Thread.<span style="color:#a6e22e">startVirtualThread</span>(r);
</span></span><span style="display:flex;"><span>        t2.<span style="color:#a6e22e">setName</span>(<span style="color:#e6db74">&#34;my-virtual-thread-2&#34;</span>);
</span></span><span style="display:flex;"><span>        t2.<span style="color:#a6e22e">join</span>();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// using a thread factory to create a VT for each task submitted</span>
</span></span><span style="display:flex;"><span>        ThreadFactory tf <span style="color:#f92672">=</span> Thread.<span style="color:#a6e22e">ofVirtual</span>().<span style="color:#a6e22e">name</span>(<span style="color:#e6db74">&#34;my-virtual-thread-&#34;</span>, 3).<span style="color:#a6e22e">factory</span>();
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">try</span> (<span style="color:#66d9ef">var</span> executor <span style="color:#f92672">=</span> Executors.<span style="color:#a6e22e">newThreadPerTaskExecutor</span>(tf)) {
</span></span><span style="display:flex;"><span>            executor.<span style="color:#a6e22e">submit</span>(r);
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// executor that starts a new VT for each task</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">try</span> (<span style="color:#66d9ef">var</span> executor <span style="color:#f92672">=</span> Executors.<span style="color:#a6e22e">newVirtualThreadPerTaskExecutor</span>()) {
</span></span><span style="display:flex;"><span>            executor.<span style="color:#a6e22e">submit</span>(r);
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// creates a platform thread using the new API</span>
</span></span><span style="display:flex;"><span>        Thread t4 <span style="color:#f92672">=</span> Thread.<span style="color:#a6e22e">ofPlatform</span>().<span style="color:#a6e22e">name</span>(<span style="color:#e6db74">&#34;my-platform-thread-1&#34;</span>).<span style="color:#a6e22e">start</span>(r);
</span></span><span style="display:flex;"><span>        t4.<span style="color:#a6e22e">join</span>();
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The code from above produces the following output:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>Hello from my-virtual-thread-1. Am I virtual? true
</span></span><span style="display:flex;"><span>Hello from my-virtual-thread-2. Am I virtual? true
</span></span><span style="display:flex;"><span>Hello from my-virtual-thread-3. Am I virtual? true
</span></span><span style="display:flex;"><span>Hello from . Am I virtual? true
</span></span><span style="display:flex;"><span>Hello from my-platform-thread-1. Am I virtual? false
</span></span></code></pre></div><p>The main API differences between <em>virtual</em> and <em>platform</em> threads are:</p>
<ul>
<li>the public <code>Thread</code> constructors cannot create virtual threads</li>
<li>virtual threads are always daemon threads, they cannot be changed to be non-daemon</li>
<li>virtual threads have a fixed priority, <code>Thread.NORM_PRIORITY</code>, this priority cannot be changed</li>
<li>virtual threads are not active members of thread groups</li>
</ul>
<p>Here are some <em>guidelines</em> to keep in mind when using virtual threads:</p>
<ul>
<li>one thread per task: as virtual threads are lightweight, there is no need to reuse of pool them, just create a new one for each task</li>
<li>blocking I/O inside a <code>synchronized</code> block can pin a virtual thread - this limitation has been removed in Java 24, via <a href="https://openjdk.org/jeps/491" target="_blank">JEP 491: Synchronize Virtual Threads without Pinning</a></li>
<li>minimize thread-local usage: as VTs can be in the millions, excessive use of thread-local variables can lead to memory issues</li>
<li>VTs are most useful when blocking I/O or some other blocking operations, <code>BlockingQueue.take()</code>, are involved, i.e. the workload is not CPU-bound</li>
</ul>
<h2 id="java-22">Java 22</h2>
<h3 id="foreign-function--memory-api">Foreign Function &amp; Memory API</h3>
<p><a href="https://openjdk.org/jeps/454" target="_blank">JEP 454: Foreign Function &amp; Memory API</a> introduces a new API that allows Java programs to interoperate with code and data outside of the Java runtime. This includes calling native functions and accessing native memory.</p>
<p>There is a lot going on in this JEP, so I will not cover it all. Instead, I will show you a simple example of how to use it. Feel free to check the JEP&rsquo;s page.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">import</span> java.lang.foreign.*;
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> java.lang.invoke.MethodHandle;
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> java.lang.invoke.MethodHandles;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">StrlenExample</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">main</span>(String<span style="color:#f92672">[]</span> args) <span style="color:#66d9ef">throws</span> Throwable {
</span></span><span style="display:flex;"><span>        Linker linker <span style="color:#f92672">=</span> Linker.<span style="color:#a6e22e">nativeLinker</span>();
</span></span><span style="display:flex;"><span>        SymbolLookup stdlib <span style="color:#f92672">=</span> linker.<span style="color:#a6e22e">defaultLookup</span>();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        MemorySegment strlenFunc <span style="color:#f92672">=</span> stdlib.<span style="color:#a6e22e">find</span>(<span style="color:#e6db74">&#34;strlen&#34;</span>)
</span></span><span style="display:flex;"><span>                .<span style="color:#a6e22e">orElseThrow</span>(() <span style="color:#f92672">-&gt;</span> <span style="color:#66d9ef">new</span> RuntimeException(<span style="color:#e6db74">&#34;strlen not found&#34;</span>));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        FunctionDescriptor strlenDesc <span style="color:#f92672">=</span> FunctionDescriptor.<span style="color:#a6e22e">of</span>(ValueLayout.<span style="color:#a6e22e">JAVA_LONG</span>, ValueLayout.<span style="color:#a6e22e">ADDRESS</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        MethodHandle strlen <span style="color:#f92672">=</span> linker.<span style="color:#a6e22e">downcallHandle</span>(strlenFunc, strlenDesc);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">try</span> (Arena arena <span style="color:#f92672">=</span> Arena.<span style="color:#a6e22e">ofConfined</span>()) {
</span></span><span style="display:flex;"><span>            MemorySegment cString <span style="color:#f92672">=</span> arena.<span style="color:#a6e22e">allocateFrom</span>(<span style="color:#e6db74">&#34;Hello, FFM!&#34;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">long</span> length <span style="color:#f92672">=</span> (<span style="color:#66d9ef">long</span>) strlen.<span style="color:#a6e22e">invoke</span>(cString);
</span></span><span style="display:flex;"><span>            System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(<span style="color:#e6db74">&#34;Length: &#34;</span> <span style="color:#f92672">+</span> length);
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The code uses Java 22&rsquo;s Foreign Function &amp; Memory (FFM) API to call the native C <code>strlen</code> function, which calculates the length of a C-style string. It first obtains a <em>linker</em> and locates the <code>strlen</code> symbol from the standard C library. Then, it defines the function signature using a <code>FunctionDescriptor</code>, creates a <em>method handle</em> to invoke it, and allocates native memory for the input string using <code>arena.allocateFrom(&quot;Hello, FFM!&quot;)</code>. Finally, it calls the native <code>strlen</code> function and prints the resulting length. The use of Arena ensures safe memory management by automatically freeing the memory when done.</p>
<p>Running the code with the command below will print the length of the string:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>java --enable-native-access<span style="color:#f92672">=</span>ALL-UNNAMED StrlenExample.java
</span></span><span style="display:flex;"><span>Length: <span style="color:#ae81ff">11</span>
</span></span></code></pre></div><p>The <code>--enable-native-access=ALL-UNNAMED</code> flag is necessary to allow the unnamed module (i.e., code not in a named module) to access native code.</p>
<h3 id="unnamed-variables-and-patterns">Unnamed Variables and Patterns</h3>
<p><a href="https://openjdk.org/jeps/456" target="_blank">JEP 456: Unnamed Variables &amp; Patterns</a> summarizes this enhancement as follows:</p>
<blockquote>
<p>Enhance the Java programming language with unnamed variables and unnamed patterns, which can be used when <em>variable declarations</em> or <em>nested patterns</em> are required but never used. Both are denoted by the underscore character, _.</p>
<p>&ndash; <!-- raw HTML omitted --><a href="https://openjdk.org/jeps/456" target="_blank">JEP 456: Unnamed Variables &amp; Patterns</a><!-- raw HTML omitted --></p>
</blockquote>
<p>Let&rsquo;s see some examples:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">import</span> java.util.List;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">AboutUnnamedVarsAndPatterns</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">main</span>(String<span style="color:#f92672">[]</span> args) {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> words <span style="color:#f92672">=</span> List.<span style="color:#a6e22e">of</span>(<span style="color:#e6db74">&#34;one&#34;</span>, <span style="color:#e6db74">&#34;two&#34;</span>, <span style="color:#e6db74">&#34;three&#34;</span>);
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> counter <span style="color:#f92672">=</span> 0;
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// we do not do anything with a word</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">for</span> (String _ : words) {
</span></span><span style="display:flex;"><span>            counter<span style="color:#f92672">++</span>;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>        System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(counter);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> a <span style="color:#f92672">=</span> 1;
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> b <span style="color:#f92672">=</span> 2;
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// normally, the next line would be removed, in this case it illustrates a point</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> _ <span style="color:#f92672">=</span> 3;
</span></span><span style="display:flex;"><span>        System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(a <span style="color:#f92672">+</span> b);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> notANumber <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;boom&#34;</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">try</span> {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">int</span> _ <span style="color:#f92672">=</span> Integer.<span style="color:#a6e22e">parseInt</span>(notANumber);
</span></span><span style="display:flex;"><span>        } <span style="color:#66d9ef">catch</span> (NumberFormatException _) {
</span></span><span style="display:flex;"><span>            System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(<span style="color:#e6db74">&#34;Bad number: &#34;</span> <span style="color:#f92672">+</span> notANumber);
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(generateText(<span style="color:#66d9ef">new</span> Circle(<span style="color:#66d9ef">new</span> Point(0, 0), 1)));
</span></span><span style="display:flex;"><span>        System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(generateText(<span style="color:#66d9ef">new</span> Line(<span style="color:#66d9ef">new</span> Point(1, 1), <span style="color:#66d9ef">new</span> Point(2, 2))));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">static</span> String <span style="color:#a6e22e">generateText</span>(Shape s) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">switch</span> (s) {
</span></span><span style="display:flex;"><span>            <span style="color:#75715e">// an example of unnamed pattern variable: `var _`, as we are not interested in</span>
</span></span><span style="display:flex;"><span>            <span style="color:#75715e">// the circle&#39;s radius</span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">case</span> Circle(Point(<span style="color:#66d9ef">var</span> x, <span style="color:#66d9ef">var</span> y), <span style="color:#66d9ef">var</span> _) <span style="color:#f92672">-&gt;</span> <span style="color:#e6db74">&#34;Center: (%d, %d)&#34;</span>.<span style="color:#a6e22e">formatted</span>(x, y);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            <span style="color:#75715e">// as we are not interested in the second point we can ignore it completely,</span>
</span></span><span style="display:flex;"><span>            <span style="color:#75715e">// this is an example of a unnnamed pattern</span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">case</span> Line(Point(<span style="color:#66d9ef">var</span> startX, <span style="color:#66d9ef">var</span> startY), _) <span style="color:#f92672">-&gt;</span>
</span></span><span style="display:flex;"><span>                <span style="color:#e6db74">&#34;Start: (%d, %d)&#34;</span>.<span style="color:#a6e22e">formatted</span>(startX, startY);
</span></span><span style="display:flex;"><span>        };
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">record</span> <span style="color:#a6e22e">Point</span>(<span style="color:#66d9ef">int</span> x, <span style="color:#66d9ef">int</span> y) {
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">sealed</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">Shape</span> permits Circle, Line {
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">record</span> <span style="color:#a6e22e">Circle</span>(Point center, <span style="color:#66d9ef">int</span> radius) <span style="color:#66d9ef">implements</span> Shape {
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">record</span> <span style="color:#a6e22e">Line</span>(Point start, Point end) <span style="color:#66d9ef">implements</span> Shape {
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>To summarize, we have:</p>
<ul>
<li><code>for (String _ : words) {</code> -&gt; unnamed variable</li>
<li><code>var _ = 3;</code> -&gt; unnamed variable</li>
<li><code>catch (NumberFormatException _) {</code> -&gt; unnamed variable</li>
<li><code>case Circle(Point(var x, var y), var _) -&gt;</code> -&gt; unnamed pattern variable</li>
<li><code>case Line(Point(var startX, var startY), _) -&gt;</code> -&gt; unnamed pattern</li>
</ul>
<h3 id="launch-multi-file-source-code-programs">Launch Multi-File Source-Code Programs</h3>
<p><a href="https://openjdk.org/jeps/458" target="_blank">JEP 458: Launch Multi-File Source-Code Programs</a> enhances the java application launcher to be able to run a program supplied as multiple files of Java source code.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#75715e">// File: First.java</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">First</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">run</span>() {
</span></span><span style="display:flex;"><span>        System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(First.<span style="color:#a6e22e">class</span>.<span style="color:#a6e22e">getName</span>());
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// File: Second.java</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Second</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">run</span>() {
</span></span><span style="display:flex;"><span>        System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(Second.<span style="color:#a6e22e">class</span>.<span style="color:#a6e22e">getName</span>());
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// File: JEP458.java</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">JEP458</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">main</span>(String<span style="color:#f92672">[]</span> args) {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> first <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> First();
</span></span><span style="display:flex;"><span>        first.<span style="color:#a6e22e">run</span>();
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> second <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> Second();
</span></span><span style="display:flex;"><span>        second.<span style="color:#a6e22e">run</span>();
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Running <code>java JEP458.java</code> will print:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>First
</span></span><span style="display:flex;"><span>Second
</span></span></code></pre></div><h2 id="java-23">Java 23</h2>
<h3 id="markdown-documentation-comments">Markdown Documentation Comments</h3>
<p><a href="https://openjdk.org/jeps/467" target="_blank">JEP 467: Markdown Documentation Comments</a> introduces a new way to write documentation comments using Markdown syntax.</p>
<p>Let&rsquo;s have a look at the following example:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">JEP467</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">/// ## Start of documentation</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">///</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">/// This _documentation_ was written in Markdown.</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">///</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">/// - `This`</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">/// - is</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">/// - cool.</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">///</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">/// Simple tables are supported:</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">///</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">/// | Latin | Greek |</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">/// |-------|-------|</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">/// | a     | alpha |</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">/// | b     | beta  |</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">///</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">/// This is some Java code:</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">///</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">/// ```java</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">/// System.out.println(&#34;Mind blowing&#34;);</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">/// ```</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">///</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">/// ## End of documentation</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">main</span>(String<span style="color:#f92672">[]</span> args) {
</span></span><span style="display:flex;"><span>        System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(greet(<span style="color:#e6db74">&#34;Vlad&#34;</span>));
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">/// This method builds a greeting and gives it back.</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">///</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">/// @param name the name to use in the greeting</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">/// @return a greeting as a string</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> String <span style="color:#a6e22e">greet</span>(String name) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#e6db74">&#34;Hello, %s!&#34;</span>.<span style="color:#a6e22e">formatted</span>(name);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Note the use of the <code>///</code> prefix for the documentation comments.</p>
<p>Give it a run with the following command:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>javadoc -d docs JEP467.java
</span></span></code></pre></div><h2 id="java-24">Java 24</h2>
<h3 id="class-file-api">Class-File API</h3>
<p><a href="https://openjdk.org/jeps/484" target="_blank">JEP 484: Class-File API</a> provides a standard API for parsing, generating, and transforming Java class files. Take a look at the JEP for more information, as I will not cover it here.</p>
<h3 id="stream-gatherers">Stream Gatherers</h3>
<p><a href="https://openjdk.org/jeps/485" target="_blank">JEP 485: Stream Gatherers</a> enhances the Stream API to support <em>custom <strong>intermediate</strong> operations</em>, allowing stream pipelines to transform data in ways that are <em>not easily achievable</em> with the existing operations.</p>
<p>The core concept is a <em>gatherer</em>, which represents a transform of the elements of a stream. Gatherers can be used to transform elements in a one-to-one, one-to-many, many-to-one, or many-to-many fashion. They can also track previously seen elements in order to influence the transformation of subsequent elements.</p>
<p>From a technical point of view, there are three elements involved in this API:</p>
<ul>
<li>the <code>java.util.stream.Gatherer</code> interface, which models a gatherer</li>
<li>the <code>gather</code> method in the <code>java.util.stream.Stream</code> interface, which takes a <code>Gatherer</code> as an argument</li>
<li>the <code>java.util.stream.Gatherers</code> class, which provides a set of built-in gatherers</li>
</ul>
<p>The <code>java.util.stream.Gatherers</code> class introduces the following built-in gatherers:</p>
<ul>
<li><a href="https://cr.openjdk.org/~vklang/gatherers/api/java.base/java/util/stream/Gatherers.html#fold%28java.util.function.Supplier,java.util.function.BiFunction%29" target="_blank">fold</a> - performs an ordered reduction-like transformation</li>
<li><a href="https://cr.openjdk.org/~vklang/gatherers/api/java.base/java/util/stream/Gatherers.html#mapConcurrent%28int,java.util.function.Function%29" target="_blank">mapConcurrent</a> - executes a mapping function with a configured level of max concurrency, using virtual threads, preserving the ordering of the stream</li>
<li><a href="https://cr.openjdk.org/~vklang/gatherers/api/java.base/java/util/stream/Gatherers.html#scan%28java.util.function.Supplier,java.util.function.BiFunction%29" target="_blank">scan</a> - performs an incremental accumulation starting from an initial value, and each subsequent value being obtained by applying the given function to the current value and the next input element</li>
<li><a href="https://cr.openjdk.org/~vklang/gatherers/api/java.base/java/util/stream/Gatherers.html#windowFixed%28int%29" target="_blank">windowFixed</a> - gathers elements into a window of a fixed size</li>
<li><a href="https://cr.openjdk.org/~vklang/gatherers/api/java.base/java/util/stream/Gatherers.html#windowSliding%28int%29" target="_blank">windowSliding</a> - gathers elements into windows of a given size, where each subsequent window includes all elements of the previous window, except for the least recent</li>
</ul>
<p>Let&rsquo;s see now some examples:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">import</span> java.util.List;
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> java.util.stream.Gatherers;
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> java.util.stream.Stream;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">AboutGatherers</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">main</span>(String<span style="color:#f92672">[]</span> args) {
</span></span><span style="display:flex;"><span>        List<span style="color:#f92672">&lt;</span>List<span style="color:#f92672">&lt;</span>Integer<span style="color:#f92672">&gt;&gt;</span> result1 <span style="color:#f92672">=</span>
</span></span><span style="display:flex;"><span>                Stream.<span style="color:#a6e22e">of</span>(1, 2, 3, 4, 5, 6, 7, 8).<span style="color:#a6e22e">gather</span>(Gatherers.<span style="color:#a6e22e">windowFixed</span>(3)).<span style="color:#a6e22e">toList</span>();
</span></span><span style="display:flex;"><span>        System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(<span style="color:#e6db74">&#34;result1 = &#34;</span> <span style="color:#f92672">+</span> result1);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        List<span style="color:#f92672">&lt;</span>List<span style="color:#f92672">&lt;</span>Integer<span style="color:#f92672">&gt;&gt;</span> result2 <span style="color:#f92672">=</span>
</span></span><span style="display:flex;"><span>                Stream.<span style="color:#a6e22e">of</span>(1, 2, 3, 4, 5, 6, 7, 8).<span style="color:#a6e22e">gather</span>(Gatherers.<span style="color:#a6e22e">windowSliding</span>(2)).<span style="color:#a6e22e">toList</span>();
</span></span><span style="display:flex;"><span>        System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(<span style="color:#e6db74">&#34;result2 = &#34;</span> <span style="color:#f92672">+</span> result2);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        List<span style="color:#f92672">&lt;</span>String<span style="color:#f92672">&gt;</span> result3 <span style="color:#f92672">=</span>
</span></span><span style="display:flex;"><span>                Stream.<span style="color:#a6e22e">of</span>(1, 2, 3, 4, 5, 6, 7, 8, 9)
</span></span><span style="display:flex;"><span>                        .<span style="color:#a6e22e">gather</span>(
</span></span><span style="display:flex;"><span>                                Gatherers.<span style="color:#a6e22e">scan</span>(() <span style="color:#f92672">-&gt;</span> <span style="color:#e6db74">&#34;&#34;</span>, (string, number) <span style="color:#f92672">-&gt;</span> string <span style="color:#f92672">+</span> number)
</span></span><span style="display:flex;"><span>                        )
</span></span><span style="display:flex;"><span>                        .<span style="color:#a6e22e">toList</span>();
</span></span><span style="display:flex;"><span>        System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(<span style="color:#e6db74">&#34;result3 = &#34;</span> <span style="color:#f92672">+</span> result3);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> result4 <span style="color:#f92672">=</span> Stream.<span style="color:#a6e22e">iterate</span>(1, n <span style="color:#f92672">-&gt;</span> n <span style="color:#f92672">+</span> 1).<span style="color:#a6e22e">limit</span>(9).<span style="color:#a6e22e">gather</span>(
</span></span><span style="display:flex;"><span>                Gatherers.<span style="color:#a6e22e">mapConcurrent</span>(3, n <span style="color:#f92672">-&gt;</span> n <span style="color:#f92672">*</span> n)
</span></span><span style="display:flex;"><span>        ).<span style="color:#a6e22e">toList</span>();
</span></span><span style="display:flex;"><span>        System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(<span style="color:#e6db74">&#34;result4 = &#34;</span> <span style="color:#f92672">+</span> result4);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        String result5 <span style="color:#f92672">=</span>
</span></span><span style="display:flex;"><span>                Stream.<span style="color:#a6e22e">of</span>(1, 2, 3, 4, 5, 6, 7, 8, 9)
</span></span><span style="display:flex;"><span>                        .<span style="color:#a6e22e">gather</span>(
</span></span><span style="display:flex;"><span>                                Gatherers.<span style="color:#a6e22e">fold</span>(() <span style="color:#f92672">-&gt;</span> <span style="color:#e6db74">&#34;&#34;</span>, (string, number) <span style="color:#f92672">-&gt;</span> string <span style="color:#f92672">+</span> number)
</span></span><span style="display:flex;"><span>                        ).<span style="color:#a6e22e">findFirst</span>().<span style="color:#a6e22e">orElse</span>(<span style="color:#e6db74">&#34;&#34;</span>);
</span></span><span style="display:flex;"><span>        System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(<span style="color:#e6db74">&#34;result5 = &#34;</span> <span style="color:#f92672">+</span> result5);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The output of the code above is:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>result1 <span style="color:#f92672">=</span> <span style="color:#f92672">[[</span>1, 2, 3<span style="color:#f92672">]</span>, <span style="color:#f92672">[</span>4, 5, 6<span style="color:#f92672">]</span>, <span style="color:#f92672">[</span>7, 8<span style="color:#f92672">]]</span>
</span></span><span style="display:flex;"><span>result2 <span style="color:#f92672">=</span> <span style="color:#f92672">[[</span>1, 2<span style="color:#f92672">]</span>, <span style="color:#f92672">[</span>2, 3<span style="color:#f92672">]</span>, <span style="color:#f92672">[</span>3, 4<span style="color:#f92672">]</span>, <span style="color:#f92672">[</span>4, 5<span style="color:#f92672">]</span>, <span style="color:#f92672">[</span>5, 6<span style="color:#f92672">]</span>, <span style="color:#f92672">[</span>6, 7<span style="color:#f92672">]</span>, <span style="color:#f92672">[</span>7, 8<span style="color:#f92672">]]</span>
</span></span><span style="display:flex;"><span>result3 <span style="color:#f92672">=</span> <span style="color:#f92672">[</span>1, 12, 123, 1234, 12345, 123456, 1234567, 12345678, 123456789<span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>result4 <span style="color:#f92672">=</span> <span style="color:#f92672">[</span>1, 4, 9, 16, 25, 36, 49, 64, 81<span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>result5 <span style="color:#f92672">=</span> <span style="color:#ae81ff">123456789</span>
</span></span></code></pre></div><p>We can also write our own gatherers. The following example shows how to implement a custom gatherer that implements the <em>distinct by length</em> operation. This means that we will only keep the first occurrence of each element, based on its length.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> Gatherer<span style="color:#f92672">&lt;</span>String, Set<span style="color:#f92672">&lt;</span>Integer<span style="color:#f92672">&gt;</span>, String<span style="color:#f92672">&gt;</span> <span style="color:#a6e22e">distinctByLength</span>() {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> Gatherer.<span style="color:#a6e22e">ofSequential</span>(
</span></span><span style="display:flex;"><span>            HashSet::<span style="color:#66d9ef">new</span>,
</span></span><span style="display:flex;"><span>            (seen, element, downstream) <span style="color:#f92672">-&gt;</span> {
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">if</span> (downstream.<span style="color:#a6e22e">isRejecting</span>()) {
</span></span><span style="display:flex;"><span>                    <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">false</span>;
</span></span><span style="display:flex;"><span>                }
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">if</span> (seen.<span style="color:#a6e22e">add</span>(element.<span style="color:#a6e22e">length</span>())) {
</span></span><span style="display:flex;"><span>                    downstream.<span style="color:#a6e22e">push</span>(element);
</span></span><span style="display:flex;"><span>                }
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">true</span>;
</span></span><span style="display:flex;"><span>            }
</span></span><span style="display:flex;"><span>    );
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Using the custom gatherer is as simple as:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> distinctByLength <span style="color:#f92672">=</span> Stream.<span style="color:#a6e22e">of</span>(<span style="color:#e6db74">&#34;a&#34;</span>, <span style="color:#e6db74">&#34;bc&#34;</span>, <span style="color:#e6db74">&#34;de&#34;</span>, <span style="color:#e6db74">&#34;fgh&#34;</span>).<span style="color:#a6e22e">gather</span>(distinctByLength()).<span style="color:#a6e22e">toList</span>();
</span></span><span style="display:flex;"><span>System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(distinctByLength);
</span></span></code></pre></div><p>The output of the code above is:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span><span style="color:#f92672">[</span>a, bc, fgh<span style="color:#f92672">]</span>
</span></span></code></pre></div><p>Have a look at the <a href="https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/util/stream/Gatherer.html" target="_blank">Gatherer interface</a>, especially at the <code>ofSequential</code> and <code>of</code> methods, to see  in more detail how to implement your own gatherers. In the example above, we used the <code>ofSequential</code> method, which is a convenience method, that calls the <code>of</code> method, passing in the <em>initializer</em> and the <em>integrator</em>. The <em>combiner</em> and the <em>finisher</em> are the default ones.</p>
<h3 id="synchronized-virtual-threads-without-pinning">Synchronized Virtual Threads without Pinning</h3>
<p><a href="https://openjdk.org/jeps/491" target="_blank">JEP 491: Synchronize Virtual Threads without Pinning</a> fixes the issue of <em>pinning</em> virtual threads when using <code>synchronized</code> blocks or methods. This means that we can now use <code>synchronized</code> blocks and methods without pinning the virtual thread to its carrier. Check the JEP&rsquo;s page for the nitty-gritty details.</p>
<h2 id="conclusion">Conclusion</h2>
<p>The Java language is evolving like never before, and the features I touched upon in this post are just a small part of the whole picture. Make sure to check the release notes for each version for a complete picture. The language itself is becoming more expressive and powerful and tackles areas that were previously the main domain of other languages. This is a good thing! It&rsquo;s a good time to be a Java developer.</p>
<h2 id="references">References</h2>
<ul>
<li><a href="https://www.oracle.com/es/java/technologies/java-se-support-roadmap.html" target="_blank">Java SE Support Roadmap</a></li>
<li><a href="https://openjdk.org/projects/jdk/24/" target="_blank">Java 24</a></li>
</ul>
]]></content>
        </item>
        
        <item>
            <title>Machine Learning Zoomcamp: The Rest</title>
            <link>https://vladflore.tech/posts/2025/04/machine-learning-zoomcamp-the-rest/</link>
            <pubDate>Fri, 18 Apr 2025 00:00:00 +0000</pubDate>
            
            <guid>https://vladflore.tech/posts/2025/04/machine-learning-zoomcamp-the-rest/</guid>
            <description>&lt;h2 id=&#34;intro&#34;&gt;Intro&lt;/h2&gt;
&lt;p&gt;This post covers the rest of the modules of the Machine Learning Zoomcamp, including the midterm and the two capstone projects.&lt;/p&gt;
&lt;p&gt;Below are the posts for the previous modules:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;https://vladflore.tech/posts/2024/09/machine-learning-zoomcamp-module-1-recap/&#34;&gt;Machine Learning Zoomcamp Module 1&lt;/a&gt; - points received: &lt;em&gt;9&lt;/em&gt; (&lt;em&gt;7&lt;/em&gt;/7 for questions + &lt;em&gt;2&lt;/em&gt; bonus for learning in public)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://vladflore.tech/posts/2024/10/machine-learning-zoomcamp-module-2-recap/&#34;&gt;Machine Learning Zoomcamp Module 2&lt;/a&gt; - points received: &lt;em&gt;5&lt;/em&gt; (&lt;em&gt;5&lt;/em&gt;/6 for questions + &lt;em&gt;0&lt;/em&gt; bonus for learning in public)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://vladflore.tech/posts/2024/12/machine-learning-zoomcamp-module-3-recap/&#34;&gt;Machine Learning Zoomcamp Module 3&lt;/a&gt; - points received: &lt;em&gt;7&lt;/em&gt; (&lt;em&gt;6&lt;/em&gt;/6 for questions + &lt;em&gt;1&lt;/em&gt; bonus for learning in public)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://vladflore.tech/posts/2024/12/machine-learning-zoomcamp-module-4-recap/&#34;&gt;Machine Learning Zoomcamp Module 4&lt;/a&gt; - points received: &lt;em&gt;6&lt;/em&gt; (&lt;em&gt;6&lt;/em&gt;/6 for questions + &lt;em&gt;0&lt;/em&gt; bonus for learning in public)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://vladflore.tech/posts/2025/01/machine-learning-zoomcamp-module-5-recap/&#34;&gt;Machine Learning Zoomcamp Module 5&lt;/a&gt; - points received: &lt;em&gt;6&lt;/em&gt; (&lt;em&gt;6&lt;/em&gt;/6 for questions + &lt;em&gt;0&lt;/em&gt; bonus for learning in public)&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;module-6---decision-trees-and-ensemble-learning&#34;&gt;Module 6 - Decision Trees and Ensemble Learning&lt;/h2&gt;
&lt;p&gt;Points received: &lt;em&gt;6&lt;/em&gt;&lt;/p&gt;</description>
            <content type="html"><![CDATA[<h2 id="intro">Intro</h2>
<p>This post covers the rest of the modules of the Machine Learning Zoomcamp, including the midterm and the two capstone projects.</p>
<p>Below are the posts for the previous modules:</p>
<ol>
<li><a href="https://vladflore.tech/posts/2024/09/machine-learning-zoomcamp-module-1-recap/">Machine Learning Zoomcamp Module 1</a> - points received: <em>9</em> (<em>7</em>/7 for questions + <em>2</em> bonus for learning in public)</li>
<li><a href="https://vladflore.tech/posts/2024/10/machine-learning-zoomcamp-module-2-recap/">Machine Learning Zoomcamp Module 2</a> - points received: <em>5</em> (<em>5</em>/6 for questions + <em>0</em> bonus for learning in public)</li>
<li><a href="https://vladflore.tech/posts/2024/12/machine-learning-zoomcamp-module-3-recap/">Machine Learning Zoomcamp Module 3</a> - points received: <em>7</em> (<em>6</em>/6 for questions + <em>1</em> bonus for learning in public)</li>
<li><a href="https://vladflore.tech/posts/2024/12/machine-learning-zoomcamp-module-4-recap/">Machine Learning Zoomcamp Module 4</a> - points received: <em>6</em> (<em>6</em>/6 for questions + <em>0</em> bonus for learning in public)</li>
<li><a href="https://vladflore.tech/posts/2025/01/machine-learning-zoomcamp-module-5-recap/">Machine Learning Zoomcamp Module 5</a> - points received: <em>6</em> (<em>6</em>/6 for questions + <em>0</em> bonus for learning in public)</li>
</ol>
<h2 id="module-6---decision-trees-and-ensemble-learning">Module 6 - Decision Trees and Ensemble Learning</h2>
<p>Points received: <em>6</em></p>
<p>The homework code can be found <a href="https://github.com/vladflore/machine-learning-zoomcamp-cohort-2024/blob/main/06-trees-hw.ipynb" target="_blank">here</a>.</p>
<h2 id="midterm-project">Midterm Project</h2>
<p>Passed ✅ w/ <em>23</em> points.</p>
<p>The project can be found <a href="https://github.com/vladflore/machine-learning-zoomcamp-cohort-2024/tree/main/midterm" target="_blank">here</a>.</p>
<h2 id="module-8---neural-networks-and-deep-learning">Module 8 - Neural Networks and Deep Learning</h2>
<p>Points received: <em>6</em></p>
<p>The homework can be found <a href="https://github.com/vladflore/machine-learning-zoomcamp-cohort-2024/blob/main/08-deep-learning-hw.ipynb" target="_blank">here</a>.</p>
<h2 id="module-9---serverless-deep-learning">Module 9 - Serverless Deep Learning</h2>
<p>Points received: <em>6</em></p>
<p>The homework can be found <a href="https://github.com/vladflore/machine-learning-zoomcamp-cohort-2024/tree/main/09-serverless" target="_blank">here</a>.</p>
<h2 id="module-10---kubernetes-and-tensorflow-serving">Module 10 - Kubernetes and TensorFlow Serving</h2>
<p>Points received: <em>7</em></p>
<p>The homework can be found <a href="https://github.com/vladflore/machine-learning-zoomcamp-cohort-2024/tree/main/10-k8s" target="_blank">here</a>.</p>
<h2 id="capstone-1-project">Capstone 1 Project</h2>
<p>Passed ✅ w/ <em>21</em> points.</p>
<p>The project can be found <a href="https://github.com/vladflore/machine-learning-zoomcamp-cohort-2024/tree/main/capstone1" target="_blank">here</a>.</p>
<h2 id="capstone-2-project">Capstone 2 Project</h2>
<p>Passed ✅ w/ <em>24</em> points.</p>
<p>The project can be found <a href="https://github.com/vladflore/machine-learning-zoomcamp-cohort-2024/tree/main/capstone2" target="_blank">here</a>.</p>
<h2 id="conclusion">Conclusion</h2>
<p>Total score: <em>127</em></p>
<p>Positioned <em>27</em> of <em>760</em> students who have submited at least one homework.</p>
<p><a href="https://certificate.datatalks.club/ml-zoomcamp/2024/8a544aac437ae33c0a6ff12c8547ac2f9d1bb859.pdf" target="_blank">Certificate</a>.</p>
<p>Overall, the course was very well structured and the content was very well presented. The projects were challenging but doable, and the community was very supportive. I would highly recommend this course to anyone interested in getting into machine learning. The course is very hands-on and provides a lot of practical experience.</p>
]]></content>
        </item>
        
        <item>
            <title>Machine Learning Zoomcamp: Module 5 Recap</title>
            <link>https://vladflore.tech/posts/2025/01/machine-learning-zoomcamp-module-5-recap/</link>
            <pubDate>Sun, 26 Jan 2025 00:00:00 +0000</pubDate>
            
            <guid>https://vladflore.tech/posts/2025/01/machine-learning-zoomcamp-module-5-recap/</guid>
            <description>&lt;h2 id=&#34;intro&#34;&gt;Intro&lt;/h2&gt;
&lt;p&gt;This post is a recap of the Machine Learning Zoomcamp Module 5.&lt;/p&gt;
&lt;p&gt;Below are the posts for the previous modules:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;https://vladflore.tech/posts/2024/09/machine-learning-zoomcamp-module-1-recap/&#34;&gt;Machine Learning Zoomcamp Module 1&lt;/a&gt; - points received: &lt;em&gt;9&lt;/em&gt; (&lt;em&gt;7&lt;/em&gt;/7 for questions + &lt;em&gt;2&lt;/em&gt; bonus for learning in public)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://vladflore.tech/posts/2024/10/machine-learning-zoomcamp-module-2-recap/&#34;&gt;Machine Learning Zoomcamp Module 2&lt;/a&gt; - points received: &lt;em&gt;5&lt;/em&gt; (&lt;em&gt;5&lt;/em&gt;/6 for questions + &lt;em&gt;0&lt;/em&gt; bonus for learning in public)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://vladflore.tech/posts/2024/12/machine-learning-zoomcamp-module-3-recap/&#34;&gt;Machine Learning Zoomcamp Module 3&lt;/a&gt; - points received: &lt;em&gt;7&lt;/em&gt; (&lt;em&gt;6&lt;/em&gt;/6 for questions + &lt;em&gt;1&lt;/em&gt; bonus for learning in public)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://vladflore.tech/posts/2024/12/machine-learning-zoomcamp-module-4-recap/&#34;&gt;Machine Learning Zoomcamp Module 4&lt;/a&gt; - points received: &lt;em&gt;6&lt;/em&gt; (&lt;em&gt;6&lt;/em&gt;/6 for questions + &lt;em&gt;0&lt;/em&gt; bonus for learning in public)&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;the-gist-of-the-module&#34;&gt;The gist of the module&lt;/h2&gt;
&lt;p&gt;This module is all about deploying the machine learning model we built in the previous modules. Specifically, we&amp;rsquo;ll save the model to a file and then load it and expose it as a web service that can be consumed by others.&lt;/p&gt;</description>
            <content type="html"><![CDATA[<h2 id="intro">Intro</h2>
<p>This post is a recap of the Machine Learning Zoomcamp Module 5.</p>
<p>Below are the posts for the previous modules:</p>
<ol>
<li><a href="https://vladflore.tech/posts/2024/09/machine-learning-zoomcamp-module-1-recap/">Machine Learning Zoomcamp Module 1</a> - points received: <em>9</em> (<em>7</em>/7 for questions + <em>2</em> bonus for learning in public)</li>
<li><a href="https://vladflore.tech/posts/2024/10/machine-learning-zoomcamp-module-2-recap/">Machine Learning Zoomcamp Module 2</a> - points received: <em>5</em> (<em>5</em>/6 for questions + <em>0</em> bonus for learning in public)</li>
<li><a href="https://vladflore.tech/posts/2024/12/machine-learning-zoomcamp-module-3-recap/">Machine Learning Zoomcamp Module 3</a> - points received: <em>7</em> (<em>6</em>/6 for questions + <em>1</em> bonus for learning in public)</li>
<li><a href="https://vladflore.tech/posts/2024/12/machine-learning-zoomcamp-module-4-recap/">Machine Learning Zoomcamp Module 4</a> - points received: <em>6</em> (<em>6</em>/6 for questions + <em>0</em> bonus for learning in public)</li>
</ol>
<h2 id="the-gist-of-the-module">The gist of the module</h2>
<p>This module is all about deploying the machine learning model we built in the previous modules. Specifically, we&rsquo;ll save the model to a file and then load it and expose it as a web service that can be consumed by others.</p>
<h2 id="saving-and-loading-the-model">Saving and loading the model</h2>
<p>We can use the <code>pickle</code> library to save the model to a file and load it back.</p>
<p>Saving the model and the dictionary vectorizer:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#f92672">import</span> pickle
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">with</span> open(<span style="color:#e6db74">&#39;model.bin&#39;</span>, <span style="color:#e6db74">&#39;wb&#39;</span>) <span style="color:#66d9ef">as</span> model_file_out:
</span></span><span style="display:flex;"><span>    pickle<span style="color:#f92672">.</span>dump(model, model_file_out)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">with</span> open(<span style="color:#e6db74">&#39;dv.bin&#39;</span>, <span style="color:#e6db74">&#39;wb&#39;</span>) <span style="color:#66d9ef">as</span> dv_file_out:
</span></span><span style="display:flex;"><span>    pickle<span style="color:#f92672">.</span>dump(dv, dv_file_out)
</span></span></code></pre></div><p>Loading the model and the dictionary vectorizer:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#f92672">import</span> pickle
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">with</span> open(<span style="color:#e6db74">&#39;model.bin&#39;</span>, <span style="color:#e6db74">&#39;rb&#39;</span>) <span style="color:#66d9ef">as</span> model_file_in:
</span></span><span style="display:flex;"><span>    model <span style="color:#f92672">=</span> pickle<span style="color:#f92672">.</span>load(model_file_in)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">with</span> open(<span style="color:#e6db74">&#39;dv.bin&#39;</span>, <span style="color:#e6db74">&#39;rb&#39;</span>) <span style="color:#66d9ef">as</span> dv_file_in:
</span></span><span style="display:flex;"><span>    dv <span style="color:#f92672">=</span> pickle<span style="color:#f92672">.</span>load(dv_file_in)
</span></span></code></pre></div><p>If the <code>pickle</code> library is not installed, we can install it using <code>pip install pickle-mixin</code>.</p>
<h2 id="building-a-web-service">Building a web service</h2>
<p>We can use the <code>flask</code> library to build the web service and expose the model.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#f92672">import</span> pickle
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">from</span> sklearn.feature_extraction <span style="color:#f92672">import</span> DictVectorizer
</span></span><span style="display:flex;"><span><span style="color:#f92672">from</span> sklearn.linear_model <span style="color:#f92672">import</span> LogisticRegression
</span></span><span style="display:flex;"><span><span style="color:#f92672">from</span> flask <span style="color:#f92672">import</span> Flask
</span></span><span style="display:flex;"><span><span style="color:#f92672">from</span> flask <span style="color:#f92672">import</span> request
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>app <span style="color:#f92672">=</span> Flask(<span style="color:#e6db74">&#39;prediction-service&#39;</span>)
</span></span><span style="display:flex;"><span>model_file <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;model.bin&#34;</span>
</span></span><span style="display:flex;"><span>dv_file <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;dv.bin&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">@app.route</span>(<span style="color:#e6db74">&#39;/predict&#39;</span>, methods<span style="color:#f92672">=</span>[<span style="color:#e6db74">&#39;POST&#39;</span>])
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">predict</span>():
</span></span><span style="display:flex;"><span>    customer <span style="color:#f92672">=</span> request<span style="color:#f92672">.</span>get_json()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">with</span> open(model_file, <span style="color:#e6db74">&#39;rb&#39;</span>) <span style="color:#66d9ef">as</span> model_file_in:
</span></span><span style="display:flex;"><span>       model <span style="color:#f92672">=</span> pickle<span style="color:#f92672">.</span>load(model_file_in)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">with</span> open(dv_file, <span style="color:#e6db74">&#39;rb&#39;</span>) <span style="color:#66d9ef">as</span> dv_file_in:
</span></span><span style="display:flex;"><span>       dv <span style="color:#f92672">=</span> pickle<span style="color:#f92672">.</span>load(dv_file_in)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    X <span style="color:#f92672">=</span> dv<span style="color:#f92672">.</span>transform([customer])
</span></span><span style="display:flex;"><span>    prediction <span style="color:#f92672">=</span> model<span style="color:#f92672">.</span>predict_proba(X)[<span style="color:#ae81ff">0</span>,<span style="color:#ae81ff">1</span>]
</span></span><span style="display:flex;"><span>    result <span style="color:#f92672">=</span> {<span style="color:#e6db74">&#39;prediction&#39;</span>: float(prediction)}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> result
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> __name__ <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;__main__&#34;</span>:
</span></span><span style="display:flex;"><span>    app<span style="color:#f92672">.</span>run(debug<span style="color:#f92672">=</span><span style="color:#66d9ef">True</span>, host<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;0.0.0.0&#39;</span>, port<span style="color:#f92672">=</span><span style="color:#ae81ff">9696</span>)
</span></span></code></pre></div><p>With the code above in a file called <code>prediction_service.py</code>, we can run the web service by running:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>python prediction_service.py
</span></span></code></pre></div><p>While the code above is a simple example, it&rsquo;s not recommended to use it in production. For production, we should consider using a production-ready web server (<a href="https://en.wikipedia.org/wiki/Web_Server_Gateway_Interface" target="_blank">WSGI</a>) like <code>gunicorn</code>. This is as simple as running:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>gunicorn --bind 0.0.0.0:9696 prediction_service:app
</span></span></code></pre></div><p>To install <code>gunicorn</code>, we can run <code>pip install gunicorn</code>.</p>
<h2 id="containerization">Containerization</h2>
<h3 id="dependencies-management">Dependencies management</h3>
<p>We can use <a href="https://pipenv.pypa.io/en/latest/" target="_blank"><code>pipenv</code></a> to manage the dependencies for the web service.</p>
<p>Installing the dependencies is as easy as running:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>pipenv install &lt;dependency&gt;
</span></span></code></pre></div><p>This will create a <code>Pipfile</code> and a <code>Pipfile.lock</code> file that we can use to install the dependencies in a different environment.</p>
<h3 id="create-a-dockerfile">Create a <code>Dockerfile</code></h3>
<p>We can use Docker to containerize the web service.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-Dockerfile" data-lang="Dockerfile"><span style="display:flex;"><span><span style="color:#75715e"># Use the specified base image</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#66d9ef">FROM</span> <span style="color:#e6db74">svizor/zoomcamp-model:3.11.5-slim</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"># Set the working directory inside the container</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#66d9ef">WORKDIR</span> <span style="color:#e6db74">/app</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"># Copy Pipfile and Pipfile.lock to the working directory</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#66d9ef">COPY</span> <span style="color:#f92672">[</span><span style="color:#e6db74">&#34;Pipfile&#34;</span>, <span style="color:#e6db74">&#34;Pipfile.lock&#34;</span>, <span style="color:#e6db74">&#34;./&#34;</span><span style="color:#f92672">]</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"># Install pipenv</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#66d9ef">RUN</span> pip install pipenv<span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"># Install dependencies defined in Pipfile.lock</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#66d9ef">RUN</span> pipenv install --deploy --system<span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"># Copy Python scripts and model files to the working directory</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#66d9ef">COPY</span> <span style="color:#f92672">[</span><span style="color:#e6db74">&#34;*.py&#34;</span>, <span style="color:#e6db74">&#34;model.bin&#34;</span>, <span style="color:#e6db74">&#34;dv.bin&#34;</span>, <span style="color:#e6db74">&#34;./&#34;</span><span style="color:#f92672">]</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"># Expose port 9696 for the web service</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#66d9ef">EXPOSE</span> <span style="color:#e6db74">9696</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"># Define the entry point for the container</span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#66d9ef">ENTRYPOINT</span> [<span style="color:#e6db74">&#34;gunicorn&#34;</span>, <span style="color:#e6db74">&#34;--bind&#34;</span>, <span style="color:#e6db74">&#34;0.0.0.0:9696&#34;</span>, <span style="color:#e6db74">&#34;prediction_service:app&#34;</span>]<span style="color:#960050;background-color:#1e0010">
</span></span></span></code></pre></div><h2 id="conclusion">Conclusion</h2>
<p>We have seen how to export and load a machine learning model and dictionary vectorizer, together with how to build a web service exposing an endpoint for making predictions and how to containerize the web service.</p>
<p>The homework code can be found <a href="https://github.com/vladflore/machine-learning-zoomcamp-cohort-2024/tree/main/05-deployment-hw" target="_blank">here</a>.</p>
]]></content>
        </item>
        
        <item>
            <title>Machine Learning Zoomcamp: Module 4 Recap</title>
            <link>https://vladflore.tech/posts/2024/12/machine-learning-zoomcamp-module-4-recap/</link>
            <pubDate>Wed, 11 Dec 2024 00:00:00 +0000</pubDate>
            
            <guid>https://vladflore.tech/posts/2024/12/machine-learning-zoomcamp-module-4-recap/</guid>
            <description>&lt;h2 id=&#34;intro&#34;&gt;Intro&lt;/h2&gt;
&lt;p&gt;This post is a recap of the Machine Learning Zoomcamp Module 4.&lt;/p&gt;
&lt;p&gt;Below are the posts for the previous modules:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;https://vladflore.tech/posts/2024/09/machine-learning-zoomcamp-module-1-recap/&#34;&gt;Machine Learning Zoomcamp Module 1&lt;/a&gt; - points received: &lt;em&gt;9&lt;/em&gt; (&lt;em&gt;7&lt;/em&gt;/7 for questions + &lt;em&gt;2&lt;/em&gt; bonus for learning in public)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://vladflore.tech/posts/2024/10/machine-learning-zoomcamp-module-2-recap/&#34;&gt;Machine Learning Zoomcamp Module 2&lt;/a&gt; - points received: &lt;em&gt;5&lt;/em&gt; (&lt;em&gt;5&lt;/em&gt;/6 for questions + &lt;em&gt;0&lt;/em&gt; bonus for learning in public)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://vladflore.tech/posts/2024/12/machine-learning-zoomcamp-module-3-recap/&#34;&gt;Machine Learning Zoomcamp Module 3&lt;/a&gt; - points received: &lt;em&gt;7&lt;/em&gt; (&lt;em&gt;6&lt;/em&gt;/6 for questions + &lt;em&gt;1&lt;/em&gt; bonus for learning in public)&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;the-gist-of-the-module&#34;&gt;The gist of the module&lt;/h2&gt;
&lt;p&gt;This module focuses on the evaluation of classification models. It covers various metrics used for this purpose, including &lt;em&gt;accuracy&lt;/em&gt;, &lt;em&gt;precision&lt;/em&gt;, &lt;em&gt;recall&lt;/em&gt;, &lt;em&gt;F1 score&lt;/em&gt;, and &lt;em&gt;ROC-AUC&lt;/em&gt;. The lessons build upon the dataset and model from the previous module, which involves predicting customer churn. The objective is to determine whether a customer is likely to leave or remain, using a logistic regression model.&lt;/p&gt;</description>
            <content type="html"><![CDATA[<h2 id="intro">Intro</h2>
<p>This post is a recap of the Machine Learning Zoomcamp Module 4.</p>
<p>Below are the posts for the previous modules:</p>
<ol>
<li><a href="https://vladflore.tech/posts/2024/09/machine-learning-zoomcamp-module-1-recap/">Machine Learning Zoomcamp Module 1</a> - points received: <em>9</em> (<em>7</em>/7 for questions + <em>2</em> bonus for learning in public)</li>
<li><a href="https://vladflore.tech/posts/2024/10/machine-learning-zoomcamp-module-2-recap/">Machine Learning Zoomcamp Module 2</a> - points received: <em>5</em> (<em>5</em>/6 for questions + <em>0</em> bonus for learning in public)</li>
<li><a href="https://vladflore.tech/posts/2024/12/machine-learning-zoomcamp-module-3-recap/">Machine Learning Zoomcamp Module 3</a> - points received: <em>7</em> (<em>6</em>/6 for questions + <em>1</em> bonus for learning in public)</li>
</ol>
<h2 id="the-gist-of-the-module">The gist of the module</h2>
<p>This module focuses on the evaluation of classification models. It covers various metrics used for this purpose, including <em>accuracy</em>, <em>precision</em>, <em>recall</em>, <em>F1 score</em>, and <em>ROC-AUC</em>. The lessons build upon the dataset and model from the previous module, which involves predicting customer churn. The objective is to determine whether a customer is likely to leave or remain, using a logistic regression model.</p>
<h2 id="accuracy">Accuracy</h2>
<p>Accuracy is a common metric used to evaluate classification models. It measures the proportion of correct predictions made by the model. However, accuracy alone may not provide a complete picture of the model&rsquo;s performance, especially in imbalanced datasets.</p>
<h2 id="confusion-matrix">Confusion matrix</h2>
<p>The <em>confusion matrix</em> is a tabular representation of the model&rsquo;s predictions against the actual values. It consists of four components: <em>true positives</em>, <em>true negatives</em>, <em>false positives</em>, and <em>false negatives</em>. These components are used to calculate other evaluation metrics such as precision, recall, and F1 score.</p>
<p>True positives (TP) are the cases where the model correctly predicts the positive class.
True negatives (TN) are the cases where the model correctly predicts the negative class.
False positives (FP) are the cases where the model incorrectly predicts the positive class.
False negatives (FN) are the cases where the model incorrectly predicts the negative class.</p>
<p>Visually, the confusion matrix looks like this:</p>
<table>
  <thead>
      <tr>
          <th></th>
          <th>Predicted Positive</th>
          <th>Predicted Negative</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Actual Positive</td>
          <td>True Positive (TP)</td>
          <td>False Negative (FN)</td>
      </tr>
      <tr>
          <td>Actual Negative</td>
          <td>False Positive (FP)</td>
          <td>True Negative (TN)</td>
      </tr>
  </tbody>
</table>
<p>Using these components, the accuracy is nothing else than the sum of the true positives and true negatives divided by the total number of observations.</p>
<pre tabindex="0"><code>Accuracy = (TP + TN) / (TP + TN + FP + FN)
</code></pre><h2 id="precision">Precision</h2>
<p><em>Precision</em> measures the proportion of true positive predictions among all positive predictions made by the model. It is calculated as the ratio of true positives to the sum of true positives and false positives.</p>
<pre tabindex="0"><code>Precision = TP / (TP + FP)
</code></pre><h2 id="recall">Recall</h2>
<p><em>Recall</em>, also known as sensitivity or true positive rate, measures the proportion of true positive predictions among all actual positive cases. It is calculated as the ratio of true positives to the sum of true positives and false negatives.</p>
<pre tabindex="0"><code>Recall = TP / (TP + FN)
</code></pre><h2 id="f1-score">F1 score</h2>
<p>The <em>F1 score</em> is the harmonic mean of precision and recall. It provides a balance between the two metrics and is useful when the classes are imbalanced.</p>
<p>An F1 score of 1 indicates a perfect model, while a score of 0 indicates a model that performs no better than random. The relative contribution of precision and recall to the F1 score are equal.</p>
<pre tabindex="0"><code>F1 Score = 2 * (Precision * Recall) / (Precision + Recall)
</code></pre><h2 id="roc-curve">ROC curve</h2>
<p>The <em>Receiver Operating Characteristic (ROC) curve</em> is a graphical representation of the trade-off between the true positive rate (recall), which we want to maximize, and the false positive rate, which we want to minimize, of a classification model. It is used to evaluate the performance of the model across different thresholds.</p>
<p>False positive rate (FPR) is the proportion of false positive predictions among all actual negative cases. It is calculated as the ratio of false positives to the sum of false positives and true negatives.</p>
<p>True positive rate (TPR) is the same as recall.</p>
<p>The ROC curve plots the TPR against the FPR for different threshold values.</p>
<h2 id="area-under-the-roc-curve">Area Under the ROC curve</h2>
<p>The Area Under the ROC Curve (AUC-ROC) is a metric used to evaluate the performance of a binary classification model. It measures the model&rsquo;s ability to distinguish between the two classes (positive and negative) across all possible classification thresholds.</p>
<p>AUC-ROC answers the question, &ldquo;What is the probability that the model will rank a randomly chosen positive instance higher than a randomly chosen negative instance?&rdquo;</p>
<p>The AUC-ROC score ranges from 0 to 1, where a score of 0.5 indicates a model that performs no better than random, and a score of 1 indicates a perfect model.</p>
<h2 id="cross-validation">Cross-validation</h2>
<p><em>Cross-validation</em> is a technique used to evaluate the performance of a machine learning model. It involves splitting the dataset into multiple subsets, training the model on some subsets, and testing it on others. This process is repeated multiple times to obtain a more reliable estimate of the model&rsquo;s performance.</p>
<p>The most common form of cross-validation is k-fold cross-validation, where the dataset is divided into k subsets (folds). The model is trained on k-1 folds and tested on the remaining fold. This process is repeated k times, with each fold serving as the test set once.</p>
<p>This technique is applied in the parameter tuning process to select the best hyperparameters for the model.</p>
<h2 id="conclusion">Conclusion</h2>
<p>This module provides an overview of the evaluation metrics used to assess the performance of classification models. It covers the importance of accuracy, precision, recall, F1-score, ROC-AUC, and the confusion matrix in evaluating the model&rsquo;s performance.</p>
<p>The homework code can be found <a href="https://github.com/vladflore/machine-learning-zoomcamp-cohort-2024/blob/main/04-classification-evaluation-metrics-hw.ipynb" target="_blank">here</a>.</p>
]]></content>
        </item>
        
        <item>
            <title>Machine Learning Zoomcamp: Module 3 Recap</title>
            <link>https://vladflore.tech/posts/2024/12/machine-learning-zoomcamp-module-3-recap/</link>
            <pubDate>Fri, 06 Dec 2024 00:00:00 +0000</pubDate>
            
            <guid>https://vladflore.tech/posts/2024/12/machine-learning-zoomcamp-module-3-recap/</guid>
            <description>&lt;h2 id=&#34;intro&#34;&gt;Intro&lt;/h2&gt;
&lt;p&gt;This post is a recap of the Machine Learning Zoomcamp Module 3.&lt;/p&gt;
&lt;p&gt;Below are the posts for the previous modules:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;https://vladflore.tech/posts/2024/09/machine-learning-zoomcamp-module-1-recap/&#34;&gt;Machine Learning Zoomcamp Module 1&lt;/a&gt; - points received: &lt;em&gt;9&lt;/em&gt; (&lt;em&gt;7&lt;/em&gt;/7 for questions + &lt;em&gt;2&lt;/em&gt; bonus for learning in public)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://vladflore.tech/posts/2024/10/machine-learning-zoomcamp-module-2-recap/&#34;&gt;Machine Learning Zoomcamp Module 2&lt;/a&gt; - points received: &lt;em&gt;5&lt;/em&gt; (&lt;em&gt;5&lt;/em&gt;/6 for questions + &lt;em&gt;0&lt;/em&gt; bonus for learning in public)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For module 2 I managed to score 5 points out of 6 for the questions. While the code and the result I got were correct, I interpreted the result incorrectly, choosing the wrong answer. Oh well, it happens&amp;hellip;&lt;/p&gt;</description>
            <content type="html"><![CDATA[<h2 id="intro">Intro</h2>
<p>This post is a recap of the Machine Learning Zoomcamp Module 3.</p>
<p>Below are the posts for the previous modules:</p>
<ol>
<li><a href="https://vladflore.tech/posts/2024/09/machine-learning-zoomcamp-module-1-recap/">Machine Learning Zoomcamp Module 1</a> - points received: <em>9</em> (<em>7</em>/7 for questions + <em>2</em> bonus for learning in public)</li>
<li><a href="https://vladflore.tech/posts/2024/10/machine-learning-zoomcamp-module-2-recap/">Machine Learning Zoomcamp Module 2</a> - points received: <em>5</em> (<em>5</em>/6 for questions + <em>0</em> bonus for learning in public)</li>
</ol>
<p>For module 2 I managed to score 5 points out of 6 for the questions. While the code and the result I got were correct, I interpreted the result incorrectly, choosing the wrong answer. Oh well, it happens&hellip;</p>
<h2 id="the-gist-of-the-module">The gist of the module</h2>
<p>While the previous module was all about regression, i.e. predicting a continuous value, this module is about classification, i.e. predicting a category. As we have just two categories, we are talking about <em>binary classification</em>.</p>
<h2 id="the-dataset">The dataset</h2>
<p>As with all machine learning problems, we begin with the dataset. In this module, the dataset focuses on predicting customer churn, determining whether a customer is likely to leave or stay. The dataset used for the homework focuses on predicting if a customer has subscribed a term deposit or not.</p>
<h2 id="data-preparation-and-eda">Data preparation and EDA</h2>
<p>One of the first steps in implementing a machine learning model is to prepare the data and perform exploratory data analysis (EDA).</p>
<p>Regarding data preparation, we need to:</p>
<ul>
<li>bring the columns and values within to a common format, i.e. lowercase, no spaces, etc.</li>
<li>perform some numerical conversions</li>
<li>handling missing values</li>
<li>encoding categorical variables, i.e. <code>yes</code>/<code>no</code> to <code>1</code>/<code>0</code></li>
</ul>
<p>Regarding EDA, we need to:</p>
<ul>
<li>check the distribution of the target variable</li>
<li>check the distribution of the features</li>
<li>calculate the correlation between the features</li>
<li>calculate the mutual information between the features and the target variable</li>
</ul>
<h2 id="training-a-model">Training a model</h2>
<p>The next step is to train a model. In this module, we used the logistic regression model. The logistic regression model is a linear model that predicts the probability of an outcome. In our case the outcome is binary.</p>
<p>Before proceeding with the training, we need to split the data into training, validation, and test sets. The training set is used to train the model, the validation set is used to tune the hyperparameters, and the test set is used to evaluate the model.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#f92672">from</span> sklearn.model_selection <span style="color:#f92672">import</span> train_test_split
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>df_train, df_remaining <span style="color:#f92672">=</span> train_test_split(df, test_size<span style="color:#f92672">=</span><span style="color:#ae81ff">0.4</span>, random_state<span style="color:#f92672">=</span><span style="color:#ae81ff">42</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>df_val, df_test <span style="color:#f92672">=</span> train_test_split(df_remaining, test_size<span style="color:#f92672">=</span><span style="color:#ae81ff">0.5</span>, random_state<span style="color:#f92672">=</span><span style="color:#ae81ff">42</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>y_train <span style="color:#f92672">=</span> df_train<span style="color:#f92672">.</span>y<span style="color:#f92672">.</span>values
</span></span><span style="display:flex;"><span>y_val <span style="color:#f92672">=</span> df_val<span style="color:#f92672">.</span>y<span style="color:#f92672">.</span>values
</span></span><span style="display:flex;"><span>y_test <span style="color:#f92672">=</span> df_test<span style="color:#f92672">.</span>y<span style="color:#f92672">.</span>values
</span></span></code></pre></div><h3 id="performing-one-hot-encoding">Performing one-hot encoding</h3>
<p>Before training the model, we need to perform one-hot encoding on the categorical variables. One-hot encoding is a process of converting categorical variables into a form that could be provided to ML algorithms to do a better job in prediction. Below we use the homework dataset to perform one-hot encoding.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#f92672">from</span> sklearn.feature_extraction <span style="color:#f92672">import</span> DictVectorizer
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>numerical_features <span style="color:#f92672">=</span> [<span style="color:#e6db74">&#39;balance&#39;</span>, <span style="color:#e6db74">&#39;previous&#39;</span>, <span style="color:#e6db74">&#39;pdays&#39;</span>, <span style="color:#e6db74">&#39;campaign&#39;</span>, <span style="color:#e6db74">&#39;age&#39;</span>, <span style="color:#e6db74">&#39;day&#39;</span>, <span style="color:#e6db74">&#39;duration&#39;</span>]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>categorical_features <span style="color:#f92672">=</span> [<span style="color:#e6db74">&#39;education&#39;</span>, <span style="color:#e6db74">&#39;housing&#39;</span>, <span style="color:#e6db74">&#39;month&#39;</span>, <span style="color:#e6db74">&#39;contact&#39;</span>, <span style="color:#e6db74">&#39;marital&#39;</span>, <span style="color:#e6db74">&#39;poutcome&#39;</span>, <span style="color:#e6db74">&#39;job&#39;</span>]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>dict_train <span style="color:#f92672">=</span> df_train[numerical_features<span style="color:#f92672">+</span>categorical_features]<span style="color:#f92672">.</span>to_dict(orient<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;records&#39;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>dv <span style="color:#f92672">=</span> DictVectorizer(sparse<span style="color:#f92672">=</span><span style="color:#66d9ef">False</span>)
</span></span><span style="display:flex;"><span>X_train <span style="color:#f92672">=</span> dv<span style="color:#f92672">.</span>fit_transform(dict_train)
</span></span></code></pre></div><p>After the one-hot encoding the feature names are stored in the <code>dv.get_feature_names_out()</code> method, and look like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>[
</span></span><span style="display:flex;"><span>  <span style="color:#e6db74">&#39;age&#39;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#e6db74">&#39;balance&#39;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#e6db74">&#39;campaign&#39;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#e6db74">&#39;contact=cellular&#39;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#e6db74">&#39;contact=telephone&#39;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#e6db74">&#39;contact=unknown&#39;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#e6db74">&#39;day&#39;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#e6db74">&#39;duration&#39;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#e6db74">&#39;education=primary&#39;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#e6db74">&#39;education=secondary&#39;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#e6db74">&#39;education=tertiary&#39;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#e6db74">&#39;education=unknown&#39;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#e6db74">&#39;housing=no&#39;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">...</span>
</span></span><span style="display:flex;"><span>  <span style="color:#e6db74">&#39;housing=yes&#39;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#e6db74">&#39;poutcome=failure&#39;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#e6db74">&#39;poutcome=other&#39;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#e6db74">&#39;poutcome=success&#39;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#e6db74">&#39;poutcome=unknown&#39;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#e6db74">&#39;previous&#39;</span>
</span></span><span style="display:flex;"><span>]
</span></span></code></pre></div><h3 id="training-a-logistic-regression-model">Training a logistic regression model</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#f92672">from</span> sklearn.linear_model <span style="color:#f92672">import</span> LogisticRegression
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>model <span style="color:#f92672">=</span> LogisticRegression(solver<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;liblinear&#39;</span>, C<span style="color:#f92672">=</span><span style="color:#ae81ff">1.0</span>, max_iter<span style="color:#f92672">=</span><span style="color:#ae81ff">1000</span>, random_state<span style="color:#f92672">=</span><span style="color:#ae81ff">42</span>)
</span></span><span style="display:flex;"><span>model<span style="color:#f92672">.</span>fit(X_train, y_train)
</span></span></code></pre></div><p>The model is trained using the training set and the target variable. The <code>solver</code> parameter is set to <code>liblinear</code>, which is a good choice for small datasets. The <code>C</code> parameter is set to <code>1.0</code>, which is the default value. The <code>max_iter</code> parameter is set to <code>1000</code>, which is the maximum number of iterations taken for the solvers to converge. The <code>random_state</code> parameter is set to <code>42</code> to ensure reproducibility.</p>
<h2 id="making-predictions">Making predictions</h2>
<p>After training the model, we can make predictions using the validation set.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>dict_val <span style="color:#f92672">=</span> df_val<span style="color:#f92672">.</span>to_dict(orient<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;records&#39;</span>)
</span></span><span style="display:flex;"><span>dv <span style="color:#f92672">=</span> DictVectorizer(sparse<span style="color:#f92672">=</span><span style="color:#66d9ef">False</span>)
</span></span><span style="display:flex;"><span>X_val <span style="color:#f92672">=</span> dv<span style="color:#f92672">.</span>fit_transform(dict_val)
</span></span><span style="display:flex;"><span>y_pred <span style="color:#f92672">=</span> model<span style="color:#f92672">.</span>predict_proba(X_val)[:, <span style="color:#ae81ff">1</span>]
</span></span></code></pre></div><p>One last step is to make a decission based on the predictions. In this case, we use a threshold of <code>0.5</code> to determine if a customer has subscribed a term deposit or not.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>y_decission <span style="color:#f92672">=</span> y_pred <span style="color:#f92672">&gt;=</span> <span style="color:#ae81ff">0.5</span>
</span></span></code></pre></div><p>After this step, we can calculate the accuracy of the model.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>(y_val <span style="color:#f92672">==</span> y_decission)<span style="color:#f92672">.</span>mean()
</span></span></code></pre></div><p>We can do one final check by calculating the accuracy of the model using the test set.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>dict_test <span style="color:#f92672">=</span> df_test<span style="color:#f92672">.</span>to_dict(orient<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;records&#39;</span>)
</span></span><span style="display:flex;"><span>X_test <span style="color:#f92672">=</span> dv<span style="color:#f92672">.</span>fit_transform(dict_test)
</span></span><span style="display:flex;"><span>y_pred <span style="color:#f92672">=</span> model<span style="color:#f92672">.</span>predict_proba(X_test)[:, <span style="color:#ae81ff">1</span>]
</span></span><span style="display:flex;"><span>y_decission <span style="color:#f92672">=</span> y_pred <span style="color:#f92672">&gt;=</span> <span style="color:#ae81ff">0.5</span>
</span></span><span style="display:flex;"><span>(y_test <span style="color:#f92672">==</span> y_decission)<span style="color:#f92672">.</span>mean()
</span></span></code></pre></div><h2 id="conclusion">Conclusion</h2>
<p>This module was a great introduction to binary classification. We learned how to prepare the data, perform EDA, train a model, and make predictions. We also learned how to evaluate the model using the accuracy metric.</p>
<p>The homework code can be found <a href="https://github.com/vladflore/machine-learning-zoomcamp-cohort-2024/blob/main/03-classification-hw.ipynb" target="_blank">here</a>.</p>
]]></content>
        </item>
        
        <item>
            <title>Machine Learning Zoomcamp: Module 2 Recap</title>
            <link>https://vladflore.tech/posts/2024/10/machine-learning-zoomcamp-module-2-recap/</link>
            <pubDate>Mon, 14 Oct 2024 00:00:00 +0000</pubDate>
            
            <guid>https://vladflore.tech/posts/2024/10/machine-learning-zoomcamp-module-2-recap/</guid>
            <description>&lt;h2 id=&#34;intro&#34;&gt;Intro&lt;/h2&gt;
&lt;p&gt;In this post I will make a recap of the Machine Learning Zoomcamp Module 2.&lt;/p&gt;
&lt;p&gt;The posts for the previous modules, together with the points I received for each module&amp;rsquo;s homework, are listed below:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;https://vladflore.tech/posts/2024/09/machine-learning-zoomcamp-module-1-recap/&#34;&gt;Machine Learning Zoomcamp Module 1&lt;/a&gt; - points received: &lt;em&gt;9&lt;/em&gt; (&lt;em&gt;7&lt;/em&gt;/7 for questions + &lt;em&gt;2&lt;/em&gt; bonus for learning in public)&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;the-gist-of-the-module&#34;&gt;The gist of the module&lt;/h2&gt;
&lt;p&gt;The problem tackled in this module was the prediction of car prices based on a dataset containing car features.&lt;/p&gt;</description>
            <content type="html"><![CDATA[<h2 id="intro">Intro</h2>
<p>In this post I will make a recap of the Machine Learning Zoomcamp Module 2.</p>
<p>The posts for the previous modules, together with the points I received for each module&rsquo;s homework, are listed below:</p>
<ol>
<li><a href="https://vladflore.tech/posts/2024/09/machine-learning-zoomcamp-module-1-recap/">Machine Learning Zoomcamp Module 1</a> - points received: <em>9</em> (<em>7</em>/7 for questions + <em>2</em> bonus for learning in public)</li>
</ol>
<h2 id="the-gist-of-the-module">The gist of the module</h2>
<p>The problem tackled in this module was the prediction of car prices based on a dataset containing car features.</p>
<p>This type of problem is called a regression problem, and the main idea is to try to predict a <em>continuous value</em>, in this case, the price of a car, based on a set of car features, using a Machine Learning model. For this problem, the model used was the <em>Linear Regression</em> model.</p>
<p>To get a real taste of how such a problem could be solved, the model was implemented from scratch using Python and NumPy, while the dataset was explored and manipulated using Pandas and Matplotlib.</p>
<h2 id="the-dataset">The dataset</h2>
<p>As with all things in Machine Learning, the first step is to get the data and make a sense of it.</p>
<p>The dataset used in this module was the <a href="https://www.kaggle.com/datasets/CooperUnion/cardataset" target="_blank">Car Features and MSRP</a> from Kaggle.</p>
<p>Note that I will be using <a href="https://raw.githubusercontent.com/alexeygrigorev/datasets/master/laptops.csv" target="_blank">another dataset</a>, the one from the homework, to illustrate the concepts discussed in this post. While the datasets are different, the process is the same.</p>
<p>As it is often the case, the dataset may require some cleaning and preprocessing before it could be used to train a model. One such action was normalizing the column names. To get rid of inconsistencies, all columns were converted to lowercase, and the spaces were replaced with underscores.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>url <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;https://raw.githubusercontent.com/alexeygrigorev/datasets/master/laptops.csv&#39;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>df <span style="color:#f92672">=</span> pd<span style="color:#f92672">.</span>read_csv(url)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>cols <span style="color:#f92672">=</span> df<span style="color:#f92672">.</span>columns<span style="color:#f92672">.</span>str<span style="color:#f92672">.</span>lower()<span style="color:#f92672">.</span>str<span style="color:#f92672">.</span>replace(<span style="color:#e6db74">r</span><span style="color:#e6db74">&#39;\s+&#39;</span>,<span style="color:#e6db74">&#39;_&#39;</span>, regex<span style="color:#f92672">=</span><span style="color:#66d9ef">True</span>)
</span></span><span style="display:flex;"><span>df<span style="color:#f92672">.</span>columns <span style="color:#f92672">=</span> cols
</span></span></code></pre></div><p>A similar conversion process can be applied to the values in the columns, to make sure that the data is consistent and easy to work with.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>string_columns <span style="color:#f92672">=</span> list(df<span style="color:#f92672">.</span>dtypes[df<span style="color:#f92672">.</span>dtypes <span style="color:#f92672">==</span> <span style="color:#e6db74">&#39;object&#39;</span>]<span style="color:#f92672">.</span>index)
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> col <span style="color:#f92672">in</span> string_columns:
</span></span><span style="display:flex;"><span>    df[col] <span style="color:#f92672">=</span> df[col]<span style="color:#f92672">.</span>str<span style="color:#f92672">.</span>lower()<span style="color:#f92672">.</span>str<span style="color:#f92672">.</span>replace(<span style="color:#e6db74">r</span><span style="color:#e6db74">&#39;\s+&#39;</span>,<span style="color:#e6db74">&#39;_&#39;</span>, regex<span style="color:#f92672">=</span><span style="color:#66d9ef">True</span>)
</span></span></code></pre></div><p>Another common preprocessing step is to handle missing values. For instance, if a column contains missing values, one could replace them with the mean of the column.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>df<span style="color:#f92672">.</span>screen <span style="color:#f92672">=</span> df<span style="color:#f92672">.</span>screen<span style="color:#f92672">.</span>fillna(df<span style="color:#f92672">.</span>screen<span style="color:#f92672">.</span>mean())
</span></span></code></pre></div><p>Looking at the target variable, i.e. the variable we want to predict, is also important. In this case, the target variable is the price of the car. It is a good idea to check the distribution of the target variable, as it can give us some insights into the data. One way to do this is to plot a histogram of the target variable, using a library like Seaborn.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#f92672">import</span> seaborn <span style="color:#66d9ef">as</span> sns
</span></span><span style="display:flex;"><span>fp <span style="color:#f92672">=</span> df<span style="color:#f92672">.</span>final_price
</span></span><span style="display:flex;"><span>sns<span style="color:#f92672">.</span>histplot(fp, bins<span style="color:#f92672">=</span><span style="color:#ae81ff">50</span>)
</span></span></code></pre></div><p>One imediate observation could be that the data is not normally distributed. This could be a problem, as the Linear Regression model works better with normally distributed data. One way to address this issue is to apply a transformation to the target variable. One such transformation is the logarithmic transformation.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>fp <span style="color:#f92672">=</span> np<span style="color:#f92672">.</span>log1p(df<span style="color:#f92672">.</span>final_price)
</span></span></code></pre></div><p>Plotting the histogram of the transformed target variable could show a more normally distributed data.</p>
<p>Before training the model, we have to split the data into <em>training</em>, <em>validation</em> and <em>testing</em> sets. The training set is used to train the model, the validation set is used to tune the hyperparameters of the model, and the testing set is used to evaluate the model&rsquo;s performance. A common split is 60% for training, 20% for validation, and 20% for testing.</p>
<p>Without relying on libraries like Scikit-Learn, we can split the data by shuffling the indices of the dataset and then splitting the indices into the three sets.</p>
<h2 id="training-the-model">Training the model</h2>
<p>Training the model refers to the process by which an algorithm learns the relationship between the input features and the target variable. In this case, the algorithm used was the Linear Regression model. The artifacts of the training process are the <em>weights</em> and the <em>bias</em> of the model.</p>
<p>Linear Regression is a simple model that tries to <em>find the best line that fits the data</em>. The line is defined by the equation <code>y = w1*x1 + w2*x2 + ... + wn*xn + b</code>, where <code>w1, w2, ..., wn</code> are the weights, <code>x1, x2, ..., xn</code> are the input features, and <code>b</code> is the bias. In the module bias was named <code>w0</code>. It is also called the <em>intercept</em>, which is the value of the target variable when all the input features are zero, i.e. the value of the target variable when there is no influence from the input features.</p>
<p>For a single feature, x, and its weight, w, the equation becomes <code>y = w*x + b</code>. This is nothing else than the equation of a line, where <code>w</code> is the slope of the line, and <code>b</code> is the y-intercept. The intercept is where the line crosses the y-axis, and the slope is the rate at which the line rises or falls, or mathematically, the change in y divided by the change in x.</p>
<p>Considering we have many observations, we can arrange the input features in a matrix, X, and the target variable in a vector, y. The equation of the model becomes <code>y = X*w + b</code>, where <code>X</code> is a matrix of shape <code>(n_samples, n_features)</code>, <code>w</code> is a vector of shape <code>(n_features, 1)</code>, and <code>b</code> is a scalar.</p>
<p>Now we are talking about matrix-vector multiplication, which means we can think at <code>b</code> as a vector of ones, and add it as a column to the matrix <code>X</code>. This way, the equation becomes <code>y = X*w</code>, where <code>X</code> is a matrix of shape <code>(n_samples, n_features + 1)</code>, <code>w</code> is a vector of shape <code>(n_features + 1, 1)</code>, and <code>y</code> is a vector of shape <code>(n_samples, 1)</code>.</p>
<p>If the matrix <code>X</code> is invertible (i.e. it is a square matrix and its determinant is not zero), we can find the weights, <code>w</code>, by multiplying the inverse of <code>X</code> with <code>y</code>.</p>
<p>If matrix <code>X</code> is not invertible, we have to make use of the transpose of <code>X</code>, <code>X^T</code>, which multiplied with <code>X</code> gives a square matrix, <code>X^T*X</code>, also called the <a href="https://en.wikipedia.org/wiki/Gram_matrix" target="_blank">Gram matrix</a>, which <em>could</em> be invertible. If this is the case, the weights can be found as <code>w = (X^T*X)^-1*X^T*y</code>, where <code>^-1</code> is the matrix inverse.</p>
<p>If the Gram matrix is not invertible, we need to talk about regularization, a bit later on in this post.</p>
<h3 id="feature-engineering">Feature engineering</h3>
<p>In order to improve the model performance, we can engineer the features. This means that we can create new features from the existing ones, or transform the existing features in a way that makes them more informative. This basically means that the feature matrix, <code>X</code>, can contain more columns than the original dataset.</p>
<p>For example, if one of the features is the <em>status</em> of a laptop, i.e. weather it is <em>new</em> or <em>refurbished</em>, we can add two new columns to the feature matrix, one for each status, let&rsquo;s say, <code>is_new</code> and <code>is_refurbished</code>. If the laptop is new, the value of <code>is_new</code> is 1, and the value of <code>is_refurbished</code> is 0. If the laptop is refurbished, the value of <code>is_new</code> is 0, and the value of <code>is_refurbished</code> is 1.</p>
<h3 id="regularization">Regularization</h3>
<p>We saw that the Gram matrix may not be invertible. This happens when the matrix is <em>singular</em>, i.e. it has a determinant of zero. This could happen when the number of features is not the same as the number of observations, or when the features are <em>collinear</em>, i.e. they are linearly dependent. Collinearity just means that one or more columns in the feature matrix can be expressed as a linear combination of the other columns. For instance, if we have two columns, <code>x1</code> and <code>x2</code>, and <code>x2 = 2*x1</code>, then the two columns are collinear.</p>
<p>One way to address this issue is to add a factor to the diagonal of the Gram matrix, called the <em>regularization term</em>. This term is a scalar, <code>r</code>, multiplied with the identity matrix, <code>I</code>, and added to the Gram matrix. The equation becomes <code>w = (X^T*X + r*I)^-1*X^T*y</code>.</p>
<p>This equation can be nicely expressed in Python code:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">train_linear_regression_reg</span>(X, y, r<span style="color:#f92672">=</span><span style="color:#ae81ff">0.0</span>):
</span></span><span style="display:flex;"><span>  ones <span style="color:#f92672">=</span> np<span style="color:#f92672">.</span>ones(X<span style="color:#f92672">.</span>shape[<span style="color:#ae81ff">0</span>]) <span style="color:#75715e"># create a vector of ones</span>
</span></span><span style="display:flex;"><span>  X <span style="color:#f92672">=</span> np<span style="color:#f92672">.</span>column_stack([ones, X]) <span style="color:#75715e"># add the vector of ones as a column to the matrix X</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  XTX <span style="color:#f92672">=</span> X<span style="color:#f92672">.</span>T<span style="color:#f92672">.</span>dot(X) <span style="color:#75715e"># calculate the Gram matrix</span>
</span></span><span style="display:flex;"><span>  reg <span style="color:#f92672">=</span> r <span style="color:#f92672">*</span> np<span style="color:#f92672">.</span>eye(XTX<span style="color:#f92672">.</span>shape[<span style="color:#ae81ff">0</span>]) <span style="color:#75715e"># create the regularization term</span>
</span></span><span style="display:flex;"><span>  XTX <span style="color:#f92672">=</span> XTX <span style="color:#f92672">+</span> reg <span style="color:#75715e"># add the regularization term to the Gram matrix</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  XTX_inv <span style="color:#f92672">=</span> np<span style="color:#f92672">.</span>linalg<span style="color:#f92672">.</span>inv(XTX) <span style="color:#75715e"># calculate the inverse of the Gram matrix</span>
</span></span><span style="display:flex;"><span>  w <span style="color:#f92672">=</span> XTX_inv<span style="color:#f92672">.</span>dot(X<span style="color:#f92672">.</span>T)<span style="color:#f92672">.</span>dot(y) <span style="color:#75715e"># calculate the weights</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> w[<span style="color:#ae81ff">0</span>], w[<span style="color:#ae81ff">1</span>:] <span style="color:#75715e"># return the bias and the weights</span>
</span></span></code></pre></div><h2 id="model-evaluation">Model evaluation</h2>
<p>Once we have our model trained, i.e. we know the weights and the bias, we can evaluate its performance. One way to do this is to calculate the root mean squared error (RMSE) of the model. The RMSE is a measure of the difference between the predicted values and the actual values. The lower the RMSE, the better the model.</p>
<p>The RMSE is calculated as the square root of the mean of the squared differences between the predicted values and the actual values. The equation is <code>RMSE = sqrt(mean((y_pred - y)^2))</code>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">rmse</span>(y, y_pred):
</span></span><span style="display:flex;"><span>  se <span style="color:#f92672">=</span> (y <span style="color:#f92672">-</span> y_pred) <span style="color:#f92672">**</span> <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>  mse <span style="color:#f92672">=</span> se<span style="color:#f92672">.</span>mean()
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> np<span style="color:#f92672">.</span>sqrt(mse)
</span></span></code></pre></div><p>We can do this for the validation set and the testing set, and compare the RMSE values. If the RMSE of the testing set is much higher than the RMSE of the validation set, it could be a sign of overfitting, i.e. the model is too complex and it is fitting the noise in the data, rather than the underlying pattern.</p>
<p>Once we have a fairly good model, we can use it to make predictions on new data.</p>
<h2 id="using-the-model">Using the model</h2>
<p>Using the model just means to apply the weights and the bias to the new data. The equation is the same as the one used to train the model, <code>y = X*w + b</code>, where <code>X</code> is the feature matrix of the new data, <code>w</code> is the weights of the model, and <code>b</code> is the bias.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">predict</span>(X, w, b):
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> X<span style="color:#f92672">.</span>dot(w) <span style="color:#f92672">+</span> b
</span></span></code></pre></div><h2 id="conclusion">Conclusion</h2>
<p>In this module, we learned how to train a Linear Regression model from scratch, using Python and NumPy. We also learned how to preprocess the data, engineer the features, and evaluate the model. We also learned about regularization and how to address the issue of collinearity.</p>
<p>The homework code can be found <a href="https://github.com/vladflore/machine-learning-zoomcamp-cohort-2024/blob/main/02-regression-hw.ipynb" target="_blank">here</a>.</p>
]]></content>
        </item>
        
        <item>
            <title>Machine Learning Zoomcamp: Module 1 Recap</title>
            <link>https://vladflore.tech/posts/2024/09/machine-learning-zoomcamp-module-1-recap/</link>
            <pubDate>Wed, 25 Sep 2024 00:00:00 +0000</pubDate>
            
            <guid>https://vladflore.tech/posts/2024/09/machine-learning-zoomcamp-module-1-recap/</guid>
            <description>&lt;h2 id=&#34;intro&#34;&gt;Intro&lt;/h2&gt;
&lt;p&gt;In &lt;a href=&#34;https://vladflore.tech/posts/2024/09/learning...-machine-learning/&#34;&gt;one of my previous posts&lt;/a&gt;, I mentioned that I was taking the &lt;a href=&#34;https://datatalks.club/blog/guide-to-free-online-courses-at-datatalks-club.html#machine-learning-zoomcamp&#34; target=&#34;_blank&#34;&gt;Machine Learning Zoomcamp&lt;/a&gt; course. I have completed the first module of the course, and I wanted to share a recap of what I learned. In addition to that, I&amp;rsquo;d go one step further and add some extra bits of information here and there.&lt;/p&gt;
&lt;h2 id=&#34;what-is-machine-learning&#34;&gt;What is Machine Learning?&lt;/h2&gt;
&lt;p&gt;To answer this, we need to understand what &lt;em&gt;learning&lt;/em&gt; is. Learning is the process of acquiring knowledge or skills through experience, study, or being taught. A simple Google search would give you this definition. &lt;a href=&#34;https://en.wikipedia.org/wiki/Learning&#34; target=&#34;_blank&#34;&gt;Wikipedia&lt;/a&gt; defines &lt;em&gt;learning&lt;/em&gt; similarly, adding that &amp;ldquo;[&amp;hellip;]the ability to learn is possessed by humans, non-human animals, and &lt;em&gt;some machines&lt;/em&gt;[&amp;hellip;]&amp;rdquo;. When learning is done by machines, we refer to it as &lt;em&gt;Machine Learning&lt;/em&gt; (ML). In simple terms, ML is the process of teaching a computer to learn from &lt;em&gt;data&lt;/em&gt;. The computer uses the data to identify patterns and make decisions without being explicitly programmed to do so.&lt;/p&gt;</description>
            <content type="html"><![CDATA[<h2 id="intro">Intro</h2>
<p>In <a href="https://vladflore.tech/posts/2024/09/learning...-machine-learning/">one of my previous posts</a>, I mentioned that I was taking the <a href="https://datatalks.club/blog/guide-to-free-online-courses-at-datatalks-club.html#machine-learning-zoomcamp" target="_blank">Machine Learning Zoomcamp</a> course. I have completed the first module of the course, and I wanted to share a recap of what I learned. In addition to that, I&rsquo;d go one step further and add some extra bits of information here and there.</p>
<h2 id="what-is-machine-learning">What is Machine Learning?</h2>
<p>To answer this, we need to understand what <em>learning</em> is. Learning is the process of acquiring knowledge or skills through experience, study, or being taught. A simple Google search would give you this definition. <a href="https://en.wikipedia.org/wiki/Learning" target="_blank">Wikipedia</a> defines <em>learning</em> similarly, adding that &ldquo;[&hellip;]the ability to learn is possessed by humans, non-human animals, and <em>some machines</em>[&hellip;]&rdquo;. When learning is done by machines, we refer to it as <em>Machine Learning</em> (ML). In simple terms, ML is the process of teaching a computer to learn from <em>data</em>. The computer uses the data to identify patterns and make decisions without being explicitly programmed to do so.</p>
<h2 id="why-do-we-need-ml">Why do we need ML?</h2>
<p>Why would we want a machine to learn? Why is a rule-based system not enough?</p>
<p>The answer is two-fold. First, we cannot anticipate all possible future situations. Think of a robot navigating a maze, for instance. Second, we sometimes just don&rsquo;t know how to implement the solution. For example, consider the task of recognizing handwritten digits. Without ML algorithms, this would be a very challenging task to implement.</p>
<p>Recognizing people&rsquo;s faces in images is another good example, we as humans can do this task effortlessly, but writing a computer program to do the same is not trivial without ML.</p>
<p>A rule-based system would require humans to write down all the rules for the computer to follow, whereas with ML, the computer can learn the rules from the data. Let&rsquo;s consider two other examples, spam detection and car price prediction. Applying a rule-based system to these tasks would be very difficult. In the case of spam detection, the rules would be constantly changing as spammers come up with new ways to bypass the system. In the case of car price prediction, there are so many factors that can affect the price of a car that it would be impossible to write down all the rules. With ML, the computer can learn the rules from the data and make predictions based on that.</p>
<h2 id="how-does-ml-work">How does ML work?</h2>
<p>To put it simply, ML works by <em>learning from examples</em>. The computer is given a set of examples, and it uses these examples to build a <em>model</em>, which is then used to make <em>predictions</em> on new data. The set of examples is called the <em>training data</em>, and the process of building the model is called <em>training</em>. The model is a mathematical representation of the patterns in the data.</p>
<h2 id="types-of-ml">Types of ML</h2>
<p>There are three main types of ML: <em>supervised learning</em>, <em>unsupervised learning</em>, and <em>reinforcement learning</em>.</p>
<p>This post will touch upon <em>supervised learning</em>, while the other two types will be covered in future posts.</p>
<h3 id="supervised-ml-sml">Supervised ML (SML)</h3>
<p>In supervised learning, the computer observes input-output pairs and learns a function that maps new inputs to outputs. The input is called the <em>feature</em>, while the output is called the <em>label</em>.</p>
<p>For example, if we are trying to predict the price of a house based on its size, the size of the house would be the input or the feature, and the price would be the output or the label. Of course, we would need a lot more features than just the size of the house to make an accurate prediction.</p>
<p>We put all the features together in a <em>feature matrix</em>, usually called <code>X</code>, where each <em>row</em> represents a different example, and each <em>column</em> represents a different feature.
The labels are put in a <em>target vector</em>, usually called <code>y</code>, for each example in the feature matrix, there is a corresponding label in the target vector.
The model is then a function that takes <code>X</code> as input and tries to predict values as close as possible to <code>y</code>. Formally, we can write this as <code>f(X) ≈ y</code>.</p>
<p>If matrix, vector, or function are not familiar terms to you, this is where maths comes in, but to keep things simple, you can think of a matrix as a table, a vector as a list of numbers, and a function as a rule that takes an input and gives an output.</p>
<p>Let&rsquo;s see some types of supervised learning problems:</p>
<ul>
<li>Regression: The output is a <em>continuous</em> value (the price of a house)</li>
<li>Classification: The output is a <em>discrete</em> value (spam or not spam / ham)</li>
<li>Ranking: The output is a ranking of items (ranking search results)</li>
</ul>
<h2 id="its-all-about-the-data">It&rsquo;s all about the data</h2>
<p>In ML, data is everything. The quality of the data is crucial to the success of the model. If the data is bad, the model will be bad. If the data is good, the model will be good, given no other errors have been made along the way.</p>
<p>You might ask, is there a process to follow when working with data? The answer is yes, there is a process called the <em><a href="https://en.wikipedia.org/wiki/Cross-industry_standard_process_for_data_mining" target="_blank">CRISP-DM</a></em> process, which stands for <em>Cross-Industry Standard Process for Data Mining</em>. The process consists of six phases:</p>
<ul>
<li>Business Understanding, i.e. understanding the problem you are trying to solve</li>
<li>Data Understanding, i.e. understanding the data you have</li>
<li>Data Preparation, i.e. preparing the data for modeling</li>
<li>Modeling, i.e. building the model</li>
<li>Evaluation, i.e. evaluating the model</li>
<li>Deployment, i.e. deploying the model</li>
</ul>
<p>The process is iterative, meaning that you might have to go back and forth between the phases until you get the desired results.</p>
<p>Fortunately, there are tools and libraries that can help you with each phase of the process. Following posts will cover some of these tools and libraries.</p>
<h2 id="choosing-a-model">Choosing a model</h2>
<p>There are many types of models used in machine learning, each suitable for different tasks like classification, regression, clustering, and more. Here are some commonly used machine learning models:</p>
<ul>
<li>Linear Regression</li>
<li>Logistic Regression</li>
<li>Decision Trees</li>
<li>Random Forests</li>
<li>Support Vector Machines</li>
<li>Neural Networks</li>
<li>Convolutional Neural Networks</li>
<li>Recurrent Neural Networks</li>
<li>K-Nearest Neighbors</li>
<li>K-Means Clustering</li>
<li>Principal Component Analysis</li>
<li>Gradient Boosting</li>
<li>Naive Bayes</li>
<li>etc.</li>
</ul>
<p>Considering the vast number of models available, how do you choose the right one for your task? The answer is, it depends. It depends on the problem you are trying to solve, the data you have, and the resources you have available. In general, it is a good idea to start with a simple model and then move on to more complex models if needed.</p>
<p>One way to choose a model is to try different models and see which one performs best on your data. This process is called <em>model selection</em>.</p>
<p>For this we need to divide our data into multiple sets.</p>
<p>One approach is to devide it into <em>two sets</em>: the <em>training set</em> and the <em>test set</em>. The training set is used to train the model, while the test set is used to evaluate the model.</p>
<p>Another approach is to divide the data into <em>three sets</em>: the <em>training set</em>, the <em>validation set</em>, and the <em>test set</em>.</p>
<p>The <em>training set</em> is used to train the model, the <em>validation set</em> is used to evaluate the model, this might imply additional <em>tweaking of the model</em>, and the <em>test set</em> is used to evaluate the final model. The training-evaluation-tweaking process is repeated and the best model is chosen based on the performance on the validation set. This model is then evaluated on the test set.</p>
<h2 id="tools-and-libraries">Tools and Libraries</h2>
<p>Previously I mentioned that there are tools and libraries that can help you with each phase of the CRISP-DM process. Two of the most commonly used libraries in Python are <em>NumPy</em> and <em>Pandas</em>. Pandas is used for data manipulation and analysis, while NumPy is used for numerical computing.</p>
<p>See <a href="">NumPy</a> and <a href="https://vladflore.tech/posts/2024/09/pandas/">Pandas</a> for more information.</p>
<p>To make use of these tools one has to set up their Python environment. One way to do this is to use <a href="https://www.anaconda.com/download" target="_blank">Anaconda</a>, which is a distribution of Python that comes with all the tools and libraries you need for data science and machine learning. Once you have Anaconda installed, you can optionally create a virtual environment, activate it, install the libraries you need, and start working on your project.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>conda create -n myenvironment python<span style="color:#f92672">=</span>3.11
</span></span><span style="display:flex;"><span>conda activate myenvironment
</span></span><span style="display:flex;"><span>conda install numpy pandas scikit-learn seaborn jupyter
</span></span></code></pre></div><p>If running all this locally is not possible for you, you can use <a href="https://colab.research.google.com/" target="_blank">Google Colab</a>, which is a free cloud-based service that allows you to run Python code in the browser, or even set up everything yourself using some cloud service like AWS, Azure, or GCP.</p>
<h2 id="conclusion">Conclusion</h2>
<p>In this post, I covered the basics of machine learning, the types of machine learning, the importance of data, the CRISP-DM process, choosing a model, and some tools and libraries that can help you with machine learning.</p>
]]></content>
        </item>
        
        <item>
            <title>Pandas</title>
            <link>https://vladflore.tech/posts/2024/09/pandas/</link>
            <pubDate>Wed, 25 Sep 2024 00:00:00 +0000</pubDate>
            
            <guid>https://vladflore.tech/posts/2024/09/pandas/</guid>
            <description>&lt;h2 id=&#34;intro&#34;&gt;Intro&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://pandas.pydata.org/&#34; target=&#34;_blank&#34;&gt;Pandas&lt;/a&gt; is a fast, powerful, flexible and easy to use open source data analysis and manipulation tool, built on top of the Python programming language. It was created by Wes McKinney in 2008.&lt;/p&gt;
&lt;p&gt;The name has nothing to do with the cute animal, it&amp;rsquo;s derived from the term &amp;ldquo;panel data&amp;rdquo;, an econometrics term for data sets that include observations over multiple time periods for the same individuals. It is also a play on the phrase &amp;ldquo;Python data analysis&amp;rdquo;.&lt;/p&gt;</description>
            <content type="html"><![CDATA[<h2 id="intro">Intro</h2>
<p><a href="https://pandas.pydata.org/" target="_blank">Pandas</a> is a fast, powerful, flexible and easy to use open source data analysis and manipulation tool, built on top of the Python programming language. It was created by Wes McKinney in 2008.</p>
<p>The name has nothing to do with the cute animal, it&rsquo;s derived from the term &ldquo;panel data&rdquo;, an econometrics term for data sets that include observations over multiple time periods for the same individuals. It is also a play on the phrase &ldquo;Python data analysis&rdquo;.</p>
<p>A good resource to learn more about Pandas is the book &ldquo;Python for Data Analysis&rdquo; by Wes McKinney.</p>
<h2 id="the-environment">The environment</h2>
<p>Make sure you can run the following commands in your terminal, without errors:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>python3.12 --version
</span></span><span style="display:flex;"><span>Python 3.12.4
</span></span></code></pre></div><p>Inside the Python&rsquo;s REPL (Read-Eval-Print Loop), you get inside by typing <code>python3.12</code> in the terminal:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#f92672">import</span> numpy <span style="color:#66d9ef">as</span> np
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> pandas <span style="color:#66d9ef">as</span> pd
</span></span><span style="display:flex;"><span>print(np<span style="color:#f92672">.</span>__version__)
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1.26.4</span>
</span></span><span style="display:flex;"><span>print(pd<span style="color:#f92672">.</span>__version__)
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2.2.2</span>
</span></span></code></pre></div><p>If you get similar results, you are ready to go.</p>
<h2 id="data-structures">Data Structures</h2>
<p>The main data structures in Pandas are the <code>Series</code> and <code>DataFrame</code> objects.</p>
<p>The <code>Series</code> object is a one-dimensional array-like object containing a sequence of values of the same type and an associated array of data labels, called its index.</p>
<p>The <code>DataFrame</code> object is a two-dimensional array with both row and column indices. The name comes from the R <code>data.frame</code> object.</p>
<h2 id="operations-on-series">Operations on Series</h2>
<p>Below are some examples of using the <code>Series</code> object.</p>
<h3 id="create-a-series-with-a-default-index">Create a Series with a default index</h3>
<p>The string representation of a Series shows the index on the left and the values on the right.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>s <span style="color:#f92672">=</span> pd<span style="color:#f92672">.</span>Series([<span style="color:#ae81ff">1</span>,<span style="color:#ae81ff">2</span>,<span style="color:#ae81ff">3</span>,<span style="color:#ae81ff">4</span>,<span style="color:#ae81ff">5</span>,<span style="color:#ae81ff">6</span>,<span style="color:#ae81ff">7</span>])
</span></span><span style="display:flex;"><span>s
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>    <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>    <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span>    <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">3</span>    <span style="color:#ae81ff">4</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">4</span>    <span style="color:#ae81ff">5</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">5</span>    <span style="color:#ae81ff">6</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">6</span>    <span style="color:#ae81ff">7</span>
</span></span><span style="display:flex;"><span>dtype: int64
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>s<span style="color:#f92672">.</span>array
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;</span>NumpyExtensionArray<span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>[<span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">2</span>, <span style="color:#ae81ff">3</span>, <span style="color:#ae81ff">4</span>, <span style="color:#ae81ff">5</span>, <span style="color:#ae81ff">6</span>, <span style="color:#ae81ff">7</span>]
</span></span><span style="display:flex;"><span>Length: <span style="color:#ae81ff">7</span>, dtype: int64
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>s<span style="color:#f92672">.</span>index
</span></span><span style="display:flex;"><span>RangeIndex(start<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span>, stop<span style="color:#f92672">=</span><span style="color:#ae81ff">7</span>, step<span style="color:#f92672">=</span><span style="color:#ae81ff">1</span>)
</span></span></code></pre></div><h3 id="create-a-series-with-a-custom-index">Create a Series with a custom index</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>s <span style="color:#f92672">=</span> pd<span style="color:#f92672">.</span>Series([<span style="color:#ae81ff">7</span>,<span style="color:#ae81ff">77</span>,<span style="color:#ae81ff">777</span>], index<span style="color:#f92672">=</span> [<span style="color:#e6db74">&#39;a&#39;</span>, <span style="color:#e6db74">&#39;b&#39;</span>, <span style="color:#e6db74">&#39;c&#39;</span>])
</span></span><span style="display:flex;"><span>s
</span></span><span style="display:flex;"><span>a      <span style="color:#ae81ff">7</span>
</span></span><span style="display:flex;"><span>b     <span style="color:#ae81ff">77</span>
</span></span><span style="display:flex;"><span>c    <span style="color:#ae81ff">777</span>
</span></span><span style="display:flex;"><span>dtype: int64
</span></span></code></pre></div><h3 id="selecting-values-from-a-series">Selecting values from a Series</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>s <span style="color:#f92672">=</span> pd<span style="color:#f92672">.</span>Series([<span style="color:#ae81ff">7</span>,<span style="color:#ae81ff">77</span>,<span style="color:#ae81ff">777</span>], index<span style="color:#f92672">=</span> [<span style="color:#e6db74">&#39;a&#39;</span>, <span style="color:#e6db74">&#39;b&#39;</span>, <span style="color:#e6db74">&#39;c&#39;</span>])
</span></span><span style="display:flex;"><span>s[<span style="color:#e6db74">&#39;b&#39;</span>]
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">77</span>
</span></span><span style="display:flex;"><span>s[[<span style="color:#e6db74">&#39;c&#39;</span>,<span style="color:#e6db74">&#39;b&#39;</span>,<span style="color:#e6db74">&#39;a&#39;</span>]]
</span></span><span style="display:flex;"><span>c    <span style="color:#ae81ff">777</span>
</span></span><span style="display:flex;"><span>b     <span style="color:#ae81ff">77</span>
</span></span><span style="display:flex;"><span>a      <span style="color:#ae81ff">7</span>
</span></span><span style="display:flex;"><span>dtype: int64
</span></span></code></pre></div><h3 id="from-python-dictionary-to-series-and-back">From Python dictionary to Series and back</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>data <span style="color:#f92672">=</span> {<span style="color:#ae81ff">1</span>:<span style="color:#e6db74">&#39;a&#39;</span>, <span style="color:#ae81ff">2</span>:<span style="color:#e6db74">&#39;b&#39;</span>, <span style="color:#ae81ff">3</span>:<span style="color:#e6db74">&#39;c&#39;</span>}
</span></span><span style="display:flex;"><span>s <span style="color:#f92672">=</span> pd<span style="color:#f92672">.</span>Series(data)
</span></span><span style="display:flex;"><span>s
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>    a
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span>    b
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">3</span>    c
</span></span><span style="display:flex;"><span>dtype: object
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>s<span style="color:#f92672">.</span>to_dict()
</span></span><span style="display:flex;"><span>{<span style="color:#ae81ff">1</span>: <span style="color:#e6db74">&#39;a&#39;</span>, <span style="color:#ae81ff">2</span>: <span style="color:#e6db74">&#39;b&#39;</span>, <span style="color:#ae81ff">3</span>: <span style="color:#e6db74">&#39;c&#39;</span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># passing `index` changes the order of the elements</span>
</span></span><span style="display:flex;"><span>s <span style="color:#f92672">=</span> pd<span style="color:#f92672">.</span>Series(data, index<span style="color:#f92672">=</span>[<span style="color:#ae81ff">3</span>,<span style="color:#ae81ff">2</span>,<span style="color:#ae81ff">1</span>])
</span></span><span style="display:flex;"><span>s
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">3</span>    c
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span>    b
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>    a
</span></span><span style="display:flex;"><span>dtype: object
</span></span></code></pre></div><h3 id="data-alignment-for-arithmetic-operations">Data alignment for arithmetic operations</h3>
<p>Exemplified for addition, but it works for other operations as well.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>s1 <span style="color:#f92672">=</span> pd<span style="color:#f92672">.</span>Series({<span style="color:#e6db74">&#39;a&#39;</span>:<span style="color:#ae81ff">1</span>, <span style="color:#e6db74">&#39;b&#39;</span>:<span style="color:#ae81ff">2</span>})
</span></span><span style="display:flex;"><span>s2 <span style="color:#f92672">=</span> pd<span style="color:#f92672">.</span>Series({<span style="color:#e6db74">&#39;a&#39;</span>:<span style="color:#ae81ff">9</span>, <span style="color:#e6db74">&#39;b&#39;</span>:<span style="color:#ae81ff">8</span>})
</span></span><span style="display:flex;"><span>s1 <span style="color:#f92672">+</span> s2
</span></span><span style="display:flex;"><span>a    <span style="color:#ae81ff">10</span>
</span></span><span style="display:flex;"><span>b    <span style="color:#ae81ff">10</span>
</span></span><span style="display:flex;"><span>dtype: int64
</span></span></code></pre></div><h2 id="operations-on-dataframe">Operations on DataFrame</h2>
<h3 id="creating-a-dataframe-from-a-dictionary-of-equal-length-lists">Creating a DataFrame from a dictionary of equal-length lists</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>frame <span style="color:#f92672">=</span> pd<span style="color:#f92672">.</span>DataFrame({<span style="color:#e6db74">&#39;even&#39;</span>:[<span style="color:#ae81ff">0</span>,<span style="color:#ae81ff">2</span>,<span style="color:#ae81ff">4</span>,<span style="color:#ae81ff">6</span>,<span style="color:#ae81ff">8</span>], <span style="color:#e6db74">&#39;odd&#39;</span>:[<span style="color:#ae81ff">1</span>,<span style="color:#ae81ff">3</span>,<span style="color:#ae81ff">5</span>,<span style="color:#ae81ff">7</span>,<span style="color:#ae81ff">9</span>], <span style="color:#e6db74">&#39;prime&#39;</span>:[<span style="color:#ae81ff">1</span>,<span style="color:#ae81ff">2</span>,<span style="color:#ae81ff">3</span>,<span style="color:#ae81ff">5</span>,<span style="color:#ae81ff">7</span>]})
</span></span><span style="display:flex;"><span>frame
</span></span><span style="display:flex;"><span>   even  odd  prime
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">0</span>    <span style="color:#ae81ff">1</span>      <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>     <span style="color:#ae81ff">2</span>    <span style="color:#ae81ff">3</span>      <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span>     <span style="color:#ae81ff">4</span>    <span style="color:#ae81ff">5</span>      <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">3</span>     <span style="color:#ae81ff">6</span>    <span style="color:#ae81ff">7</span>      <span style="color:#ae81ff">5</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">4</span>     <span style="color:#ae81ff">8</span>    <span style="color:#ae81ff">9</span>      <span style="color:#ae81ff">7</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># to change the order of the columns use the `columns` parameter</span>
</span></span><span style="display:flex;"><span>frame <span style="color:#f92672">=</span> pd<span style="color:#f92672">.</span>DataFrame({<span style="color:#e6db74">&#39;even&#39;</span>:[<span style="color:#ae81ff">0</span>,<span style="color:#ae81ff">2</span>,<span style="color:#ae81ff">4</span>,<span style="color:#ae81ff">6</span>,<span style="color:#ae81ff">8</span>], <span style="color:#e6db74">&#39;odd&#39;</span>:[<span style="color:#ae81ff">1</span>,<span style="color:#ae81ff">3</span>,<span style="color:#ae81ff">5</span>,<span style="color:#ae81ff">7</span>,<span style="color:#ae81ff">9</span>], <span style="color:#e6db74">&#39;prime&#39;</span>:[<span style="color:#ae81ff">1</span>,<span style="color:#ae81ff">2</span>,<span style="color:#ae81ff">3</span>,<span style="color:#ae81ff">5</span>,<span style="color:#ae81ff">7</span>]}, columns<span style="color:#f92672">=</span>[<span style="color:#e6db74">&#39;prime&#39;</span>,<span style="color:#e6db74">&#39;odd&#39;</span>,<span style="color:#e6db74">&#39;even&#39;</span>])
</span></span><span style="display:flex;"><span>frame
</span></span><span style="display:flex;"><span>   prime  odd  even
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>      <span style="color:#ae81ff">1</span>    <span style="color:#ae81ff">1</span>     <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>      <span style="color:#ae81ff">2</span>    <span style="color:#ae81ff">3</span>     <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span>      <span style="color:#ae81ff">3</span>    <span style="color:#ae81ff">5</span>     <span style="color:#ae81ff">4</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">3</span>      <span style="color:#ae81ff">5</span>    <span style="color:#ae81ff">7</span>     <span style="color:#ae81ff">6</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">4</span>      <span style="color:#ae81ff">7</span>    <span style="color:#ae81ff">9</span>     <span style="color:#ae81ff">8</span>
</span></span></code></pre></div><h3 id="retrieving-a-column-from-a-dataframe-as-a-series">Retrieving a column from a DataFrame as a Series</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>frame <span style="color:#f92672">=</span> pd<span style="color:#f92672">.</span>DataFrame({<span style="color:#e6db74">&#39;even&#39;</span>:[<span style="color:#ae81ff">0</span>,<span style="color:#ae81ff">2</span>,<span style="color:#ae81ff">4</span>,<span style="color:#ae81ff">6</span>,<span style="color:#ae81ff">8</span>], <span style="color:#e6db74">&#39;odd&#39;</span>:[<span style="color:#ae81ff">1</span>,<span style="color:#ae81ff">3</span>,<span style="color:#ae81ff">5</span>,<span style="color:#ae81ff">7</span>,<span style="color:#ae81ff">9</span>], <span style="color:#e6db74">&#39;prime&#39;</span>:[<span style="color:#ae81ff">1</span>,<span style="color:#ae81ff">2</span>,<span style="color:#ae81ff">3</span>,<span style="color:#ae81ff">5</span>,<span style="color:#ae81ff">7</span>]})
</span></span><span style="display:flex;"><span>primes <span style="color:#f92672">=</span> frame[<span style="color:#e6db74">&#39;prime&#39;</span>]
</span></span><span style="display:flex;"><span>primes
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>    <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>    <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span>    <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">3</span>    <span style="color:#ae81ff">5</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">4</span>    <span style="color:#ae81ff">7</span>
</span></span><span style="display:flex;"><span>Name: prime, dtype: int64
</span></span><span style="display:flex;"><span>type(primes)
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;</span><span style="color:#66d9ef">class</span> <span style="color:#960050;background-color:#1e0010">&#39;</span><span style="color:#a6e22e">pandas</span><span style="color:#f92672">.</span>core<span style="color:#f92672">.</span>series<span style="color:#f92672">.</span>Series<span style="color:#e6db74">&#39;&gt;</span>
</span></span></code></pre></div><h3 id="retrieving-a-row-from-a-dataframe-as-a-series">Retrieving a row from a DataFrame as a Series</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>frame <span style="color:#f92672">=</span> pd<span style="color:#f92672">.</span>DataFrame({<span style="color:#e6db74">&#39;even&#39;</span>:[<span style="color:#ae81ff">0</span>,<span style="color:#ae81ff">2</span>,<span style="color:#ae81ff">4</span>,<span style="color:#ae81ff">6</span>,<span style="color:#ae81ff">8</span>], <span style="color:#e6db74">&#39;odd&#39;</span>:[<span style="color:#ae81ff">1</span>,<span style="color:#ae81ff">3</span>,<span style="color:#ae81ff">5</span>,<span style="color:#ae81ff">7</span>,<span style="color:#ae81ff">9</span>], <span style="color:#e6db74">&#39;prime&#39;</span>:[<span style="color:#ae81ff">1</span>,<span style="color:#ae81ff">2</span>,<span style="color:#ae81ff">3</span>,<span style="color:#ae81ff">5</span>,<span style="color:#ae81ff">7</span>]})
</span></span><span style="display:flex;"><span>frame<span style="color:#f92672">.</span>loc[<span style="color:#ae81ff">4</span>]
</span></span><span style="display:flex;"><span>even     <span style="color:#ae81ff">8</span>
</span></span><span style="display:flex;"><span>odd      <span style="color:#ae81ff">9</span>
</span></span><span style="display:flex;"><span>prime    <span style="color:#ae81ff">7</span>
</span></span><span style="display:flex;"><span>Name: <span style="color:#ae81ff">4</span>, dtype: int64
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>frame<span style="color:#f92672">.</span>iloc[<span style="color:#ae81ff">4</span>]
</span></span><span style="display:flex;"><span>even     <span style="color:#ae81ff">8</span>
</span></span><span style="display:flex;"><span>odd      <span style="color:#ae81ff">9</span>
</span></span><span style="display:flex;"><span>prime    <span style="color:#ae81ff">7</span>
</span></span><span style="display:flex;"><span>Name: <span style="color:#ae81ff">4</span>, dtype: int64
</span></span></code></pre></div><h3 id="assigning-values-to-a-column">Assigning values to a column</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>frame
</span></span><span style="display:flex;"><span>   even  odd  prime
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">0</span>    <span style="color:#ae81ff">1</span>      <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>     <span style="color:#ae81ff">2</span>    <span style="color:#ae81ff">3</span>      <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span>     <span style="color:#ae81ff">4</span>    <span style="color:#ae81ff">5</span>      <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">3</span>     <span style="color:#ae81ff">6</span>    <span style="color:#ae81ff">7</span>      <span style="color:#ae81ff">5</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">4</span>     <span style="color:#ae81ff">8</span>    <span style="color:#ae81ff">9</span>      <span style="color:#ae81ff">7</span>
</span></span><span style="display:flex;"><span>frame<span style="color:#f92672">.</span>even <span style="color:#f92672">=</span> [<span style="color:#ae81ff">2</span>,<span style="color:#ae81ff">4</span>,<span style="color:#ae81ff">6</span>,<span style="color:#ae81ff">8</span>,<span style="color:#ae81ff">10</span>]
</span></span><span style="display:flex;"><span>frame
</span></span><span style="display:flex;"><span>   even  odd  prime
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">2</span>    <span style="color:#ae81ff">1</span>      <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>     <span style="color:#ae81ff">4</span>    <span style="color:#ae81ff">3</span>      <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span>     <span style="color:#ae81ff">6</span>    <span style="color:#ae81ff">5</span>      <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">3</span>     <span style="color:#ae81ff">8</span>    <span style="color:#ae81ff">7</span>      <span style="color:#ae81ff">5</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">4</span>    <span style="color:#ae81ff">10</span>    <span style="color:#ae81ff">9</span>      <span style="color:#ae81ff">7</span>
</span></span></code></pre></div><h3 id="adding-a-new-column">Adding a new column</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>frame
</span></span><span style="display:flex;"><span>   even  odd  prime
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">0</span>    <span style="color:#ae81ff">1</span>      <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>     <span style="color:#ae81ff">2</span>    <span style="color:#ae81ff">3</span>      <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span>     <span style="color:#ae81ff">4</span>    <span style="color:#ae81ff">5</span>      <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">3</span>     <span style="color:#ae81ff">6</span>    <span style="color:#ae81ff">7</span>      <span style="color:#ae81ff">5</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">4</span>     <span style="color:#ae81ff">8</span>    <span style="color:#ae81ff">9</span>      <span style="color:#ae81ff">7</span>
</span></span><span style="display:flex;"><span>frame[<span style="color:#e6db74">&#39;prime_is_odd&#39;</span>] <span style="color:#f92672">=</span> frame[<span style="color:#e6db74">&#39;prime&#39;</span>] <span style="color:#f92672">%</span> <span style="color:#ae81ff">2</span> <span style="color:#f92672">!=</span> <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>frame
</span></span><span style="display:flex;"><span>   even  odd  prime  prime_is_odd
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">0</span>    <span style="color:#ae81ff">1</span>      <span style="color:#ae81ff">1</span>          <span style="color:#66d9ef">True</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>     <span style="color:#ae81ff">2</span>    <span style="color:#ae81ff">3</span>      <span style="color:#ae81ff">2</span>         <span style="color:#66d9ef">False</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span>     <span style="color:#ae81ff">4</span>    <span style="color:#ae81ff">5</span>      <span style="color:#ae81ff">3</span>          <span style="color:#66d9ef">True</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">3</span>     <span style="color:#ae81ff">6</span>    <span style="color:#ae81ff">7</span>      <span style="color:#ae81ff">5</span>          <span style="color:#66d9ef">True</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">4</span>     <span style="color:#ae81ff">8</span>    <span style="color:#ae81ff">9</span>      <span style="color:#ae81ff">7</span>          <span style="color:#66d9ef">True</span>
</span></span></code></pre></div><h3 id="deleting-a-column">Deleting a column</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>frame<span style="color:#f92672">.</span>columns
</span></span><span style="display:flex;"><span>Index([<span style="color:#e6db74">&#39;even&#39;</span>, <span style="color:#e6db74">&#39;odd&#39;</span>, <span style="color:#e6db74">&#39;prime&#39;</span>, <span style="color:#e6db74">&#39;prime_is_odd&#39;</span>], dtype<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;object&#39;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">del</span> frame[<span style="color:#e6db74">&#39;prime_is_odd&#39;</span>]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>frame<span style="color:#f92672">.</span>columns
</span></span><span style="display:flex;"><span>Index([<span style="color:#e6db74">&#39;prime&#39;</span>, <span style="color:#e6db74">&#39;odd&#39;</span>, <span style="color:#e6db74">&#39;even&#39;</span>], dtype<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;object&#39;</span>)
</span></span></code></pre></div><h3 id="transposing-a-dataframe">Transposing a DataFrame</h3>
<p>i.e. swaping rows and columns</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>frame
</span></span><span style="display:flex;"><span>   even  odd  prime
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">0</span>    <span style="color:#ae81ff">1</span>      <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>     <span style="color:#ae81ff">2</span>    <span style="color:#ae81ff">3</span>      <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span>     <span style="color:#ae81ff">4</span>    <span style="color:#ae81ff">5</span>      <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">3</span>     <span style="color:#ae81ff">6</span>    <span style="color:#ae81ff">7</span>      <span style="color:#ae81ff">5</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">4</span>     <span style="color:#ae81ff">8</span>    <span style="color:#ae81ff">9</span>      <span style="color:#ae81ff">7</span>
</span></span><span style="display:flex;"><span>frame<span style="color:#f92672">.</span>T
</span></span><span style="display:flex;"><span>       <span style="color:#ae81ff">0</span>  <span style="color:#ae81ff">1</span>  <span style="color:#ae81ff">2</span>  <span style="color:#ae81ff">3</span>  <span style="color:#ae81ff">4</span>
</span></span><span style="display:flex;"><span>even   <span style="color:#ae81ff">0</span>  <span style="color:#ae81ff">2</span>  <span style="color:#ae81ff">4</span>  <span style="color:#ae81ff">6</span>  <span style="color:#ae81ff">8</span>
</span></span><span style="display:flex;"><span>odd    <span style="color:#ae81ff">1</span>  <span style="color:#ae81ff">3</span>  <span style="color:#ae81ff">5</span>  <span style="color:#ae81ff">7</span>  <span style="color:#ae81ff">9</span>
</span></span><span style="display:flex;"><span>prime  <span style="color:#ae81ff">1</span>  <span style="color:#ae81ff">2</span>  <span style="color:#ae81ff">3</span>  <span style="color:#ae81ff">5</span>  <span style="color:#ae81ff">7</span>
</span></span></code></pre></div><h3 id="from-dataframe-to-numpys-ndarray">From DataFrame to Numpy&rsquo;s ndarray</h3>
<p>NumPy arrays will be covered in another post. For now you can think of them as a more powerful version of Python&rsquo;s lists.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>frame
</span></span><span style="display:flex;"><span>   even  odd  prime
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">0</span>    <span style="color:#ae81ff">1</span>      <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>     <span style="color:#ae81ff">2</span>    <span style="color:#ae81ff">3</span>      <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span>     <span style="color:#ae81ff">4</span>    <span style="color:#ae81ff">5</span>      <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">3</span>     <span style="color:#ae81ff">6</span>    <span style="color:#ae81ff">7</span>      <span style="color:#ae81ff">5</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">4</span>     <span style="color:#ae81ff">8</span>    <span style="color:#ae81ff">9</span>      <span style="color:#ae81ff">7</span>
</span></span><span style="display:flex;"><span>frame<span style="color:#f92672">.</span>to_numpy()
</span></span><span style="display:flex;"><span>array([[<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">1</span>],
</span></span><span style="display:flex;"><span>       [<span style="color:#ae81ff">2</span>, <span style="color:#ae81ff">3</span>, <span style="color:#ae81ff">2</span>],
</span></span><span style="display:flex;"><span>       [<span style="color:#ae81ff">4</span>, <span style="color:#ae81ff">5</span>, <span style="color:#ae81ff">3</span>],
</span></span><span style="display:flex;"><span>       [<span style="color:#ae81ff">6</span>, <span style="color:#ae81ff">7</span>, <span style="color:#ae81ff">5</span>],
</span></span><span style="display:flex;"><span>       [<span style="color:#ae81ff">8</span>, <span style="color:#ae81ff">9</span>, <span style="color:#ae81ff">7</span>]])
</span></span></code></pre></div><h2 id="the-index-object">The Index object</h2>
<ul>
<li>is immutable</li>
<li>can be shared between data structures</li>
<li>is array-like and also behaves like a fixed-size <em>set</em></li>
<li>can contain duplicate labels</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>index <span style="color:#f92672">=</span> pd<span style="color:#f92672">.</span>Index([<span style="color:#e6db74">&#39;a&#39;</span>,<span style="color:#e6db74">&#39;a&#39;</span>,<span style="color:#e6db74">&#39;b&#39;</span>,<span style="color:#e6db74">&#39;c&#39;</span>])
</span></span><span style="display:flex;"><span>index
</span></span><span style="display:flex;"><span>Index([<span style="color:#e6db74">&#39;a&#39;</span>, <span style="color:#e6db74">&#39;a&#39;</span>, <span style="color:#e6db74">&#39;b&#39;</span>, <span style="color:#e6db74">&#39;c&#39;</span>], dtype<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;object&#39;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>index[<span style="color:#ae81ff">1</span>:]
</span></span><span style="display:flex;"><span>Index([<span style="color:#e6db74">&#39;a&#39;</span>, <span style="color:#e6db74">&#39;b&#39;</span>, <span style="color:#e6db74">&#39;c&#39;</span>], dtype<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;object&#39;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># index[0] = &#39;x&#39; -&gt; TypeError: Index does not support mutable operations</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>s <span style="color:#f92672">=</span> pd<span style="color:#f92672">.</span>Series([<span style="color:#ae81ff">1</span>,<span style="color:#ae81ff">1</span>,<span style="color:#ae81ff">2</span>,<span style="color:#ae81ff">3</span>], index<span style="color:#f92672">=</span>index)
</span></span><span style="display:flex;"><span>s
</span></span><span style="display:flex;"><span>a    <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>a    <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>b    <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>c    <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span>dtype: int64
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>s<span style="color:#f92672">.</span>index <span style="color:#f92672">is</span> index 
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">True</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>frame <span style="color:#f92672">=</span> pd<span style="color:#f92672">.</span>DataFrame({<span style="color:#e6db74">&#39;even&#39;</span>:[<span style="color:#ae81ff">0</span>,<span style="color:#ae81ff">2</span>,<span style="color:#ae81ff">4</span>,<span style="color:#ae81ff">6</span>,<span style="color:#ae81ff">8</span>], <span style="color:#e6db74">&#39;odd&#39;</span>:[<span style="color:#ae81ff">1</span>,<span style="color:#ae81ff">3</span>,<span style="color:#ae81ff">5</span>,<span style="color:#ae81ff">7</span>,<span style="color:#ae81ff">9</span>], <span style="color:#e6db74">&#39;prime&#39;</span>:[<span style="color:#ae81ff">1</span>,<span style="color:#ae81ff">2</span>,<span style="color:#ae81ff">3</span>,<span style="color:#ae81ff">5</span>,<span style="color:#ae81ff">7</span>]})
</span></span><span style="display:flex;"><span>frame<span style="color:#f92672">.</span>columns
</span></span><span style="display:flex;"><span>Index([<span style="color:#e6db74">&#39;even&#39;</span>, <span style="color:#e6db74">&#39;odd&#39;</span>, <span style="color:#e6db74">&#39;prime&#39;</span>], dtype<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;object&#39;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>frame<span style="color:#f92672">.</span>index
</span></span><span style="display:flex;"><span>RangeIndex(start<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span>, stop<span style="color:#f92672">=</span><span style="color:#ae81ff">5</span>, step<span style="color:#f92672">=</span><span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#e6db74">&#39;odd&#39;</span> <span style="color:#f92672">in</span> frame<span style="color:#f92672">.</span>columns
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">True</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">3</span> <span style="color:#f92672">in</span> frame<span style="color:#f92672">.</span>index
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">True</span>
</span></span></code></pre></div><h2 id="essential-functionality">Essential functionality</h2>
<h3 id="reindexing">Reindexing</h3>
<p>i.e. creates a new object with the values rearranged according to the new index.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>obj <span style="color:#f92672">=</span> pd<span style="color:#f92672">.</span>Series([<span style="color:#ae81ff">1</span>,<span style="color:#ae81ff">2</span>,<span style="color:#ae81ff">3</span>], index<span style="color:#f92672">=</span>[<span style="color:#e6db74">&#39;a&#39;</span>, <span style="color:#e6db74">&#39;b&#39;</span>, <span style="color:#e6db74">&#39;c&#39;</span>])
</span></span><span style="display:flex;"><span>obj
</span></span><span style="display:flex;"><span>a    <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>b    <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>c    <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span>dtype: int64
</span></span><span style="display:flex;"><span>obj<span style="color:#f92672">.</span>reindex([<span style="color:#e6db74">&#39;c&#39;</span>,<span style="color:#e6db74">&#39;b&#39;</span>,<span style="color:#e6db74">&#39;a&#39;</span>])
</span></span><span style="display:flex;"><span>c    <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span>b    <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>a    <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>dtype: int64
</span></span></code></pre></div><h3 id="dropping-entries-from-an-axis">Dropping entries from an axis</h3>
<p>of a Series:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>obj <span style="color:#f92672">=</span> pd<span style="color:#f92672">.</span>Series([<span style="color:#ae81ff">1</span>,<span style="color:#ae81ff">2</span>,<span style="color:#ae81ff">3</span>], index<span style="color:#f92672">=</span>[<span style="color:#e6db74">&#39;a&#39;</span>, <span style="color:#e6db74">&#39;b&#39;</span>, <span style="color:#e6db74">&#39;c&#39;</span>])
</span></span><span style="display:flex;"><span>obj<span style="color:#f92672">.</span>drop(<span style="color:#e6db74">&#39;b&#39;</span>)
</span></span><span style="display:flex;"><span>a    <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>c    <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span>dtype: int64
</span></span></code></pre></div><p>of a DataFrame:</p>
<p>This line <code>np.arange(4).reshape((2,2))</code> creates a 2x2 matrix with values from 0 to 3.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>frame <span style="color:#f92672">=</span> pd<span style="color:#f92672">.</span>DataFrame(np<span style="color:#f92672">.</span>arange(<span style="color:#ae81ff">4</span>)<span style="color:#f92672">.</span>reshape((<span style="color:#ae81ff">2</span>,<span style="color:#ae81ff">2</span>)), index<span style="color:#f92672">=</span>[<span style="color:#e6db74">&#39;a&#39;</span>, <span style="color:#e6db74">&#39;b&#39;</span>], columns<span style="color:#f92672">=</span>[<span style="color:#e6db74">&#39;c&#39;</span>, <span style="color:#e6db74">&#39;d&#39;</span>])
</span></span><span style="display:flex;"><span>frame
</span></span><span style="display:flex;"><span>   c  d
</span></span><span style="display:flex;"><span>a  <span style="color:#ae81ff">0</span>  <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>b  <span style="color:#ae81ff">2</span>  <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>frame<span style="color:#f92672">.</span>drop(index<span style="color:#f92672">=</span>[<span style="color:#e6db74">&#39;b&#39;</span>], columns<span style="color:#f92672">=</span>[<span style="color:#e6db74">&#39;d&#39;</span>])
</span></span><span style="display:flex;"><span>   c
</span></span><span style="display:flex;"><span>a  <span style="color:#ae81ff">0</span>
</span></span></code></pre></div><h3 id="indexing-selection-and-filtering">Indexing, selection, and filtering</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>obj <span style="color:#f92672">=</span> pd<span style="color:#f92672">.</span>Series([<span style="color:#ae81ff">1</span>,<span style="color:#ae81ff">2</span>,<span style="color:#ae81ff">3</span>,<span style="color:#ae81ff">4</span>], index<span style="color:#f92672">=</span>[<span style="color:#e6db74">&#39;a&#39;</span>, <span style="color:#e6db74">&#39;b&#39;</span>, <span style="color:#e6db74">&#39;c&#39;</span>, <span style="color:#e6db74">&#39;d&#39;</span>])
</span></span><span style="display:flex;"><span>obj[<span style="color:#e6db74">&#39;b&#39;</span>]
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>obj<span style="color:#f92672">.</span>loc[[<span style="color:#e6db74">&#39;b&#39;</span>,<span style="color:#e6db74">&#39;a&#39;</span>,<span style="color:#e6db74">&#39;d&#39;</span>]]
</span></span><span style="display:flex;"><span>b    <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>a    <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>d    <span style="color:#ae81ff">4</span>
</span></span><span style="display:flex;"><span>dtype: int64
</span></span><span style="display:flex;"><span>obj[<span style="color:#ae81ff">1</span>] <span style="color:#75715e"># Future warning: integer keys will always be treated as labels</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>obj<span style="color:#f92672">.</span>iloc[<span style="color:#ae81ff">1</span>]
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>obj[<span style="color:#ae81ff">2</span>:<span style="color:#ae81ff">4</span>]
</span></span><span style="display:flex;"><span>c    <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span>d    <span style="color:#ae81ff">4</span>
</span></span><span style="display:flex;"><span>dtype: int64
</span></span><span style="display:flex;"><span>obj[[<span style="color:#e6db74">&#39;b&#39;</span>,<span style="color:#e6db74">&#39;a&#39;</span>,<span style="color:#e6db74">&#39;d&#39;</span>]]
</span></span><span style="display:flex;"><span>b    <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>a    <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>d    <span style="color:#ae81ff">4</span>
</span></span><span style="display:flex;"><span>dtype: int64
</span></span><span style="display:flex;"><span>obj[obj <span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">2</span>]
</span></span><span style="display:flex;"><span>c    <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span>d    <span style="color:#ae81ff">4</span>
</span></span><span style="display:flex;"><span>dtype: int64
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>frame <span style="color:#f92672">=</span> pd<span style="color:#f92672">.</span>DataFrame(np<span style="color:#f92672">.</span>arange(<span style="color:#ae81ff">4</span>)<span style="color:#f92672">.</span>reshape((<span style="color:#ae81ff">2</span>,<span style="color:#ae81ff">2</span>)), index<span style="color:#f92672">=</span>[<span style="color:#e6db74">&#39;a&#39;</span>, <span style="color:#e6db74">&#39;b&#39;</span>], columns<span style="color:#f92672">=</span>[<span style="color:#e6db74">&#39;c&#39;</span>, <span style="color:#e6db74">&#39;d&#39;</span>])
</span></span><span style="display:flex;"><span>frame
</span></span><span style="display:flex;"><span>   c  d
</span></span><span style="display:flex;"><span>a  <span style="color:#ae81ff">0</span>  <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>b  <span style="color:#ae81ff">2</span>  <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span>frame<span style="color:#f92672">.</span>loc[<span style="color:#e6db74">&#39;b&#39;</span>]
</span></span><span style="display:flex;"><span>c    <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>d    <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span>Name: b, dtype: int64
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>frame<span style="color:#f92672">.</span>iloc[<span style="color:#ae81ff">1</span>]
</span></span><span style="display:flex;"><span>c    <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>d    <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span>Name: b, dtype: int64
</span></span></code></pre></div><h3 id="sorting">Sorting</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>obj <span style="color:#f92672">=</span> pd<span style="color:#f92672">.</span>Series([<span style="color:#ae81ff">4</span>,<span style="color:#ae81ff">3</span>,<span style="color:#ae81ff">2</span>,<span style="color:#ae81ff">1</span>], index<span style="color:#f92672">=</span>[<span style="color:#e6db74">&#39;d&#39;</span>, <span style="color:#e6db74">&#39;c&#39;</span>, <span style="color:#e6db74">&#39;b&#39;</span>, <span style="color:#e6db74">&#39;a&#39;</span>])
</span></span><span style="display:flex;"><span>obj<span style="color:#f92672">.</span>sort_index()
</span></span><span style="display:flex;"><span>a    <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>b    <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>c    <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span>d    <span style="color:#ae81ff">4</span>
</span></span><span style="display:flex;"><span>dtype: int64
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>frame <span style="color:#f92672">=</span> pd<span style="color:#f92672">.</span>DataFrame(np<span style="color:#f92672">.</span>arange(<span style="color:#ae81ff">4</span>)<span style="color:#f92672">.</span>reshape((<span style="color:#ae81ff">2</span>,<span style="color:#ae81ff">2</span>)), index<span style="color:#f92672">=</span>[<span style="color:#e6db74">&#39;b&#39;</span>, <span style="color:#e6db74">&#39;a&#39;</span>], columns<span style="color:#f92672">=</span>[<span style="color:#e6db74">&#39;d&#39;</span>, <span style="color:#e6db74">&#39;c&#39;</span>])
</span></span><span style="display:flex;"><span>frame
</span></span><span style="display:flex;"><span>   d  c
</span></span><span style="display:flex;"><span>b  <span style="color:#ae81ff">0</span>  <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>a  <span style="color:#ae81ff">2</span>  <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span>frame<span style="color:#f92672">.</span>sort_index()
</span></span><span style="display:flex;"><span>   d  c
</span></span><span style="display:flex;"><span>a  <span style="color:#ae81ff">2</span>  <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span>b  <span style="color:#ae81ff">0</span>  <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>frame<span style="color:#f92672">.</span>sort_index(axis<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;columns&#39;</span>)
</span></span><span style="display:flex;"><span>   c  d
</span></span><span style="display:flex;"><span>b  <span style="color:#ae81ff">1</span>  <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>a  <span style="color:#ae81ff">3</span>  <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>frame<span style="color:#f92672">.</span>sort_index(axis<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;columns&#39;</span>, ascending<span style="color:#f92672">=</span><span style="color:#66d9ef">False</span>)
</span></span><span style="display:flex;"><span>   d  c
</span></span><span style="display:flex;"><span>b  <span style="color:#ae81ff">0</span>  <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>a  <span style="color:#ae81ff">2</span>  <span style="color:#ae81ff">3</span>
</span></span></code></pre></div><h2 id="reading-and-writing-data">Reading and writing data</h2>
<p>Pandas can read and write data from and to a variety of formats, such as CSV, JSON, Excel, SQL databases, and more.</p>
<p>In this example, we will be focusing on reading and writing CSV files.</p>
<h3 id="reading-a-csv-file">Reading a CSV file</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>cat data.csv
</span></span><span style="display:flex;"><span>col1,col2,col3
</span></span><span style="display:flex;"><span>1,2,foo
</span></span><span style="display:flex;"><span>3,4,bar
</span></span><span style="display:flex;"><span>5,6,baz
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>pd.read_csv<span style="color:#f92672">(</span><span style="color:#e6db74">&#39;data.csv&#39;</span><span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>   col1  col2 col3
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">1</span>     <span style="color:#ae81ff">2</span>  foo
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>     <span style="color:#ae81ff">3</span>     <span style="color:#ae81ff">4</span>  bar
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span>     <span style="color:#ae81ff">5</span>     <span style="color:#ae81ff">6</span>  baz
</span></span></code></pre></div><p>In case the file does not have a header row, <code>read_csv</code>, has some parameters to help with that.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>cat data_no_header.csv
</span></span><span style="display:flex;"><span>1,2,foo
</span></span><span style="display:flex;"><span>3,4,bar
</span></span><span style="display:flex;"><span>5,6,baz
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>pd.read_csv<span style="color:#f92672">(</span><span style="color:#e6db74">&#39;data_no_header.csv&#39;</span>, header<span style="color:#f92672">=</span>None<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0</span>  <span style="color:#ae81ff">1</span>    <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>  <span style="color:#ae81ff">1</span>  <span style="color:#ae81ff">2</span>  foo
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>  <span style="color:#ae81ff">3</span>  <span style="color:#ae81ff">4</span>  bar
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span>  <span style="color:#ae81ff">5</span>  <span style="color:#ae81ff">6</span>  baz
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>pd.read_csv<span style="color:#f92672">(</span><span style="color:#e6db74">&#39;data_no_header.csv&#39;</span>, names<span style="color:#f92672">=[</span><span style="color:#e6db74">&#39;c1&#39;</span>,<span style="color:#e6db74">&#39;c2&#39;</span>,<span style="color:#e6db74">&#39;c3&#39;</span><span style="color:#f92672">])</span>
</span></span><span style="display:flex;"><span>   c1  c2   c3
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>   <span style="color:#ae81ff">1</span>   <span style="color:#ae81ff">2</span>  foo
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>   <span style="color:#ae81ff">3</span>   <span style="color:#ae81ff">4</span>  bar
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span>   <span style="color:#ae81ff">5</span>   <span style="color:#ae81ff">6</span>  baz
</span></span></code></pre></div><p>We can also specify the index column to be used instead of the default one.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>pd<span style="color:#f92672">.</span>read_csv(<span style="color:#e6db74">&#39;data.csv&#39;</span>)
</span></span><span style="display:flex;"><span>   col1  col2 col3
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">1</span>     <span style="color:#ae81ff">2</span>  foo
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>     <span style="color:#ae81ff">3</span>     <span style="color:#ae81ff">4</span>  bar
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span>     <span style="color:#ae81ff">5</span>     <span style="color:#ae81ff">6</span>  baz
</span></span><span style="display:flex;"><span>pd<span style="color:#f92672">.</span>read_csv(<span style="color:#e6db74">&#39;data.csv&#39;</span>, index_col<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;col3&#39;</span>)
</span></span><span style="display:flex;"><span>      col1  col2
</span></span><span style="display:flex;"><span>col3
</span></span><span style="display:flex;"><span>foo      <span style="color:#ae81ff">1</span>     <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>bar      <span style="color:#ae81ff">3</span>     <span style="color:#ae81ff">4</span>
</span></span><span style="display:flex;"><span>baz      <span style="color:#ae81ff">5</span>     <span style="color:#ae81ff">6</span>
</span></span></code></pre></div><p>In case the csv file uses another separator, we can specify it using the <code>sep</code> parameter.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>pd<span style="color:#f92672">.</span>read_csv(<span style="color:#e6db74">&#39;data_with_spaces.csv&#39;</span>, sep<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;</span><span style="color:#ae81ff">\\</span><span style="color:#e6db74">s+&#39;</span>)
</span></span><span style="display:flex;"><span>   col1  col2 col3
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">1</span>     <span style="color:#ae81ff">2</span>  foo
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>     <span style="color:#ae81ff">3</span>     <span style="color:#ae81ff">4</span>  bar
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span>     <span style="color:#ae81ff">5</span>     <span style="color:#ae81ff">6</span>  baz
</span></span></code></pre></div><p><code>read_csv</code> also allows us to skip specific rows, or to only read a specific number of rows.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>pd<span style="color:#f92672">.</span>read_csv(<span style="color:#e6db74">&#39;data_with_spaces.csv&#39;</span>, sep<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;</span><span style="color:#ae81ff">\\</span><span style="color:#e6db74">s+&#39;</span>)
</span></span><span style="display:flex;"><span>   col1  col2 col3
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">1</span>     <span style="color:#ae81ff">2</span>  foo
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>     <span style="color:#ae81ff">3</span>     <span style="color:#ae81ff">4</span>  bar
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span>     <span style="color:#ae81ff">5</span>     <span style="color:#ae81ff">6</span>  baz
</span></span><span style="display:flex;"><span>pd<span style="color:#f92672">.</span>read_csv(<span style="color:#e6db74">&#39;data_with_spaces.csv&#39;</span>, sep<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;</span><span style="color:#ae81ff">\\</span><span style="color:#e6db74">s+&#39;</span>, skiprows<span style="color:#f92672">=</span>[<span style="color:#ae81ff">1</span>,<span style="color:#ae81ff">2</span>])
</span></span><span style="display:flex;"><span>   col1  col2 col3
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">5</span>     <span style="color:#ae81ff">6</span>  baz
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>pd<span style="color:#f92672">.</span>read_csv(<span style="color:#e6db74">&#39;data_with_spaces.csv&#39;</span>, sep<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;</span><span style="color:#ae81ff">\\</span><span style="color:#e6db74">s+&#39;</span>)
</span></span><span style="display:flex;"><span>   col1  col2 col3
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">1</span>     <span style="color:#ae81ff">2</span>  foo
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>     <span style="color:#ae81ff">3</span>     <span style="color:#ae81ff">4</span>  bar
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span>     <span style="color:#ae81ff">5</span>     <span style="color:#ae81ff">6</span>  baz
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">3</span>     <span style="color:#ae81ff">7</span>     <span style="color:#ae81ff">8</span>  bax
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">4</span>     <span style="color:#ae81ff">9</span>    <span style="color:#ae81ff">10</span>  bay
</span></span><span style="display:flex;"><span>pd<span style="color:#f92672">.</span>read_csv(<span style="color:#e6db74">&#39;data_with_spaces.csv&#39;</span>, sep<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;</span><span style="color:#ae81ff">\\</span><span style="color:#e6db74">s+&#39;</span>, nrows<span style="color:#f92672">=</span><span style="color:#ae81ff">3</span>)
</span></span><span style="display:flex;"><span>   col1  col2 col3
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">1</span>     <span style="color:#ae81ff">2</span>  foo
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>     <span style="color:#ae81ff">3</span>     <span style="color:#ae81ff">4</span>  bar
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span>     <span style="color:#ae81ff">5</span>     <span style="color:#ae81ff">6</span>  baz
</span></span></code></pre></div><h3 id="writing-a-csv-file">Writing a CSV file</h3>
<p><code>to_csv</code> writes a DataFrame to a CSV file. It offers a variety of parameters to customize the output, among them are <code>sep</code>, <code>header</code>, and <code>columns</code>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>data <span style="color:#f92672">=</span> pd<span style="color:#f92672">.</span>read_csv(<span style="color:#e6db74">&#39;data_with_spaces.csv&#39;</span>, sep<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;</span><span style="color:#ae81ff">\\</span><span style="color:#e6db74">s+&#39;</span>, nrows<span style="color:#f92672">=</span><span style="color:#ae81ff">3</span>)
</span></span><span style="display:flex;"><span>data
</span></span><span style="display:flex;"><span>   col1  col2 col3
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">1</span>     <span style="color:#ae81ff">2</span>  foo
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>     <span style="color:#ae81ff">3</span>     <span style="color:#ae81ff">4</span>  bar
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span>     <span style="color:#ae81ff">5</span>     <span style="color:#ae81ff">6</span>  baz
</span></span><span style="display:flex;"><span>data<span style="color:#f92672">.</span>to_csv(<span style="color:#e6db74">&#39;new_data.csv&#39;</span>, sep<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;|&#39;</span>, header<span style="color:#f92672">=</span><span style="color:#66d9ef">True</span>, columns<span style="color:#f92672">=</span>[<span style="color:#e6db74">&#39;col2&#39;</span>,<span style="color:#e6db74">&#39;col3&#39;</span>])
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>cat new_data.csv
</span></span><span style="display:flex;"><span>|col2|col3
</span></span><span style="display:flex;"><span>0|2|foo
</span></span><span style="display:flex;"><span>1|4|bar
</span></span><span style="display:flex;"><span>2|6|baz
</span></span></code></pre></div><h2 id="data-cleaning">Data cleaning</h2>
<h3 id="missing-data">Missing data</h3>
<p>Python&rsquo;s <code>None</code> and NumPy&rsquo;s <code>np.nan</code>(<code>np</code> comes from <code>import numpy as np</code>) are considered missing data in Pandas.</p>
<p><code>na</code> stands for &ldquo;not available&rdquo;.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>s <span style="color:#f92672">=</span> pd<span style="color:#f92672">.</span>Series([<span style="color:#ae81ff">1</span>,<span style="color:#ae81ff">2</span>,np<span style="color:#f92672">.</span>nan,<span style="color:#66d9ef">None</span>,<span style="color:#ae81ff">3</span>,<span style="color:#ae81ff">4</span>])
</span></span><span style="display:flex;"><span>s
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>    <span style="color:#ae81ff">1.0</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>    <span style="color:#ae81ff">2.0</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span>    NaN
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">3</span>    NaN
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">4</span>    <span style="color:#ae81ff">3.0</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">5</span>    <span style="color:#ae81ff">4.0</span>
</span></span><span style="display:flex;"><span>dtype: float64
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>s<span style="color:#f92672">.</span>isna()
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>    <span style="color:#66d9ef">False</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>    <span style="color:#66d9ef">False</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span>     <span style="color:#66d9ef">True</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">3</span>     <span style="color:#66d9ef">True</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">4</span>    <span style="color:#66d9ef">False</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">5</span>    <span style="color:#66d9ef">False</span>
</span></span><span style="display:flex;"><span>dtype: bool
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>s<span style="color:#f92672">.</span>notna()
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>     <span style="color:#66d9ef">True</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>     <span style="color:#66d9ef">True</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span>    <span style="color:#66d9ef">False</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">3</span>    <span style="color:#66d9ef">False</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">4</span>     <span style="color:#66d9ef">True</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">5</span>     <span style="color:#66d9ef">True</span>
</span></span><span style="display:flex;"><span>dtype: bool
</span></span></code></pre></div><p><code>notna()</code> is the opposite of <code>isna()</code>.</p>
<h3 id="filtering-out-missing-data">Filtering out missing data</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>s <span style="color:#f92672">=</span> pd<span style="color:#f92672">.</span>Series([<span style="color:#ae81ff">1</span>,<span style="color:#ae81ff">2</span>,np<span style="color:#f92672">.</span>nan,<span style="color:#66d9ef">None</span>,<span style="color:#ae81ff">3</span>,<span style="color:#ae81ff">4</span>])
</span></span><span style="display:flex;"><span>s
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>    <span style="color:#ae81ff">1.0</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>    <span style="color:#ae81ff">2.0</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span>    NaN
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">3</span>    NaN
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">4</span>    <span style="color:#ae81ff">3.0</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">5</span>    <span style="color:#ae81ff">4.0</span>
</span></span><span style="display:flex;"><span>dtype: float64
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>s<span style="color:#f92672">.</span>dropna()
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>    <span style="color:#ae81ff">1.0</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>    <span style="color:#ae81ff">2.0</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">4</span>    <span style="color:#ae81ff">3.0</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">5</span>    <span style="color:#ae81ff">4.0</span>
</span></span><span style="display:flex;"><span>dtype: float64
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>data <span style="color:#f92672">=</span> pd<span style="color:#f92672">.</span>DataFrame([[<span style="color:#ae81ff">1</span>,<span style="color:#ae81ff">2</span>,<span style="color:#ae81ff">3</span>],[<span style="color:#ae81ff">4</span>,<span style="color:#66d9ef">None</span>,<span style="color:#ae81ff">5</span>],[<span style="color:#66d9ef">None</span>,<span style="color:#66d9ef">None</span>,np<span style="color:#f92672">.</span>nan]])
</span></span><span style="display:flex;"><span>data
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>    <span style="color:#ae81ff">1</span>    <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>  <span style="color:#ae81ff">1.0</span>  <span style="color:#ae81ff">2.0</span>  <span style="color:#ae81ff">3.0</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>  <span style="color:#ae81ff">4.0</span>  NaN  <span style="color:#ae81ff">5.0</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span>  NaN  NaN  NaN
</span></span><span style="display:flex;"><span>data<span style="color:#f92672">.</span>dropna()
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>    <span style="color:#ae81ff">1</span>    <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>  <span style="color:#ae81ff">1.0</span>  <span style="color:#ae81ff">2.0</span>  <span style="color:#ae81ff">3.0</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># to drop only rows that are all NA</span>
</span></span><span style="display:flex;"><span>data<span style="color:#f92672">.</span>dropna(how<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;all&#39;</span>)
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>    <span style="color:#ae81ff">1</span>    <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>  <span style="color:#ae81ff">1.0</span>  <span style="color:#ae81ff">2.0</span>  <span style="color:#ae81ff">3.0</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>  <span style="color:#ae81ff">4.0</span>  NaN  <span style="color:#ae81ff">5.0</span>
</span></span></code></pre></div><p>For dropping columns we need to specify <code>axis='columns'</code>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>data
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>    <span style="color:#ae81ff">1</span>    <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>  <span style="color:#ae81ff">1.0</span>  <span style="color:#ae81ff">2.0</span>  <span style="color:#ae81ff">3.0</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>  <span style="color:#ae81ff">4.0</span>  NaN  <span style="color:#ae81ff">5.0</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span>  NaN  NaN  NaN
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># add a new column with all NA values</span>
</span></span><span style="display:flex;"><span>data[len(data<span style="color:#f92672">.</span>columns)] <span style="color:#f92672">=</span> [<span style="color:#66d9ef">None</span>,<span style="color:#66d9ef">None</span>,<span style="color:#66d9ef">None</span>]
</span></span><span style="display:flex;"><span>data
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>    <span style="color:#ae81ff">1</span>    <span style="color:#ae81ff">2</span>     <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>  <span style="color:#ae81ff">1.0</span>  <span style="color:#ae81ff">2.0</span>  <span style="color:#ae81ff">3.0</span>  <span style="color:#66d9ef">None</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>  <span style="color:#ae81ff">4.0</span>  NaN  <span style="color:#ae81ff">5.0</span>  <span style="color:#66d9ef">None</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span>  NaN  NaN  NaN  <span style="color:#66d9ef">None</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>data<span style="color:#f92672">.</span>dropna(axis<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;columns&#39;</span>, how<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;all&#39;</span>)
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>    <span style="color:#ae81ff">1</span>    <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>  <span style="color:#ae81ff">1.0</span>  <span style="color:#ae81ff">2.0</span>  <span style="color:#ae81ff">3.0</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>  <span style="color:#ae81ff">4.0</span>  NaN  <span style="color:#ae81ff">5.0</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span>  NaN  NaN  NaN
</span></span></code></pre></div><h3 id="filling-in-missing-data">Filling in missing data</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>data
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>    <span style="color:#ae81ff">1</span>    <span style="color:#ae81ff">2</span>     <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>  <span style="color:#ae81ff">1.0</span>  <span style="color:#ae81ff">2.0</span>  <span style="color:#ae81ff">3.0</span>  <span style="color:#66d9ef">None</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>  <span style="color:#ae81ff">4.0</span>  NaN  <span style="color:#ae81ff">5.0</span>  <span style="color:#66d9ef">None</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span>  NaN  NaN  NaN  <span style="color:#66d9ef">None</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>data<span style="color:#f92672">.</span>fillna(<span style="color:#ae81ff">0</span>)
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>    <span style="color:#ae81ff">1</span>    <span style="color:#ae81ff">2</span>  <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>  <span style="color:#ae81ff">1.0</span>  <span style="color:#ae81ff">2.0</span>  <span style="color:#ae81ff">3.0</span>  <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>  <span style="color:#ae81ff">4.0</span>  <span style="color:#ae81ff">0.0</span>  <span style="color:#ae81ff">5.0</span>  <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span>  <span style="color:#ae81ff">0.0</span>  <span style="color:#ae81ff">0.0</span>  <span style="color:#ae81ff">0.0</span>  <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>data<span style="color:#f92672">.</span>fillna({<span style="color:#ae81ff">0</span>:<span style="color:#f92672">-</span><span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">1</span>:<span style="color:#f92672">-</span><span style="color:#ae81ff">2</span>, <span style="color:#ae81ff">2</span>:<span style="color:#f92672">-</span><span style="color:#ae81ff">3</span>, <span style="color:#ae81ff">3</span>:<span style="color:#f92672">-</span><span style="color:#ae81ff">4</span>})
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>    <span style="color:#ae81ff">1</span>    <span style="color:#ae81ff">2</span>  <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>  <span style="color:#ae81ff">1.0</span>  <span style="color:#ae81ff">2.0</span>  <span style="color:#ae81ff">3.0</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">4</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>  <span style="color:#ae81ff">4.0</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">2.0</span>  <span style="color:#ae81ff">5.0</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">4</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">1.0</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">2.0</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">3.0</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">4</span>
</span></span></code></pre></div><h3 id="removing-duplicates">Removing duplicates</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>data <span style="color:#f92672">=</span> pd<span style="color:#f92672">.</span>DataFrame([[<span style="color:#ae81ff">1</span>,<span style="color:#ae81ff">2</span>,<span style="color:#ae81ff">3</span>],[<span style="color:#ae81ff">4</span>,<span style="color:#ae81ff">2</span>,<span style="color:#ae81ff">5</span>],[<span style="color:#ae81ff">1</span>,<span style="color:#ae81ff">2</span>,<span style="color:#ae81ff">3</span>]])
</span></span><span style="display:flex;"><span>data
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0</span>  <span style="color:#ae81ff">1</span>  <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>  <span style="color:#ae81ff">1</span>  <span style="color:#ae81ff">2</span>  <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>  <span style="color:#ae81ff">4</span>  <span style="color:#ae81ff">2</span>  <span style="color:#ae81ff">5</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span>  <span style="color:#ae81ff">1</span>  <span style="color:#ae81ff">2</span>  <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># returns a boolean Series indicating whether each row is a duplicate</span>
</span></span><span style="display:flex;"><span>data<span style="color:#f92672">.</span>duplicated()
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>    <span style="color:#66d9ef">False</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>    <span style="color:#66d9ef">False</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span>     <span style="color:#66d9ef">True</span>
</span></span><span style="display:flex;"><span>dtype: bool
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>data<span style="color:#f92672">.</span>drop_duplicates()
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0</span>  <span style="color:#ae81ff">1</span>  <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>  <span style="color:#ae81ff">1</span>  <span style="color:#ae81ff">2</span>  <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>  <span style="color:#ae81ff">4</span>  <span style="color:#ae81ff">2</span>  <span style="color:#ae81ff">5</span>
</span></span></code></pre></div><p>By defaault, <code>drop_duplicates</code> looks at all columns, but we can specify a subset of columns to consider.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>data
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>    <span style="color:#ae81ff">1</span>    <span style="color:#ae81ff">2</span>  <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>  <span style="color:#ae81ff">1.0</span>  <span style="color:#ae81ff">2.0</span>  <span style="color:#ae81ff">3.0</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">4</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>  <span style="color:#ae81ff">4.0</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">2.0</span>  <span style="color:#ae81ff">5.0</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">4</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">1.0</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">2.0</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">3.0</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">4</span>
</span></span><span style="display:flex;"><span>data<span style="color:#f92672">.</span>drop_duplicates(subset<span style="color:#f92672">=</span>[<span style="color:#ae81ff">3</span>])
</span></span><span style="display:flex;"><span>     <span style="color:#ae81ff">0</span>    <span style="color:#ae81ff">1</span>    <span style="color:#ae81ff">2</span>  <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>  <span style="color:#ae81ff">1.0</span>  <span style="color:#ae81ff">2.0</span>  <span style="color:#ae81ff">3.0</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">4</span>
</span></span></code></pre></div><h3 id="applying-functions-or-mapping">Applying functions or mapping</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>data <span style="color:#f92672">=</span> pd<span style="color:#f92672">.</span>DataFrame([[<span style="color:#ae81ff">1</span>,<span style="color:#ae81ff">2</span>,<span style="color:#ae81ff">3</span>],[<span style="color:#ae81ff">4</span>,<span style="color:#ae81ff">2</span>,<span style="color:#ae81ff">5</span>],[<span style="color:#ae81ff">1</span>,<span style="color:#ae81ff">2</span>,<span style="color:#ae81ff">3</span>]])
</span></span><span style="display:flex;"><span>data
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0</span>  <span style="color:#ae81ff">1</span>  <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>  <span style="color:#ae81ff">1</span>  <span style="color:#ae81ff">2</span>  <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>  <span style="color:#ae81ff">4</span>  <span style="color:#ae81ff">2</span>  <span style="color:#ae81ff">5</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span>  <span style="color:#ae81ff">1</span>  <span style="color:#ae81ff">2</span>  <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">f</span>(x):
</span></span><span style="display:flex;"><span><span style="color:#f92672">...</span>     <span style="color:#66d9ef">return</span> x<span style="color:#f92672">**</span><span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">...</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>data[<span style="color:#ae81ff">3</span>] <span style="color:#f92672">=</span> data[<span style="color:#ae81ff">2</span>]<span style="color:#f92672">.</span>map(f)
</span></span><span style="display:flex;"><span>data
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0</span>  <span style="color:#ae81ff">1</span>  <span style="color:#ae81ff">2</span>   <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>  <span style="color:#ae81ff">1</span>  <span style="color:#ae81ff">2</span>  <span style="color:#ae81ff">3</span>   <span style="color:#ae81ff">9</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>  <span style="color:#ae81ff">4</span>  <span style="color:#ae81ff">2</span>  <span style="color:#ae81ff">5</span>  <span style="color:#ae81ff">25</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">2</span>  <span style="color:#ae81ff">1</span>  <span style="color:#ae81ff">2</span>  <span style="color:#ae81ff">3</span>   <span style="color:#ae81ff">9</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>digits <span style="color:#f92672">=</span> pd<span style="color:#f92672">.</span>DataFrame([[<span style="color:#ae81ff">1</span>,<span style="color:#ae81ff">2</span>],[<span style="color:#ae81ff">3</span>,<span style="color:#ae81ff">4</span>]])
</span></span><span style="display:flex;"><span>digits
</span></span><span style="display:flex;"><span>   <span style="color:#ae81ff">0</span>  <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>  <span style="color:#ae81ff">1</span>  <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>  <span style="color:#ae81ff">3</span>  <span style="color:#ae81ff">4</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>d <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span><span style="color:#f92672">...</span> <span style="color:#ae81ff">1</span>: <span style="color:#e6db74">&#39;one&#39;</span>,
</span></span><span style="display:flex;"><span><span style="color:#f92672">...</span> <span style="color:#ae81ff">2</span>: <span style="color:#e6db74">&#39;two&#39;</span>,
</span></span><span style="display:flex;"><span><span style="color:#f92672">...</span> <span style="color:#ae81ff">3</span>: <span style="color:#e6db74">&#39;three&#39;</span>,
</span></span><span style="display:flex;"><span><span style="color:#f92672">...</span> <span style="color:#ae81ff">4</span>: <span style="color:#e6db74">&#39;four&#39;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">...</span> }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>digits[<span style="color:#ae81ff">0</span>] <span style="color:#f92672">=</span> digits[<span style="color:#ae81ff">0</span>]<span style="color:#f92672">.</span>map(d)
</span></span><span style="display:flex;"><span>digits[<span style="color:#ae81ff">1</span>] <span style="color:#f92672">=</span> digits[<span style="color:#ae81ff">1</span>]<span style="color:#f92672">.</span>map(d)
</span></span><span style="display:flex;"><span>digits
</span></span><span style="display:flex;"><span>       <span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">0</span>    one   two
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span>  three  four
</span></span></code></pre></div><h2 id="outro">Outro</h2>
<p>This post covered the basics of Pandas, a powerful data manipulation tool built on top of Python. We learned about the main data structures in Pandas, the <code>Series</code> and <code>DataFrame</code> objects, and how to perform operations on them.</p>
<p>This is just the tip of the iceberg, Pandas has a lot more to offer, and I encourage you to explore the <a href="https://pandas.pydata.org/docs/" target="_blank">official documentation</a> and other resources to learn more about it.</p>
]]></content>
        </item>
        
        <item>
            <title>Learning... Machine Learning</title>
            <link>https://vladflore.tech/posts/2024/09/learning...-machine-learning/</link>
            <pubDate>Fri, 13 Sep 2024 00:00:00 +0000</pubDate>
            
            <guid>https://vladflore.tech/posts/2024/09/learning...-machine-learning/</guid>
            <description>&lt;h2 id=&#34;the-whys&#34;&gt;The Whys&lt;/h2&gt;
&lt;p&gt;The time has come. I will learn Machine Learning, or at least, I&amp;rsquo;ll be trying my best to do so. You might now ask yourself, &lt;em&gt;why machine learning?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Nowadays, Machine Learning(ML), is on a lot of people&amp;rsquo;s minds, especially after the rise of the LLMs (Large Language Models).&lt;/p&gt;
&lt;p&gt;To not know about ML is to be left behind. I want to be part of the future, and I want to be able to understand the technology that will shape it.&lt;/p&gt;</description>
            <content type="html"><![CDATA[<h2 id="the-whys">The Whys</h2>
<p>The time has come. I will learn Machine Learning, or at least, I&rsquo;ll be trying my best to do so. You might now ask yourself, <em>why machine learning?</em></p>
<p>Nowadays, Machine Learning(ML), is on a lot of people&rsquo;s minds, especially after the rise of the LLMs (Large Language Models).</p>
<p>To not know about ML is to be left behind. I want to be part of the future, and I want to be able to understand the technology that will shape it.</p>
<p>As with a lot of other things, one can just look at it from the outside, make use of it, maybe even apply it, or one can dive deep into it, understand it, and maybe even contribute to it.
I want to be part of the latter group.</p>
<p>Understanding ML and applying it to solve problems, <em>can</em> be a fun and rewarding experience. In my case, I&rsquo;ve been having this itch for a while now, and time has come to scratch it.</p>
<p>While I am, as I am writing this, not actually doing ML professionally, I do work in an environment where ML is used. The work the ML engineers are doing there seems fascinating to me, and since I am a curios person, I want to know what&rsquo;s all about it.</p>
<p>I also think that knowing ML will be beneficial for my career. I am a software engineer, and I think that knowing ML will nicely complement my skill set.</p>
<h2 id="the-hows">The Hows</h2>
<p>There are a lot of resources out there to learn ML, some free, some paid. After bookmarking too many of them, I decided to start with two of them, both free. The main one, the one I will be focusing on, is <a href="https://github.com/DataTalksClub/machine-learning-zoomcamp" target="_blank">Machine Learning Zoomcamp</a> by Alexey Grigorev and co. I registered for this 4 months long free course and I am excited to start it. I will be complementing it with the <a href="https://developers.google.com/machine-learning/crash-course" target="_blank">Machine Learning Crash Course</a> by Google. This is also free and has been recently updated. Additionally, I will be skimming through the relevant chapters of the book <a href="https://www.amazon.com/Artificial-Intelligence-A-Modern-Approach/dp/0134610997" target="_blank">Artificial Intelligence, A Modern Approach, 4th Edition</a>.</p>
<p>I will be documenting my journey here, in this blog. I will be writing about the concepts I learn, the exercises I do, the projects I work on, and the challenges I face. I will also be sharing the resources I find useful.</p>
<p>If things go well, I might even decide to for a more formal education in ML, something that fits my schedule and my budget. I have these two in mind:</p>
<ul>
<li><a href="https://www.deeplearning.ai/courses/machine-learning-specialization/" target="_blank">Machine Learning Specialization</a></li>
<li><a href="https://online.stanford.edu/programs/artificial-intelligence-professional-program" target="_blank">Artificial Intelligence Professional Program from Stanford</a></li>
</ul>
<p>Of course, these are just two of the many options out there.</p>
<h2 id="the-prerequisites">The Prerequisites</h2>
<p>While learning is not something I frown upon, it does require <em>time</em> and effort. As I am also working, this extra learning has to happen in my free time, i.e. outside the proverbial 9 to 5. I hope that with a bit of discipline and better time management, I will be able to do it.</p>
<p>When it comes to machine learning (ML), <em>Python</em> is the most widely used language, making it crucial to have a strong understanding of it. Python is renowned for its simplicity and ease of learning, so even those who are not very familiar with it can quickly become proficient. Personally, I already have a good command of Python, so I am well-prepared in this aspect. While Python is the most popular language for ML, it is not the only one used in the field. Languages like R and Julia are also employed. I believe Python&rsquo;s popularity is largely due to the extensive <em>libraries and frameworks</em> available for ML, rather than the language itself.</p>
<p>The depth of one&rsquo;s engagement in this field dictates the necessity for a solid grasp of mathematics. This doesn&rsquo;t imply mastering all areas of mathematics, but rather having a firm understanding of <em>linear algebra</em>, <em>calculus</em>, and <em>probability theory</em>. Eventually, mathematical concepts will come into play, and having a strong foundation in these areas will be beneficial.</p>
<p>Besides the language itself, Python libraries are essential when it comes to ML. Depending on the task at hand, different libraries are used, and as such it is important to be familiar with them. Some of the most popular libraries include:</p>
<ul>
<li><a href="https://numpy.org/" target="_blank">NumPy</a></li>
<li><a href="https://pandas.pydata.org/" target="_blank">Pandas</a></li>
<li><a href="https://matplotlib.org/" target="_blank">Matplotlib</a></li>
<li><a href="https://scikit-learn.org/" target="_blank">Scikit-learn</a></li>
<li><a href="https://www.tensorflow.org/" target="_blank">TensorFlow</a></li>
<li><a href="https://pytorch.org/" target="_blank">PyTorch</a></li>
<li><a href="https://keras.io/" target="_blank">Keras</a></li>
<li><a href="https://mlflow.org/" target="_blank">MLflow</a></li>
</ul>
<p>On top of all this, one might have to work with <em>cloud services</em> like AWS, GCP, or Azure, use <em>Docker</em> and <em>Kubernetes</em>, and have a good understanding of <em>data engineering</em> and <em>data science</em>, as these are closely related to ML.</p>
<p>So, as you can see, there is a lot to cover. This might feel overwhelming at first, but Rome was not built in a day, so step by step, it&rsquo;s the way to go.</p>
<p>Happy learning!</p>
]]></content>
        </item>
        
        <item>
            <title>Life update</title>
            <link>https://vladflore.tech/posts/2024/09/life-update/</link>
            <pubDate>Fri, 06 Sep 2024 00:00:00 +0000</pubDate>
            
            <guid>https://vladflore.tech/posts/2024/09/life-update/</guid>
            <description>&lt;p&gt;It&amp;rsquo;s been 20 months since I moved to another country, and life has been quite interesting since then.&lt;/p&gt;
&lt;p&gt;To give some context, I left Germany at the beginning of January 2023 and moved to Barcelona, Spain. In other words, I swapped &lt;em&gt;Bratwurst&lt;/em&gt;, &lt;em&gt;Bretzel&lt;/em&gt;, and cold weather for &lt;em&gt;jamón&lt;/em&gt;, &lt;em&gt;crema catalana&lt;/em&gt;, and warm weather. This is, of course, an oversimplification, but it&amp;rsquo;s still accurate.&lt;/p&gt;
&lt;p&gt;As you may know, moving to a new country is not easy, even with help. Because of this, the first few weeks and even months were a bit hectic and different from what I expected.&lt;/p&gt;</description>
            <content type="html"><![CDATA[<p>It&rsquo;s been 20 months since I moved to another country, and life has been quite interesting since then.</p>
<p>To give some context, I left Germany at the beginning of January 2023 and moved to Barcelona, Spain. In other words, I swapped <em>Bratwurst</em>, <em>Bretzel</em>, and cold weather for <em>jamón</em>, <em>crema catalana</em>, and warm weather. This is, of course, an oversimplification, but it&rsquo;s still accurate.</p>
<p>As you may know, moving to a new country is not easy, even with help. Because of this, the first few weeks and even months were a bit hectic and different from what I expected.</p>
<p>One of the things that really surprised me was that people here don&rsquo;t speak English very well, if at all.</p>
<p>As I write this, I&rsquo;ve had several interactions with people from different areas, and that first impression still holds true. You can communicate with them in English, and they will try to help, but it&rsquo;s not always easy. I&rsquo;m okay with this since I&rsquo;m the foreigner and should learn their language, but just be aware that English isn&rsquo;t enough here — nor is German!</p>
<p>The biggest surprise comes when you expect them to speak English well, especially in institutions where they claim to speak English. But when you approach them, it turns out it&rsquo;s more of a &ldquo;más o menos&rdquo; situation with an emphasis on &ldquo;menos.&rdquo;</p>
<p>That being said, where there’s a will, there’s a way, and using gestures and &ldquo;Spanglish&rdquo; works just as well. So, until you improve your Spanish, just do your best and accept that you’re going to make a fool of yourself every now and then.</p>
<p>The language situation here deserves a <a href="">separate post</a>, so keep an eye out for that.</p>
<p>To keep things brief, I&rsquo;ll share more about <a href="">my experiences in and around Barcelona</a> in the future, so stay tuned!</p>
<p>Another update is that I’ve been working on a new project called The <em>I-Fit Project</em>—or to put it simply, I’ve started going to the gym and eating healthier ;). I began this journey in March 2023 and have been going to the gym regularly, with a few breaks here and there. Along the way, I faced some health issues, mostly due to not being active before, but they are now mostly under control.</p>
<p>By going to the gym, I do not mean just that, I took a genuine interest in it, and I&rsquo;ve been learning a lot about fitness, nutrition, and health. I&rsquo;ve also been working with a personal trainer, who has been a great help in this journey. While it is not always easy, I&rsquo;m happy with the progress I&rsquo;ve made so far and I am looking forward to what things could look like in the future.</p>
<p>One last thing before closing this post, people here are very different than in Germany. They are more open, friendly, and&hellip; loud. They are also more relaxed and less punctual, which can be a bit frustrating at times. But, as with the language, you get used to it and learn to adapt.</p>
<p>While not everything is perfect, good nutritious food, warm weather, the sea, and the mountains make up for it.</p>
]]></content>
        </item>
        
        <item>
            <title>Learning Python as a Java developer - 2/</title>
            <link>https://vladflore.tech/posts/2023/06/learning-python-as-a-java-developer-2/</link>
            <pubDate>Mon, 12 Jun 2023 00:00:00 +0000</pubDate>
            
            <guid>https://vladflore.tech/posts/2023/06/learning-python-as-a-java-developer-2/</guid>
            <description>&lt;p&gt;This is the second part of the series &amp;ldquo;Learning Python as a Java developer&amp;rdquo;. If you are interested in the other ones, check the links below:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://vladflore.tech/posts/2022/07/learning-python-as-a-java-developer-1/&#34;&gt;part one&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;learning-resources&#34;&gt;Learning resources&lt;/h2&gt;
&lt;p&gt;Before going into the details of the second part, I want to enumerate some of the resources I used and I am still using to learn/brush up on Python, beside the ones I mentioned in the first part:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://cs50.harvard.edu/python/2022/&#34; target=&#34;_blank&#34;&gt;CS50’s Introduction to Programming with Python, 2022&lt;/a&gt; - free/payed&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://dabeaz-course.github.io/practical-python/&#34; target=&#34;_blank&#34;&gt;Practical Python Programming, a course by David Beazley&lt;/a&gt; - free. Note: search for content made by David Beazley, he is a great!&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://edube.org/&#34; target=&#34;_blank&#34;&gt;OpenEDG Python courses&lt;/a&gt; - free&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://hyperskill.org&#34; target=&#34;_blank&#34;&gt;Hyperskill Python tracks&lt;/a&gt; - payed&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.educative.io/&#34; target=&#34;_blank&#34;&gt;Educative.io Python courses&lt;/a&gt; - payed&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.python.org/3/tutorial/index.html&#34; target=&#34;_blank&#34;&gt;The Python Tutorial&lt;/a&gt; - free&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://realpython.com/&#34; target=&#34;_blank&#34;&gt;Real Python&lt;/a&gt; - free/payed&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://learnxinyminutes.com/docs/python/&#34; target=&#34;_blank&#34;&gt;Learn X in Y minutes&lt;/a&gt; - free&lt;/li&gt;
&lt;li&gt;Working on Python projects&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are a lot of other resources out there, each one with its own pros and cons. I suggest you to try some of them and find the one that fits you the best. Google is your friend!&lt;/p&gt;</description>
            <content type="html"><![CDATA[<p>This is the second part of the series &ldquo;Learning Python as a Java developer&rdquo;. If you are interested in the other ones, check the links below:</p>
<ul>
<li><a href="https://vladflore.tech/posts/2022/07/learning-python-as-a-java-developer-1/">part one</a></li>
</ul>
<h2 id="learning-resources">Learning resources</h2>
<p>Before going into the details of the second part, I want to enumerate some of the resources I used and I am still using to learn/brush up on Python, beside the ones I mentioned in the first part:</p>
<ul>
<li><a href="https://cs50.harvard.edu/python/2022/" target="_blank">CS50’s Introduction to Programming with Python, 2022</a> - free/payed</li>
<li><a href="https://dabeaz-course.github.io/practical-python/" target="_blank">Practical Python Programming, a course by David Beazley</a> - free. Note: search for content made by David Beazley, he is a great!</li>
<li><a href="https://edube.org/" target="_blank">OpenEDG Python courses</a> - free</li>
<li><a href="https://hyperskill.org" target="_blank">Hyperskill Python tracks</a> - payed</li>
<li><a href="https://www.educative.io/" target="_blank">Educative.io Python courses</a> - payed</li>
<li><a href="https://docs.python.org/3/tutorial/index.html" target="_blank">The Python Tutorial</a> - free</li>
<li><a href="https://realpython.com/" target="_blank">Real Python</a> - free/payed</li>
<li><a href="https://learnxinyminutes.com/docs/python/" target="_blank">Learn X in Y minutes</a> - free</li>
<li>Working on Python projects</li>
</ul>
<p>There are a lot of other resources out there, each one with its own pros and cons. I suggest you to try some of them and find the one that fits you the best. Google is your friend!</p>
<h2 id="first-impressions--cntd">First impressions &hellip; cnt&rsquo;d</h2>
<p>In the first part I talked about some of the first impressions I had when I started learning Python. In this part I want to talk about some other ones.</p>
<p>Python is a <em>dynamically typed language</em>, so you don&rsquo;t have to declare the type of a variable. For example, if you have a variable <code>a</code> and you assign it to a value, let&rsquo;s say <code>1</code>, you can&rsquo;t know the type of <code>a</code> just by looking at the code. You have to run it and see what happens. However, <a href="https://peps.python.org/pep-0484/" target="_blank">PEP 484</a> introduced <em>type hints</em>, so you can add type hints to your code and have a better understanding of what is going on. For example, you can do something like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>a: int <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>
</span></span></code></pre></div><p>You would need a tool to check the type hints, like <a href="https://mypy.readthedocs.io/en/stable/" target="_blank">mypy</a>. However, you don&rsquo;t have to use type hints, they are optional.</p>
<p>Python is also an <em>interpreted language</em>, so you don&rsquo;t have to compile it, as is the case of Java. This is great, because you can run your code as soon as you write it. On the other side, you don&rsquo;t have a compiler to tell you if you are doing something wrong. You have to run your code and see what happens.</p>
<p>An interpreted language is also slower than a compiled one. However, Python is not that slow, because it is implemented in C, see <a href="https://github.com/python/cpython" target="_blank">CPython</a>. If you need to speed up your code, you can use a tool like <a href="https://cython.org/" target="_blank">Cython</a>. To add to the confusion, there is also <a href="https://www.jython.org/" target="_blank">Jython</a>, an implementation of Python in Java.</p>
<p>Another thing that I found a bit confusing is the fact that <em>you can assign a value to a variable without declaring it</em>. For example, you can do something like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>a <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>b <span style="color:#f92672">=</span> <span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>c <span style="color:#f92672">=</span> a <span style="color:#f92672">+</span> b
</span></span></code></pre></div><p>This is perfectly fine, but if you are coming from a language like Java, you are used to declare the variables before using them.</p>
<p>Knowing another programming language can be a double-edged sword. On one side, you can leverage your knowledge to learn the new language faster. On the other side, you can be confused by the differences between the two languages.</p>
<p>Once you get the hang of it, Python is a great language to work with. It is easy to learn, it has a lot of libraries and it is <em>used in a lot of different fields</em>, from web development to data science. It is also a great language to teach programming.</p>
<p>Another thing worth mentioning is that Python is a <em>multi-paradigm language</em>. You can use it in an imperative, functional or object-oriented way. You can also mix the paradigms. Much the same as Java, but with a simpler syntax and less typing.</p>
<p>When writing Java code I usually look at the internal implementation of the classes and methods I am using. This is a great way to learn how things work under the hood. However, in Python this is not always possible, because the <em>implementation is written in C</em>. You can still look at the source code, but it is not as easy as in Java.</p>
<p>Moving past the syntax and the features you would expect to have in any language, there are some things that are specific to Python. For example, Python has <em>list comprehensions</em>, which are a great way to create lists. You can do something like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>digits <span style="color:#f92672">=</span> [x <span style="color:#66d9ef">for</span> x <span style="color:#f92672">in</span> range(<span style="color:#ae81ff">10</span>)]
</span></span></code></pre></div><p>This is equivalent to:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>digits <span style="color:#f92672">=</span> []
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> x <span style="color:#f92672">in</span> range(<span style="color:#ae81ff">10</span>):
</span></span><span style="display:flex;"><span>    digits<span style="color:#f92672">.</span>append(x)
</span></span></code></pre></div><p>Besides being shorter, list comprehensions are also faster than the equivalent <code>for</code> loop. Besides list comprehensions, there are also <em>dictionary and set comprehensions</em>.</p>
<p><em>Generators</em> are another great feature of Python. They are a way to create <em>iterators</em>. You can do something like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>digits_gen_exp <span style="color:#f92672">=</span> (x <span style="color:#66d9ef">for</span> x <span style="color:#f92672">in</span> range(<span style="color:#ae81ff">10</span>))
</span></span></code></pre></div><p>This is equivalent to:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">digits_gen_fun</span>():
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> x <span style="color:#f92672">in</span> range(<span style="color:#ae81ff">10</span>):
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">yield</span> x
</span></span></code></pre></div><p>The difference between the two is that the first one is a <em>generator expression</em>, while the second one is a <em>generator function</em>. The generator expression is shorter and faster than the generator function.</p>
<p>Once you got yourself a generator, you can do a lot of things with it. You can iterate over it:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#66d9ef">for</span> digit <span style="color:#f92672">in</span> digits_gen_exp:
</span></span><span style="display:flex;"><span>    print(digit)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> digit <span style="color:#f92672">in</span> digits_gen_fun():
</span></span><span style="display:flex;"><span>    print(digit)
</span></span></code></pre></div><p>You can create other data structures from it:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>d1 <span style="color:#f92672">=</span> list(digits_gen_exp)
</span></span><span style="display:flex;"><span>d2 <span style="color:#f92672">=</span> set(digits_gen_fun())
</span></span><span style="display:flex;"><span>d3 <span style="color:#f92672">=</span> dict(zip(digits_gen_exp, digits_gen_fun()))
</span></span></code></pre></div><p>More advanced topics include <em>decorators</em>, <em>context managers</em> and <em>metaclasses</em>. The equivalent in Java would be <em>annotations</em>, <em>try-with-resources</em> and <em>reflection</em>.</p>
<p>Additionally, there are some <em>magic methods</em> that you can implement to customize the behavior of your classes. For example, you can implement the <code>__add__</code> method to customize the behavior of the <code>+</code> operator. Overloading operators in not something you can do in Java.</p>
<p>When it comes to doing more at once or doing things faster, Python has the <em>event loop</em> and the <em>asyncio module</em>, the <em>multiprocessing module</em> and the <em>threading module</em>. In Java you have the <em>ExecutorService</em> and the <em>CompletableFuture</em>, among other things.</p>
<p>Python also has <em>modules</em> and <em>packages</em>. A module is a file containing Python code. A package is a directory containing Python code. You can import modules and packages in your code. You can also create your own modules and packages. In Java you have <em>packages</em> and <em>JAR files</em>. The term <em>module</em> is used in Java 9 and later and differs from the Python one.</p>
<p>Python has a lot of <em>built-in functions</em> and <em>built-in types</em>. You can find a list of them <a href="https://docs.python.org/3/library/functions.html" target="_blank">here</a> and <a href="https://docs.python.org/3/library/stdtypes.html" target="_blank">here</a>. You can also create your own functions and types, much the same as in Java where you have <em>methods</em> and <em>classes</em>.</p>
<p>Both languages have a lot of out-of-the-box functionality provided by the language itself and their respective ecosystems bring a lot more to the table. In Python I find it sometimes difficult to decide on <em>which package to use</em>, because there are a lot of them and there is no bulletproof way to choose one. I haven&rsquo;t had this feeling in Java.</p>
<p>Handling exceptions in Python is similar to handling them in Java. You have the <code>try</code> and <code>except</code> keywords. You can also use the <code>finally</code> keyword to execute some code after the <code>try</code> block, regardless of whether an exception was thrown or not. The <code>else</code> clause is also available, to execute some code if no exception was thrown. This last bit is not available in Java. You can also create your own exceptions, much the same as in Java.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">divide</span>(x, y):
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">try</span>:
</span></span><span style="display:flex;"><span>        result <span style="color:#f92672">=</span> x <span style="color:#f92672">/</span> y
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">except</span> <span style="color:#a6e22e">ZeroDivisionError</span>:
</span></span><span style="display:flex;"><span>        print(<span style="color:#e6db74">&#34;division by zero!&#34;</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">else</span>:
</span></span><span style="display:flex;"><span>        print(<span style="color:#e6db74">&#34;result is&#34;</span>, result)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">finally</span>:
</span></span><span style="display:flex;"><span>        print(<span style="color:#e6db74">&#34;executing finally clause&#34;</span>)
</span></span></code></pre></div><p>In Python you raise exceptions with the <code>raise</code> keyword, while in Java you throw them with the <code>throw</code> keyword.</p>
<p>Should you be interested into Machine Learning or Data Science, Python is a great language to learn. There are a lot of libraries available, like <a href="https://numpy.org/" target="_blank">NumPy</a>, <a href="https://www.scipy.org/" target="_blank">SciPy</a>, <a href="https://pandas.pydata.org/" target="_blank">Pandas</a>, <a href="https://matplotlib.org/" target="_blank">Matplotlib</a> and <a href="https://www.tensorflow.org/" target="_blank">TensorFlow</a>. You can also use <a href="https://jupyter.org/" target="_blank">Jupyter Notebooks</a> to create interactive documents. Java has some libraries for Machine Learning and Data Science, but they are not as popular as the Python ones.</p>
<p>Python is also a great language for web development. You can use <a href="https://www.djangoproject.com/" target="_blank">Django</a> or <a href="https://flask.palletsprojects.com/" target="_blank">Flask</a> to create web applications. You can also use <a href="https://riverbankcomputing.com/software/pyqt/intro" target="_blank">PyQt</a> or <a href="https://wiki.qt.io/Qt_for_Python" target="_blank">PySide</a> to create desktop applications. Java has <a href="https://spring.io/" target="_blank">Spring</a> for web development and <a href="https://openjfx.io/" target="_blank">JavaFX</a> for desktop applications.</p>
<p>Another fairly new addition to the Python ecosystem is <a href="https://docs.pyscript.net/latest/index.html#" target="_blank">PyScript</a> which allows you to write Python code and compile it to JavaScript. This is similar to <a href="https://www.graalvm.org/" target="_blank">GraalVM</a> which allows you to write Java code and compile it to JavaScript.</p>
<p>Python is also a great language for scripting. You can use it to automate tasks on your computer. You can also use it to create <em>command line interfaces</em> for your applications. Java is not that great for scripting, but you can still use it for that.</p>
<p>In future posts I will try to focus on a specific topic and compare how it is done in Java and Python. This can serve as a go-to guide for people working with both languages, including myself.</p>
<p>Happy coding!</p>
]]></content>
        </item>
        
        <item>
            <title>Java 17</title>
            <link>https://vladflore.tech/posts/2022/07/java-17/</link>
            <pubDate>Fri, 22 Jul 2022 00:00:00 +0000</pubDate>
            
            <guid>https://vladflore.tech/posts/2022/07/java-17/</guid>
            <description>&lt;h2 id=&#34;meet-java-17&#34;&gt;Meet Java 17&lt;/h2&gt;
&lt;p&gt;Java&amp;hellip; &lt;em&gt;what version is it?&lt;/em&gt; &amp;hellip;&lt;a href=&#34;https://openjdk.org/projects/jdk/17/&#34; target=&#34;_blank&#34;&gt;17&lt;/a&gt; reached GA on 14.09.2021 and brought a bunch
of new features, of which two are of more interest than the rest, at least for me. These are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;sealed classes&lt;/li&gt;
&lt;li&gt;pattern matching for switch (first preview)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Java 17 is a &lt;em&gt;LTS version&lt;/em&gt;.&lt;/p&gt;
&lt;h3 id=&#34;sealed-classes&#34;&gt;Sealed classes&lt;/h3&gt;
&lt;p&gt;Sealed classes came in Java 17 via &lt;a href=&#34;https://openjdk.org/jeps/409&#34; target=&#34;_blank&#34;&gt;JEP 409&lt;/a&gt; and although the name says &amp;ldquo;sealed &lt;em&gt;classes&lt;/em&gt;&amp;rdquo;
, interfaces are also subject to being sealed. With this new feature, three new special keywords have been added to the
language: &lt;code&gt;sealed&lt;/code&gt;, &lt;code&gt;non-sealed&lt;/code&gt; and &lt;code&gt;permits&lt;/code&gt;. The basic idea is that sealed classes and interfaces restrict which
other classes or interfaces may extend or implement them. Let&amp;rsquo;s look at an example:&lt;/p&gt;</description>
            <content type="html"><![CDATA[<h2 id="meet-java-17">Meet Java 17</h2>
<p>Java&hellip; <em>what version is it?</em> &hellip;<a href="https://openjdk.org/projects/jdk/17/" target="_blank">17</a> reached GA on 14.09.2021 and brought a bunch
of new features, of which two are of more interest than the rest, at least for me. These are:</p>
<ul>
<li>sealed classes</li>
<li>pattern matching for switch (first preview)</li>
</ul>
<p>Java 17 is a <em>LTS version</em>.</p>
<h3 id="sealed-classes">Sealed classes</h3>
<p>Sealed classes came in Java 17 via <a href="https://openjdk.org/jeps/409" target="_blank">JEP 409</a> and although the name says &ldquo;sealed <em>classes</em>&rdquo;
, interfaces are also subject to being sealed. With this new feature, three new special keywords have been added to the
language: <code>sealed</code>, <code>non-sealed</code> and <code>permits</code>. The basic idea is that sealed classes and interfaces restrict which
other classes or interfaces may extend or implement them. Let&rsquo;s look at an example:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#66d9ef">sealed</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">A</span> permits A1, A2 {}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">final</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">A1</span> <span style="color:#66d9ef">extends</span> A {}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">sealed</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">A2</span> <span style="color:#66d9ef">extends</span> A permits B {}
</span></span><span style="display:flex;"><span>non<span style="color:#f92672">-</span><span style="color:#66d9ef">sealed</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">B</span> <span style="color:#66d9ef">extends</span> A2 {}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">X</span> <span style="color:#66d9ef">extends</span> B {}
</span></span></code></pre></div><p>Class <code>A</code> is sealed and allows only classes <code>A1</code> and <code>A2</code> to extend it. Both <code>A1</code> and <code>A2</code> do that, but <code>A2</code> is again
declared as sealed, allowing only class <code>B</code> to extend it. Class <code>B</code> does that and, additionally, is declared as
non-sealed, which means its part of the hierarchy reverts to being open for extension by unknown subclasses. Class <code>X</code>
can extend <code>B</code> without any problems. One interesting aspect is that every permitted class must use a modifier to
describe how it propagates the sealing initiated by its superclass, that is either <code>final</code>, <code>sealed</code> or <code>non-sealed</code>
must be specified, any combination of these being invalid.</p>
<p>The same idea applies to interfaces too. Let&rsquo;s take for instance this structure:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#66d9ef">sealed</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">I</span> permits J {}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">sealed</span> <span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">J</span> <span style="color:#66d9ef">extends</span> I permits C, D {}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">final</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">C</span> <span style="color:#66d9ef">implements</span> J {}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">record</span> <span style="color:#a6e22e">D</span>() <span style="color:#66d9ef">implements</span> J {}
</span></span></code></pre></div><p>Interface <code>I</code> permits to be extended only by interface <code>J</code>, which is also a sealed interface permitting only classes <code>C</code>
and <code>D</code> to implement it. <code>J</code> must be declared either as <code>sealed</code> or <code>non-sealed</code>. Class <code>C</code> must also be either <code>final</code>
, <code>sealed</code> or <code>non-sealed</code>. The interesting piece is class <code>D</code>, which is a <code>record</code>. Records are by construct <code>final</code>,
so the condition above still holds. Note that <code>D</code> cannot extend any other class, it can only implement interfaces, the
reason is that a record already extends another class: <code>java.lang.Record</code>. You can convince yourself of this by
disassembling class <code>D</code> using <code>javap D</code> and looking at what the compiler did for you:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#66d9ef">final</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">D</span> <span style="color:#66d9ef">extends</span> java.<span style="color:#a6e22e">lang</span>.<span style="color:#a6e22e">Record</span> <span style="color:#66d9ef">implements</span> J
</span></span></code></pre></div><p>Sealed classes allow us to model a fixed set of <em>kinds</em> of values, similar to how <code>enum</code> classes allow us to model the
situation where a given class has only a fixed number of instances. You will be seeing sealed classes in pattern
matching for switch because they support the exhaustive analysis of patterns.</p>
<h3 id="pattern-matching-for-switch-first-preview">Pattern matching for switch (first preview)</h3>
<p>Pattern matching, <a href="https://openjdk.org/jeps/406" target="_blank">JEP 406</a> for switch is one of the features that fall under the umbrella of <em>pattern matching</em>. This feature is
in its first preview in Java 17, which mean you have to activate it before being able to actually use it. At the time of
this writing there are two other previews dealing with this: <a href="https://openjdk.org/jeps/420" target="_blank">JEP 420 - Java 18</a>
and <a href="https://openjdk.org/jeps/427" target="_blank">JEP 427 - Java 19</a>. Before going into some of the aspects of pattern matching for
switch, let&rsquo;s see what pattern matching itself wants to be.</p>
<p>Pattern matching(PM) is part of the <a href="https://openjdk.org/projects/amber/" target="_blank">Amber project</a>, which has the goal of
exploring and incubating smaller productivity-oriented Java language features that have been accepted as candidate JEPs.
PM is not a new thing under the sun, <a href="https://en.wikipedia.org/wiki/Pattern_matching" target="_blank">according to Wikipedia</a> it goes as
back as 1950, but it is a new thing in Java. The very basic idea is to check <em>something</em> for the existence of some <em>pattern</em> and take some actions if there is a match. A <em>pattern</em> is a combination of a <em>match predicate</em> that determines if the pattern matches a target, along with a set of <em>pattern variables</em> that are conditionally extracted if the pattern matches the target.</p>
<p>Now, this idea of <em>matching against something and taking some action if there is a match</em> might make you think about
the <code>instanceof</code> operator and the <code>switch</code> statement or expression. <a href="https://openjdk.org/jeps/325" target="_blank">Java 12</a> introduced
the switch expression which was finalized and made permanent in <a href="https://openjdk.org/jeps/361" target="_blank">Java 14</a>.</p>
<p>Long story short, you can now write code as below, wherein the second <code>if</code> makes use of pattern matching
for <code>instanceof</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span>Object obj <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;Hello World&#34;</span>;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> (obj <span style="color:#66d9ef">instanceof</span> String) {
</span></span><span style="display:flex;"><span>    String s <span style="color:#f92672">=</span> (String) obj;
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// do something with s, e.g. s.length()</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> (obj <span style="color:#66d9ef">instanceof</span> String s) {
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// do something with s, e.g. s.length()</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Before looking at how pattern matching for <code>switch</code> looks like, let&rsquo;s remind ourselves how a <code>switch</code> expression looks like.</p>
<p>Given an enum <code>house</code> representing the Hogwarts houses, we can get the house&rsquo;s founder using a switch expression.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#66d9ef">return</span> <span style="color:#66d9ef">switch</span> (house) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">case</span> GRYFFINDOR <span style="color:#f92672">-&gt;</span> <span style="color:#e6db74">&#34;Godric Gryffindor&#34;</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">case</span> HAFFLEPUFF <span style="color:#f92672">-&gt;</span> <span style="color:#e6db74">&#34;Helga Hufflepuff&#34;</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">case</span> RAVENCLAW <span style="color:#f92672">-&gt;</span> <span style="color:#e6db74">&#34;Rowena Ravenclaw&#34;</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">case</span> SLYTHERIN <span style="color:#f92672">-&gt;</span> <span style="color:#e6db74">&#34;Salazar Slytherin&#34;</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">case</span> <span style="color:#66d9ef">null</span> <span style="color:#f92672">-&gt;</span> <span style="color:#e6db74">&#34;not a house&#34;</span>;
</span></span><span style="display:flex;"><span>};
</span></span></code></pre></div><p>Note the separate handling for the <code>null</code> case!</p>
<p>Make sure to check the JEPs above as there is a lot going on regarding switch.</p>
<p>Now, <em>la pièce de résistance</em> is using pattern matching for switch with sealed classes. Let&rsquo;s see how that looks like.</p>
<p>Given the following pieces of code:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">abstract</span> <span style="color:#66d9ef">sealed</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">HogwartsHouse</span> permits Gryffindor, Hafflepuff, Ravenclaw, Slytherin {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">abstract</span> String <span style="color:#a6e22e">name</span>();
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">abstract</span> String <span style="color:#a6e22e">colors</span>();
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">abstract</span> String <span style="color:#a6e22e">founder</span>();
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">abstract</span> String <span style="color:#a6e22e">animal</span>();
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> String <span style="color:#a6e22e">details</span>() {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> String.<span style="color:#a6e22e">format</span>(<span style="color:#e6db74">&#34;%-13s - %-20s - %-20s - %-10s&#34;</span>, name(), colors(), founder(), animal());
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">final</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Gryffindor</span> <span style="color:#66d9ef">extends</span> HogwartsHouse {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">@Override</span> <span style="color:#66d9ef">public</span> String <span style="color:#a6e22e">name</span>() { <span style="color:#66d9ef">return</span> <span style="color:#e6db74">&#34;Gryffindor&#34;</span>; }
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">@Override</span> <span style="color:#66d9ef">public</span> String <span style="color:#a6e22e">colors</span>() { <span style="color:#66d9ef">return</span> <span style="color:#e6db74">&#34;Scarlet and Gold&#34;</span>; }
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">@Override</span> <span style="color:#66d9ef">public</span> String <span style="color:#a6e22e">founder</span>() { <span style="color:#66d9ef">return</span> <span style="color:#e6db74">&#34;Godric Gryffindor&#34;</span>; }
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">@Override</span> <span style="color:#66d9ef">public</span> String <span style="color:#a6e22e">animal</span>() { <span style="color:#66d9ef">return</span> <span style="color:#e6db74">&#34;Lion&#34;</span>; }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// The other houses (Hufflepuff, Ravenclaw, Slytherin) have been left out for the sake of brevity.</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// They all extend HogwartsHouse and implement the methods accordingly.</span>
</span></span></code></pre></div><p>we can write something like this to get the details of every house:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">HogwartsSchool</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">main</span>(String<span style="color:#f92672">[]</span> args) {
</span></span><span style="display:flex;"><span>        Stream.<span style="color:#a6e22e">of</span>(<span style="color:#66d9ef">new</span> Gryffindor(), <span style="color:#66d9ef">new</span> Hafflepuff(), <span style="color:#66d9ef">new</span> Ravenclaw(), <span style="color:#66d9ef">new</span> Slytherin(), <span style="color:#66d9ef">null</span>)
</span></span><span style="display:flex;"><span>            .<span style="color:#a6e22e">map</span>(HogwartsSchool::buildDetails).<span style="color:#a6e22e">forEach</span>(System.<span style="color:#a6e22e">out</span>::println);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">static</span> String <span style="color:#a6e22e">buildDetails</span>(HogwartsHouse house) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">switch</span> (house) {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">case</span> Gryffindor gryffindor <span style="color:#f92672">-&gt;</span> {
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">var</span> details <span style="color:#f92672">=</span> gryffindor.<span style="color:#a6e22e">details</span>();
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">yield</span> details.<span style="color:#a6e22e">concat</span>(<span style="color:#e6db74">&#34;students: Harry, Hermione, Ron&#34;</span>);
</span></span><span style="display:flex;"><span>            }
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">case</span> Hafflepuff hafflepuff <span style="color:#f92672">-&gt;</span> hafflepuff.<span style="color:#a6e22e">details</span>();
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">case</span> Ravenclaw ravenclaw <span style="color:#f92672">-&gt;</span> ravenclaw.<span style="color:#a6e22e">details</span>();
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">case</span> Slytherin slytherin <span style="color:#f92672">-&gt;</span> slytherin.<span style="color:#a6e22e">details</span>();
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">case</span> <span style="color:#66d9ef">null</span> <span style="color:#f92672">-&gt;</span> <span style="color:#e6db74">&#34;not a house&#34;</span>;
</span></span><span style="display:flex;"><span>        };
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>which produces this result:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>Gryffindor    - Scarlet and Gold     - Godric Gryffindor    - Lion      students: Harry, Hermione, Ron
</span></span><span style="display:flex;"><span>Hafflepuff    - Yellow and Black     - Helga Hufflepuff     - Badger    
</span></span><span style="display:flex;"><span>Ravenclaw     - Blue and Bronze      - Rowena Ravenclaw     - Eagle     
</span></span><span style="display:flex;"><span>Slytherin     - Green and Silver     - Salazar Slytherin    - Snake     
</span></span><span style="display:flex;"><span>not a house
</span></span></code></pre></div><p>You might have noticed, that the building details logic can be shortened quite a bit by just calling <code>house.details()</code> and leaving the polymorphism do its thing, plus adding some extra bit for the case the house is a Gryffindor one. Nonetheless, a house can <em>only</em> be one of those four types, and each pattern variable is of the correct subtype. Without sealing the house, that code would not have compiled. Notice that we are not comparing against a specific set of values, but against a specific set of types.</p>
<p>Suppose now that we change the signature of the method to be this: <code>static String buildDetails(Object house)</code>, i.e. instead of <code>HogwartsHouse</code> we have <code>Object</code> for the type of the house. This requires us to account for the missing cases, i.e. all the other possible objects that could be a <em>house</em>, arrays, lists, etc., which of course is nonsensical. The solution is to change the last case to this: <code>case default, null -&gt; &quot;not a house&quot;;</code>. Now, we are all good, the code compiles and we get the same result as before. Again, notice that we are comparing against a set of possible types, just as before.</p>
<p>Do not forget to enable the preview features, in IntelliJ IDEA is as simple as selecting the language level for the project
to be <code>17 (Preview) - Pattern matching for switch</code>.</p>
<p>From the command line it looks like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>javac HogwartsHouse.java Gryffindor.java Ravenclaw.java Hafflepuff.java Slytherin.java HogwartsSchool.java --release <span style="color:#ae81ff">17</span> --enable-preview
</span></span><span style="display:flex;"><span>java --enable-preview HogwartsSchool
</span></span></code></pre></div><h2 id="java-17s-predecessors">Java 17&rsquo;s predecessors</h2>
<p>From here on I&rsquo;ll be touching upon some other features/language improvements which came in the language in different previous versions, which I find most interesting.</p>
<h3 id="local-variable-type-inference">Local Variable Type Inference</h3>
<p>In a mortal&rsquo;s language this just means that there is a new way of declaring local variables, i.e. variables inside a method, without having to specify the type, in which case the type is inferred, if possible. The magic keyword is <code>var</code> and ca be used in instance methods, in static methods, it cannot be used for field initialization nor in cases where the compiler thinks that there is not enough information to infer the type(initializing with <code>null</code>, no initialization, return type).</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> aString <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;Hello, World!&#34;</span>; <span style="color:#75715e">// Ok</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> aListOfStrings <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> ArrayList<span style="color:#f92672">&lt;</span>String<span style="color:#f92672">&gt;</span>(); <span style="color:#75715e">// Ok</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> aNull <span style="color:#f92672">=</span> <span style="color:#66d9ef">null</span>; <span style="color:#75715e">// Ko</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> notInitialized; <span style="color:#75715e">// Ko</span>
</span></span></code></pre></div><h3 id="private-methods-in-interfaces">Private Methods in Interfaces</h3>
<p>Besides <code>default</code> and <code>static</code> methods in interfaces, since Java 9 it is also possible to add <code>private</code> methods. So, that code which should not be available for everyone, should be put inside a private method. Given the following interface and implementation:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">Interface</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">default</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">d</span>() { p(); }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">s</span>() { ps(); }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">p</span>() { }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">ps</span>() { }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">InterfaceImpl</span> <span style="color:#66d9ef">implements</span> Interface {}
</span></span></code></pre></div><p>we have the following:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#66d9ef">new</span> InterfaceImpl().<span style="color:#a6e22e">d</span>(); <span style="color:#75715e">// Ok</span>
</span></span><span style="display:flex;"><span>Interface.<span style="color:#a6e22e">s</span>(); <span style="color:#75715e">// Ok</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">new</span> InterfaceImpl().<span style="color:#a6e22e">p</span>(); <span style="color:#75715e">// Ko - not available to call</span>
</span></span><span style="display:flex;"><span>Interface.<span style="color:#a6e22e">ps</span>(); <span style="color:#75715e">// Ko - not available to call</span>
</span></span></code></pre></div><h3 id="records">Records</h3>
<p>Java 16 brought us <em>records</em>, a.k.a a sort of <em>data transfer object</em>, or <em>data carrier</em>. A record automatically generates:</p>
<ul>
<li>immutable fields for each of its components</li>
<li>a canonical constructor</li>
<li>accessor methods for all of its components</li>
<li><code>equals()</code></li>
<li><code>hashCode()</code></li>
<li><code>toString()</code></li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#66d9ef">interface</span> <span style="color:#a6e22e">Wizard</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">performSpell</span>();
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">record</span> <span style="color:#a6e22e">HogwartsStudent</span>(String name, House house) <span style="color:#66d9ef">implements</span> Wizard {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// this is the compact constructor (optional) used to perform name validation</span>
</span></span><span style="display:flex;"><span>    HogwartsStudent {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (name <span style="color:#f92672">==</span> <span style="color:#66d9ef">null</span> <span style="color:#f92672">||</span> name.<span style="color:#a6e22e">isBlank</span>()) {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">throw</span> <span style="color:#66d9ef">new</span> IllegalArgumentException(<span style="color:#e6db74">&#34;Must specify a name for the student.&#34;</span>);
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// adjustment to field can only happen in the constructor</span>
</span></span><span style="display:flex;"><span>        name <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;Dr. &#34;</span> <span style="color:#f92672">+</span> name;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">@Override</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">performSpell</span>() {
</span></span><span style="display:flex;"><span>        System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(<span style="color:#e6db74">&#34;Perform a spell&#34;</span>);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> harry <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> HogwartsStudent(<span style="color:#e6db74">&#34;Harry Potter&#34;</span>, House.<span style="color:#a6e22e">GRYFFINDOR</span>);
</span></span><span style="display:flex;"><span>System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(harry.<span style="color:#a6e22e">name</span>()); <span style="color:#75715e">// prints Dr. Harry Potter</span>
</span></span><span style="display:flex;"><span>System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(harry.<span style="color:#a6e22e">house</span>()); <span style="color:#75715e">// prints GRYFFINDOR</span>
</span></span><span style="display:flex;"><span>harry.<span style="color:#a6e22e">performSpell</span>();
</span></span></code></pre></div><p>Let&rsquo;s look now at what the compiler does for us (<code>javap HogwartsStudent.class</code>):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#66d9ef">final</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">HogwartsStudent</span> <span style="color:#66d9ef">extends</span> java.<span style="color:#a6e22e">lang</span>.<span style="color:#a6e22e">Record</span> {
</span></span><span style="display:flex;"><span>  HogwartsStudent(java.<span style="color:#a6e22e">lang</span>.<span style="color:#a6e22e">String</span>, House);
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">final</span> java.<span style="color:#a6e22e">lang</span>.<span style="color:#a6e22e">String</span> <span style="color:#a6e22e">toString</span>();
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">final</span> <span style="color:#66d9ef">int</span> <span style="color:#a6e22e">hashCode</span>();
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">final</span> <span style="color:#66d9ef">boolean</span> <span style="color:#a6e22e">equals</span>(java.<span style="color:#a6e22e">lang</span>.<span style="color:#a6e22e">Object</span>);
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">public</span> java.<span style="color:#a6e22e">lang</span>.<span style="color:#a6e22e">String</span> <span style="color:#a6e22e">name</span>();
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">public</span> House <span style="color:#a6e22e">house</span>();
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>In a nutshell, these are some of the important aspects of records:</p>
<ul>
<li>a record is a final class (=&gt; a record cannot be abstract)</li>
<li>fields are private and final</li>
<li>it already extends the <code>Record</code> class, so you cannot have a record extend any other classes</li>
<li>it cannot be extended by any other class</li>
<li>it can implement interfaces</li>
<li>we have the canonical constructor taking in a string and an enum, matching the given components</li>
<li>an extra constructor can be added, the <em>compact constructor</em>, which is typically used to validate the arguments</li>
<li>we can replace the canonical constructor with a normal constructor, but its signature must <em>exactly</em> duplicate the signature of the record including the identifier names</li>
<li>we have the accessors (no more in the JavaBean style)</li>
<li>we have the <code>equals()</code>, <code>hashCode()</code> and <code>toString()</code> methods</li>
<li>the only way to add fields to a record is by defining them in the header, however static methods, fields and initializers are allowed</li>
</ul>
<h3 id="better-nullpointerexception-reporting">Better NullPointerException Reporting</h3>
<p>Another improvement, which was finalized in Java 15, concerns the error message we see when a NPE hits us. Before, we would have just seen a rather poor message, something along the lines of <code>java.lang.NullPointerException</code>, with no indications as to why it happens. The new message offers us more information, so in the case of a chain like this <code>a.b.c</code>, where <code>b</code> is <code>null</code>, we would get something like: <code>java.lang.NullPointerException: Cannot read field &quot;c&quot; because &quot;...b&quot; is null</code>. This makes it significantly easier to understand and resolve such exceptions.</p>
<h3 id="text-blocks">Text Blocks</h3>
<p>Java 15 also brought us text blocks, which is a feature lifted from the Python language. Triple quotes denote a block of text including newlines. We can now write something like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> content <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;&#34;&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    {
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        &#34;key1&#34;:&#34;value1&#34;,
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        &#34;key2&#34;:&#34;value2&#34;,
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    }&#34;&#34;&#34;</span>;
</span></span><span style="display:flex;"><span>System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(content);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> sameContent <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;{\n&#34;</span> <span style="color:#f92672">+</span>
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;    \&#34;key1\&#34;:\&#34;value1\&#34;,\n&#34;</span> <span style="color:#f92672">+</span>
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;    \&#34;key2\&#34;:\&#34;value2\&#34;,\n&#34;</span> <span style="color:#f92672">+</span>
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;}&#34;</span>;
</span></span><span style="display:flex;"><span>System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(content.<span style="color:#a6e22e">equals</span>(sameContent)); <span style="color:#75715e">// =&gt; true</span>
</span></span></code></pre></div><p>This produces:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    &#34;key1&#34;:&#34;value1&#34;,
</span></span><span style="display:flex;"><span>    &#34;key2&#34;:&#34;value2&#34;,
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Before Java 15 that code requires a lot of string concatenation and newlines to get the same result. For longer texts it is even more complicated to work with. Notice that the newline after the first <code>&quot;&quot;&quot;</code> is automatically removed, and the final <code>&quot;&quot;&quot;</code> is placed on the same line and directly after the closing <code>}</code> of the json, this is so to prevent another newline.</p>
<p>Starting with the same version, the string objects have a <code>formatted()</code> method, which we can use the same way as <code>String.format()</code>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span>System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(<span style="color:#e6db74">&#34;&#34;&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        name: %s
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        profession: %s&#34;&#34;&#34;</span>.<span style="color:#a6e22e">formatted</span>(<span style="color:#e6db74">&#34;Vlad&#34;</span>, <span style="color:#e6db74">&#34;Software Engineer&#34;</span>));
</span></span></code></pre></div><p>which produces:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>name: Vlad
</span></span><span style="display:flex;"><span>profession: Software Engineer
</span></span></code></pre></div><p>Same result can be produced by using the <code>printf</code> method instead of the <code>println</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span>System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">printf</span>(<span style="color:#e6db74">&#34;&#34;&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        name: %s
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        profession: %s%n&#34;&#34;&#34;</span>, <span style="color:#e6db74">&#34;Vlad&#34;</span>, <span style="color:#e6db74">&#34;Software Engineer&#34;</span>);
</span></span></code></pre></div><p>As you can see, Java is making progress rapidly and brings in features which ease the programmer&rsquo;s work and make the language overall more appealing to learn and use. There is a lot of work happening right now, Java 18 is already out, with 19 coming in autumn this year. Besides Amber, other Java projects, <a href="https://wiki.openjdk.org/display/loom/Main" target="_blank">Loom</a>, <a href="https://openjdk.org/projects/valhalla/" target="_blank">Valhalla</a>, <a href="https://openjdk.org/projects/panama/" target="_blank">Panama</a>, promise a lot more and will make the language even more appealing and worth learning it.</p>
]]></content>
        </item>
        
        <item>
            <title>Learning Python as a Java developer - 1/</title>
            <link>https://vladflore.tech/posts/2022/07/learning-python-as-a-java-developer-1/</link>
            <pubDate>Sat, 16 Jul 2022 00:00:00 +0000</pubDate>
            
            <guid>https://vladflore.tech/posts/2022/07/learning-python-as-a-java-developer-1/</guid>
            <description>&lt;h2 id=&#34;becoming-a-pythonista&#34;&gt;Becoming a Pythonista&lt;/h2&gt;
&lt;p&gt;If the term &amp;ldquo;pythonista&amp;rdquo; seems unusual or off-putting to you, rest assured that you are not the only one. Personally, I find the word somewhat amusing, and I had to &lt;a href=&#34;https://en.wiktionary.org/wiki/Pythonista&#34; target=&#34;_blank&#34;&gt;look it up&lt;/a&gt; initially. After all, &amp;ldquo;Python programmer&amp;rdquo; or &amp;ldquo;Python software engineer&amp;rdquo; would suffice, right? Regardless, this post is not about what we call individuals who work with Python; rather, it&amp;rsquo;s about sharing my experience of learning Python as a Java software engineer.&lt;/p&gt;</description>
            <content type="html"><![CDATA[<h2 id="becoming-a-pythonista">Becoming a Pythonista</h2>
<p>If the term &ldquo;pythonista&rdquo; seems unusual or off-putting to you, rest assured that you are not the only one. Personally, I find the word somewhat amusing, and I had to <a href="https://en.wiktionary.org/wiki/Pythonista" target="_blank">look it up</a> initially. After all, &ldquo;Python programmer&rdquo; or &ldquo;Python software engineer&rdquo; would suffice, right? Regardless, this post is not about what we call individuals who work with Python; rather, it&rsquo;s about sharing my experience of learning Python as a Java software engineer.</p>
<p>First and foremost, I want to clarify that my intention is <em>not</em> to ignite or fuel a language debate, such as Java versus Python. Instead, my sole purpose is to share my experience and perspective on learning a new programming language, particularly Python, while coming from a Java background.</p>
<p>So, why am I (re)learning Python? The brief answer is that my current company is shifting its focus and has chosen to utilize Python more extensively for product development. As a result, I have the opportunity to use Python in a more professional capacity than before, which is exciting! A more detailed explanation is that Python is predominantly used in Machine Learning and Data Science—both fields that have captured my interest. Moreover, as a general-purpose language, Python can be used for a wide range of applications, making it a valuable skill to possess.</p>
<p>In fact, this isn&rsquo;t my first encounter with Python; I experimented with it a few years ago, specifically in early 2020, and have dabbled in it occasionally since then. I completed the Coursera Specialization <a href="https://coursera.org/verify/specialization/TWKG5SP5EL2D" target="_blank">Python for Everybody</a> and two edX courses: <a href="https://courses.edx.org/certificates/4b0e39182943413288e993b649c4707b" target="_blank">Introduction to Computer Science and Programming Using Python</a> and <a href="https://courses.edx.org/certificates/cf27f5b0da8540c2bab57360c838a8c0" target="_blank">Introduction to Computational Thinking and Data Science</a>.Additionally, I tackled coding tasks on <a href="https://exercism.org" target="_blank">Exercism</a> and <a href="https://www.codewars.com/" target="_blank">Codewars</a> from time to time. Recently, I began participating in the <a href="https://adventofcode.com/" target="_blank">Advent of Code</a> challenges, which I plan to solve using various programming languages. Python was chosen for the year 2015, the inaugural event in the AoC series. I&rsquo;m eager to see how it unfolds!</p>
<p>Currently, as I transition from casually experimenting with Python to utilizing it professionally, I am enrolled in Udacity&rsquo;s <a href="https://www.udacity.com/course/intermediate-python-nanodegree--nd303" target="_blank"> Intermediate Python Nanodegree</a>. The best part is that I have the opportunity to learn Python while working. It&rsquo;s fantastic!</p>
<h2 id="first-impressions">First impressions</h2>
<p>My initial impression of Python was that it&rsquo;s a straightforward, succinct language that doesn&rsquo;t require much ceremony. A typical example you might come across is the following:</p>
<h3 id="print-hello-world-in-python-vs-java">Print &lsquo;Hello, World!&rsquo; in Python vs. Java</h3>
<p>This is how it looks in Java(this code goes into <code>HelloWorld.java</code> file):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">HelloWorld</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">main</span>(String args<span style="color:#f92672">[]</span>) {
</span></span><span style="display:flex;"><span>        System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(<span style="color:#e6db74">&#34;Hello, World!&#34;</span>);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Then you do: <code>javac HelloWorld.java</code> and <code>java HelloWorld</code> or <code>java HelloWorld.java</code> and you get the greeting.</p>
<p>This is how it looks in Python(this code goes into <code>hello-python.py</code>):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>print(<span style="color:#e6db74">&#39;Hello, World!&#39;</span>)
</span></span></code></pre></div><p>Then you do: <code>python3 hello-world.py</code> and you get the greeting.</p>
<p>As you can see, the Java code appears more complex compared to the Python code. While the Java code will work as is, it requires a fair amount of prerequisite knowledge to fully comprehend what&rsquo;s happening. Here are some key points to consider:</p>
<ul>
<li>the class must be defined as <code>public</code> within a file with the same name and a <code>.java</code> extension. You can only have one public class in this file.</li>
<li>if the class is not public, the names can differ, and you can have multiple such classes within the same file.</li>
<li>to compile, use <code>javac A.java</code> and to run, use <code>java A</code>. Newer versions of Java can compile and run in one command, i.e., <code>java A.java</code>, but this introduces other interesting aspects.</li>
<li>the required method definition is <code>public static void main(String args[])</code>; otherwise, the code will not execute. You can replace <code>args</code> with another valid name.</li>
<li>the code includes a <code>System.out</code> statement.</li>
<li>after compiling, you may notice a <code>HelloWorld.class</code> file. Do not look inside it! This file contains the bytecode generated after using <code>javac</code> on your Java file. The Java Virtual Machine runs this bytecode, translating it into machine code.</li>
</ul>
<p>As you can see, the code is quite dense! As a programmer, if your goal is simply to print a line of text, Python offers a straightforward approach, whereas Java introduces more ceremony to achieve the same result.</p>
<p>This comparison is somewhat unfair since Java requires a class for the code to function. Therefore, it would be more reasonable to examine how Python code would appear when implementing the same functionality within a class.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Greeting</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">__init__</span>(self) <span style="color:#f92672">-&gt;</span> <span style="color:#66d9ef">None</span>:
</span></span><span style="display:flex;"><span>        print(<span style="color:#e6db74">&#39;Hello, World!&#39;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> __name__ <span style="color:#f92672">==</span> <span style="color:#e6db74">&#39;__main__&#39;</span>:
</span></span><span style="display:flex;"><span>    Greeting()
</span></span></code></pre></div><p>Now we begin to see a similar level of ceremony, albeit somewhat more cryptic. Some aspects that I find confusing include the unusual <code>if</code> statement with the <code>__thing__</code> construct and the use of <code>self</code> in the <code>__init__</code> method.</p>
<p>The <code>if</code> statement, which is outside the class (note the indentation, as Python uses it to delimit blocks of code), prevents the instantiation of the class (i.e., executing the <code>__init__</code> method) and thus the printing of the greeting when the class is used in another Python file. However, when we run the file using the Python interpreter (i.e., <code>python3 my-file.py</code>), it reads the file from top to bottom, encounters the <code>if</code> statement at the bottom, and the condition evaluates to <code>True</code>, leading to the class instantiation. This occurs because the special variable <code>__name__</code> is set to <code>__main__</code> internally. By the way, the double underscore <code>__</code> is referred to as a &ldquo;dunder&rdquo;, which stands for <em>d</em>ouble <em>under</em>score.</p>
<p>Interestingly, the <code>self</code> parameter can be named differently, and the code will still function. However, it is conventional to use the term <code>self</code>. Furthermore, it appears that numerous conventions should be considered when writing Python code. We will delve into these conventions in upcoming posts.</p>
<p>We could also remove the <code>-&gt; None</code> portion in the method definition, as it simply specifies the return type, which in this case is <code>None</code>, meaning nothing is returned. However, it seems that people have embraced the statically typed approach when writing Python code. Another notable difference is that instantiating an object in Python doesn&rsquo;t require the <code>new</code> keyword, as Java does. This leads to less typing.</p>
<p>Python is more lenient with the use of double <code>&quot;</code> and single <code>'</code> quotes, allowing them to be used interchangeably — i.e., &ldquo;Hello&rdquo; and &lsquo;Hello&rsquo; are considered the same. Java, on the other hand, does not permit such flexibility.</p>
<p>As illustrated by these small examples, Python is less verbose and more adaptable than Java. In future posts, we&rsquo;ll explore situations where Java code may require significantly more lines than Python. This conciseness also makes Python an appealing choice for coding interviews.</p>
<p>Another point worth mentioning is Java&rsquo;s commitment to backward compatibility. As a result, you&rsquo;re less likely to encounter breaking changes in Java compared to Python. A simple example of this is the <code>print</code> function in Python version 3+ versus versions 2.x:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>print(<span style="color:#e6db74">&#39;Hi there!&#39;</span>) <span style="color:#75715e"># 3+</span>
</span></span><span style="display:flex;"><span>print <span style="color:#e6db74">&#34;Hi&#34;</span>, <span style="color:#e6db74">&#34;there!&#34;</span> <span style="color:#75715e"># 2.x</span>
</span></span></code></pre></div><p>This post marks the beginning of a series dedicated to exploring the process of learning Python from the perspective of a Java developer. If you&rsquo;re interested in the other parts of this series, you can find them below:</p>
<ul>
<li><a href="https://vladflore.tech/posts/2023/06/learning-python-as-a-java-developer-2/">part two</a></li>
</ul>
]]></content>
        </item>
        
        <item>
            <title>Git Animated 4</title>
            <link>https://vladflore.tech/posts/2021/12/git-animated-4/</link>
            <pubDate>Thu, 23 Dec 2021 00:00:00 +0000</pubDate>
            
            <guid>https://vladflore.tech/posts/2021/12/git-animated-4/</guid>
            <description>&lt;p&gt;This is the forth video in the &lt;strong&gt;Git Animated&lt;/strong&gt; series.
If you are interested in the other ones, check the links below:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://vladflore.tech/posts/2021/08/git-animated-1/&#34;&gt;part one&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://vladflore.tech/posts/2021/08/git-animated-2/&#34;&gt;part two&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://vladflore.tech/posts/2021/09/git-animated-3/&#34;&gt;part three&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://vladflore.tech/posts/2026/03/git-animated-5/&#34;&gt;part five&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Another way of integrating changes of a branch into another one is by performing a &lt;strong&gt;rebase&lt;/strong&gt;. Instead of creating a new merge commit, as it happens when we &lt;strong&gt;merge&lt;/strong&gt; two histories, a rebase will change the base of a branch from one commit to another. Changing the base of a branch means changing the commit that branch was created from to be some other commit.&lt;/p&gt;</description>
            <content type="html"><![CDATA[<p>This is the forth video in the <strong>Git Animated</strong> series.
If you are interested in the other ones, check the links below:</p>
<ul>
<li><a href="https://vladflore.tech/posts/2021/08/git-animated-1/">part one</a></li>
<li><a href="https://vladflore.tech/posts/2021/08/git-animated-2/">part two</a></li>
<li><a href="https://vladflore.tech/posts/2021/09/git-animated-3/">part three</a></li>
<li><a href="https://vladflore.tech/posts/2026/03/git-animated-5/">part five</a></li>
</ul>
<p>Another way of integrating changes of a branch into another one is by performing a <strong>rebase</strong>. Instead of creating a new merge commit, as it happens when we <strong>merge</strong> two histories, a rebase will change the base of a branch from one commit to another. Changing the base of a branch means changing the commit that branch was created from to be some other commit.</p>
<p>In the animation we change the original base of <code>feature</code>, the commit <code>M2</code>, to be <code>M3</code>. Performing this action has the effect of integrating the changes introduced by <code>M3</code> into the <code>feature</code> branch, together with whatever the <code>feature</code> branch already had on it. As you may observe, this action does not produce a new commit containing the changes of both the <code>master</code> and <code>feature</code> branches, rather it creates three new commits, <code>F'0</code>, <code>F'1</code>, <code>F'2</code>, which content-wise are identical to the commits <code>F0</code>, <code>F1</code>, <code>F2</code>, and sticks them after the commit <code>M3</code>. This way, the <code>feature</code> branch contains the changes introduced by the commit <code>M3</code> too.</p>
<p>Observe that the <code>master</code> branch is still behind and knows nothing of the new commits. To bring <code>master</code> up-to-date too, one needs to perform a <em>fast-forward</em> merge of the feature into master, which in this case just means to move the <code>master</code> pointer to point to the last <code>F'2</code> commit.</p>
<p>Note also, that the original commits of <code>feature</code> branch (<code>F0</code>, <code>F1</code>, <code>F2</code>), if not &ldquo;revived&rdquo;, will be eventually garbage-collected.</p>
<p>Hopefully this animation conveys some intuition on what happens when we rebase a branch onto another.</p>
<p>For your convenience, here are the Git commands which appear in the video:</p>
<pre tabindex="0"><code>git commit -m &#39;M0&#39;
git commit -m &#39;M1&#39;
git commit -m &#39;M2&#39;
git branch feature
git checkout feature
git commit -m &#39;F0&#39;
git commit -m &#39;F1&#39;
git commit -m &#39;F2&#39;
git checkout master
git commit -m &#39;M3&#39;
git checkout feature
git rebase master
</code></pre><p>Here is the video(there is no audio):</p>
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
      <iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/mD_58aLFz_8?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"></iframe>
    </div>

<!-- raw HTML omitted -->
<p>Feel free to drop me a comment or e-mail with your constructive criticism. It will be much appreciated!</p>
<p>Enjoy!</p>
]]></content>
        </item>
        
        <item>
            <title>Git Animated 3</title>
            <link>https://vladflore.tech/posts/2021/09/git-animated-3/</link>
            <pubDate>Sun, 05 Sep 2021 00:00:00 +0000</pubDate>
            
            <guid>https://vladflore.tech/posts/2021/09/git-animated-3/</guid>
            <description>&lt;p&gt;This is the third video in the &lt;strong&gt;Git Animated&lt;/strong&gt; series.
If you are interested in the other ones, check the links below:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://vladflore.tech/posts/2021/08/git-animated-1/&#34;&gt;part one&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://vladflore.tech/posts/2021/08/git-animated-2/&#34;&gt;part two&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://vladflore.tech/posts/2021/12/git-animated-4/&#34;&gt;part four&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://vladflore.tech/posts/2026/03/git-animated-5/&#34;&gt;part five&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this video we will merge two histories, &lt;code&gt;master&lt;/code&gt; and &lt;code&gt;feature&lt;/code&gt;, which have diverged at commit &lt;code&gt;M2&lt;/code&gt;.
As each of the branches got new commits from that divergent point, the feature branch cannot be integrated
into the master branch using a fast-forward approach.&lt;/p&gt;</description>
            <content type="html"><![CDATA[<p>This is the third video in the <strong>Git Animated</strong> series.
If you are interested in the other ones, check the links below:</p>
<ul>
<li><a href="https://vladflore.tech/posts/2021/08/git-animated-1/">part one</a></li>
<li><a href="https://vladflore.tech/posts/2021/08/git-animated-2/">part two</a></li>
<li><a href="https://vladflore.tech/posts/2021/12/git-animated-4/">part four</a></li>
<li><a href="https://vladflore.tech/posts/2026/03/git-animated-5/">part five</a></li>
</ul>
<p>In this video we will merge two histories, <code>master</code> and <code>feature</code>, which have diverged at commit <code>M2</code>.
As each of the branches got new commits from that divergent point, the feature branch cannot be integrated
into the master branch using a fast-forward approach.</p>
<p>Git will take the two commit pointers(<code>M3</code> and <code>F2</code>) and attempt to find a common base commit, <code>M2</code>, between them.
Git has several different methods to find a base commit, these methods are called <em>merge strategies</em>.
Once Git finds a common base commit it will create a new <em>merge commit</em>, <code>MF</code>, that combines the changes of the specified merge commits.
Technically, a merge commit is a regular commit which just happens to have two parent commits.</p>
<p><code>git merge</code> will automatically select a merge strategy unless explicitly specified (for instance using the <code>-s</code> option).</p>
<p>One of the merge strategies Git uses is the <em>recursive strategy</em>, this is the default merge strategy when pulling or merging one branch.
If you are interested in finding more about merge strategies, check the following <a href="https://git-scm.com/docs/git-merge" target="_blank">link</a>.</p>
<p>Hopefully this animation conveys some intuition on what happens when we merge two histories.</p>
<p>For your convenience, here are the Git commands which appear in the video:</p>
<pre tabindex="0"><code>git commit -m &#39;M0&#39;
git commit -m &#39;M1&#39;
git commit -m &#39;M2&#39;
git branch feature
git checkout feature
git commit -m &#39;F0&#39;
git commit -m &#39;F1&#39;
git commit -m &#39;F2&#39;
git checkout master
git commit -m &#39;M3&#39;
git merge feature
git branch -d feature
</code></pre><p>Here is the video(there is no audio):</p>
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
      <iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/Tmfz3nN992k?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"></iframe>
    </div>

<!-- raw HTML omitted -->
<p>Feel free to drop me a comment or e-mail with your constructive criticism. It will be much appreciated!</p>
<p>Enjoy!</p>
]]></content>
        </item>
        
        <item>
            <title>Git Animated 2</title>
            <link>https://vladflore.tech/posts/2021/08/git-animated-2/</link>
            <pubDate>Sun, 15 Aug 2021 00:00:00 +0000</pubDate>
            
            <guid>https://vladflore.tech/posts/2021/08/git-animated-2/</guid>
            <description>&lt;p&gt;This is the second video in the &lt;strong&gt;Git Animated&lt;/strong&gt; series.
If you are interested in the other ones, check the links below:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://vladflore.tech/posts/2021/08/git-animated-1/&#34;&gt;part one&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://vladflore.tech/posts/2021/09/git-animated-3/&#34;&gt;part three&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://vladflore.tech/posts/2021/12/git-animated-4/&#34;&gt;part four&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://vladflore.tech/posts/2026/03/git-animated-5/&#34;&gt;part five&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this video you will see what happens when we merge two histories, specifically merging &lt;code&gt;feature&lt;/code&gt; into &lt;code&gt;master&lt;/code&gt;. The thing to note here is that the merge is a fast-forward one, this is possible when there are no further commits on the branch we branched off of, after the point of creating the new branch (in our case on the branch &lt;code&gt;master&lt;/code&gt; after commit &lt;code&gt;M2&lt;/code&gt;).&lt;/p&gt;</description>
            <content type="html"><![CDATA[<p>This is the second video in the <strong>Git Animated</strong> series.
If you are interested in the other ones, check the links below:</p>
<ul>
<li><a href="https://vladflore.tech/posts/2021/08/git-animated-1/">part one</a></li>
<li><a href="https://vladflore.tech/posts/2021/09/git-animated-3/">part three</a></li>
<li><a href="https://vladflore.tech/posts/2021/12/git-animated-4/">part four</a></li>
<li><a href="https://vladflore.tech/posts/2026/03/git-animated-5/">part five</a></li>
</ul>
<p>In this video you will see what happens when we merge two histories, specifically merging <code>feature</code> into <code>master</code>. The thing to note here is that the merge is a fast-forward one, this is possible when there are no further commits on the branch we branched off of, after the point of creating the new branch (in our case on the branch <code>master</code> after commit <code>M2</code>).</p>
<p>Additionally, after <code>feature</code> has been successfully merged into <code>master</code>, we delete the <code>feature</code> branch, this is not a must, but is a good practice to keep your repository clean.</p>
<p>Hopefully this animation conveys some intuition on what happens when we merge two histories using the fast-forward strategy.</p>
<p>For your convenience, here are the Git commands which appear in the video:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>git commit -m <span style="color:#e6db74">&#39;M0&#39;</span>
</span></span><span style="display:flex;"><span>git commit -m <span style="color:#e6db74">&#39;M1&#39;</span>
</span></span><span style="display:flex;"><span>git commit -m <span style="color:#e6db74">&#39;M2&#39;</span>
</span></span><span style="display:flex;"><span>git branch feature
</span></span><span style="display:flex;"><span>git checkout feature
</span></span><span style="display:flex;"><span>git commit -m <span style="color:#e6db74">&#39;F0&#39;</span>
</span></span><span style="display:flex;"><span>git commit -m <span style="color:#e6db74">&#39;F1&#39;</span>
</span></span><span style="display:flex;"><span>git commit -m <span style="color:#e6db74">&#39;F2&#39;</span>
</span></span><span style="display:flex;"><span>git checkout master
</span></span><span style="display:flex;"><span>git merge feature
</span></span><span style="display:flex;"><span>git branch -d feature
</span></span></code></pre></div><p>Here is the video(there is no audio):</p>
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
      <iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/wHSZ70Pi0iE?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"></iframe>
    </div>

<!-- raw HTML omitted -->
<p>Feel free to drop me a comment or e-mail with your constructive criticism. It will be much appreciated!</p>
<p>Enjoy!</p>
]]></content>
        </item>
        
        <item>
            <title>Git Animated 1</title>
            <link>https://vladflore.tech/posts/2021/08/git-animated-1/</link>
            <pubDate>Sun, 01 Aug 2021 00:00:00 +0000</pubDate>
            
            <guid>https://vladflore.tech/posts/2021/08/git-animated-1/</guid>
            <description>&lt;p&gt;Welcome to the first post and first video of the video series &lt;strong&gt;Git Animated&lt;/strong&gt;.
With this series I am trying to visually depict how different Git commands and actions look like, basically what happens behind them when you execute them.&lt;/p&gt;
&lt;p&gt;If you are interested in the other videos, please check the links below:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://vladflore.tech/posts/2021/08/git-animated-2/&#34;&gt;part two&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://vladflore.tech/posts/2021/09/git-animated-3/&#34;&gt;part three&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://vladflore.tech/posts/2021/12/git-animated-4/&#34;&gt;part four&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://vladflore.tech/posts/2026/03/git-animated-5/&#34;&gt;part five&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note: if you are a software engineer and have never heard of Git, then this post, and the future ones, are not for you&amp;hellip;and I am also sorry for you!&lt;/p&gt;</description>
            <content type="html"><![CDATA[<p>Welcome to the first post and first video of the video series <strong>Git Animated</strong>.
With this series I am trying to visually depict how different Git commands and actions look like, basically what happens behind them when you execute them.</p>
<p>If you are interested in the other videos, please check the links below:</p>
<ul>
<li><a href="https://vladflore.tech/posts/2021/08/git-animated-2/">part two</a></li>
<li><a href="https://vladflore.tech/posts/2021/09/git-animated-3/">part three</a></li>
<li><a href="https://vladflore.tech/posts/2021/12/git-animated-4/">part four</a></li>
<li><a href="https://vladflore.tech/posts/2026/03/git-animated-5/">part five</a></li>
</ul>
<p>Note: if you are a software engineer and have never heard of Git, then this post, and the future ones, are not for you&hellip;and I am also sorry for you!</p>
<h3 id="the-motivation-behind">The motivation behind</h3>
<p>From my experience I can tell that people have this tendency to take things for granted, and software engineers are no exception to this. One of the things they take for granted is Git&hellip;specifically the way to use it. This might not sound so terrible, but on the long run it has some devastating effects.</p>
<p>I was also one of those people, who initially took Git for granted, and by that I mean, I learned some basic Git terminology, some basic commands and I got away with that for some time. As I was using different IDEs, which come with very good support for Git, I didn&rsquo;t have to bother understanding what actually happened when I wrote those commands or clicked those buttons in the IDE&hellip;stuff just worked.</p>
<p>As I was using Git more and more from the command line, I started to ask myself what actually happens when I type all those commands and hit the enter key. Another good motivator was the problems I got into, or stumbled upon, which I had a hard time fixing. You know what they say, <em>read the fu**ing documentation</em>, and so I started to pay more attention to what is happening behind the curtain.</p>
<p>Fast-forward to these days, I got into another situation, where I had all sorts of Git related problems, the other team members didn&rsquo;t. This motivated me to really have a look at how things are working and to really understand the magic behind Git and its features. This is a work in progress, and it may still be for the months to come, but the more I read, the thinner the fog&hellip;</p>
<p>As I usually like teaching others about stuff, I said to myself it would be nice to create some content others might benefit of. A textual explanation is good, a static visual one is better, but a dynamic visual one is the best. So I started creating some videos.</p>
<h3 id="git-animated">Git Animated</h3>
<p>The videos in this series are created using the open source Python library <a href="https://github.com/ManimCommunity/manim" target="_blank">ManimCE</a>. You read that right, I write Python code, which generates the videos, I can only hope you would enjoy.</p>
<p>The audience of these videos is made of people who have worked before with Git, and who want to either deepen their knowledge or brush-up on some concepts/commands.</p>
<p>The first video is about initializing a local Git repository, creating a bunch of commits, creating a new branch and some more commits on it. Hopefully it conveys some intuition on what happens when all those commands , displayed on the left side of the screen, are executed.</p>
<p>For your convenience, you can find below the Git commands which appear in the video:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>git init
</span></span><span style="display:flex;"><span>git commit -m <span style="color:#e6db74">&#39;M0&#39;</span>
</span></span><span style="display:flex;"><span>git commit -m <span style="color:#e6db74">&#39;M1&#39;</span>
</span></span><span style="display:flex;"><span>git commit -m <span style="color:#e6db74">&#39;M2&#39;</span>
</span></span><span style="display:flex;"><span>git branch feature
</span></span><span style="display:flex;"><span>git checkout feature
</span></span><span style="display:flex;"><span>git commit -m <span style="color:#e6db74">&#39;F0&#39;</span>
</span></span><span style="display:flex;"><span>git commit -m <span style="color:#e6db74">&#39;F1&#39;</span>
</span></span><span style="display:flex;"><span>git commit -m <span style="color:#e6db74">&#39;F2&#39;</span>
</span></span></code></pre></div><p>Here is the video(there is no audio):</p>
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
      <iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/3BlX1IiKqm8?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"></iframe>
    </div>

<!-- raw HTML omitted -->
<h3 id="online-resources-to-learn-git">Online resources to learn Git</h3>
<ul>
<li><a href="https://git-scm.com/docs" target="_blank">Git reference documentation</a></li>
<li><a href="https://git-scm.com/book/en/v2" target="_blank">Pro Git book</a></li>
<li><a href="https://www.coursera.org/learn/version-control-with-git" target="_blank">Coursera version control with Git</a></li>
<li><a href="https://missing.csail.mit.edu/2020/version-control/" target="_blank">Lecture on Version Control by &ldquo;Missing Semester&rdquo; CSAIL MIT</a></li>
</ul>
<p>Feel free to drop me a comment or e-mail with your constructive criticism. It will be much appreciated!</p>
<p>Enjoy!</p>
]]></content>
        </item>
        
        <item>
            <title>My first OSS PR</title>
            <link>https://vladflore.tech/posts/2021/07/my-first-oss-pr/</link>
            <pubDate>Thu, 15 Jul 2021 00:00:00 +0000</pubDate>
            
            <guid>https://vladflore.tech/posts/2021/07/my-first-oss-pr/</guid>
            <description>&lt;p&gt;Software developers write code&amp;hellip;or at least they should, provided they can escape the long boring meetings which finish with no conclusions or, God forbid, with the next appointment&amp;hellip;to discuss more.&lt;/p&gt;
&lt;p&gt;When we monetize this action of writing code, we usually do it as part of a job, which comes with its pros and cons, and such we have to stay in the legal framework of that working contract. This legal framework might very well prevent us from contributing to Open Source Software(OSS), so make sure to read the fine print!&lt;/p&gt;</description>
            <content type="html"><![CDATA[<p>Software developers write code&hellip;or at least they should, provided they can escape the long boring meetings which finish with no conclusions or, God forbid, with the next appointment&hellip;to discuss more.</p>
<p>When we monetize this action of writing code, we usually do it as part of a job, which comes with its pros and cons, and such we have to stay in the legal framework of that working contract. This legal framework might very well prevent us from contributing to Open Source Software(OSS), so make sure to read the fine print!</p>
<p>Other than that, we do not get the chance to work with technologies we might want to get ourselves more familiar with, and this makes sense, but what if you <em>really</em> want to?</p>
<p><a href="https://en.wikipedia.org/wiki/Open-source_software" target="_blank">Open Source Software</a> for the win!</p>
<p>Contributing to OSS can be a daunting business, especially if the thing you want to contribute to is well known, is maintained by many developers, is under heavy development, or is just complex. Nonetheless you can still contribute!</p>
<p>In my case, I took on a <em>good first issue</em> in a project hosted on GitHub called <a href="https://github.com/fonsp/Pluto.jl" target="_blank">Pluto.jl</a>, which is, as its owner describes it, <em>simple reactive notebooks for Julia</em>.</p>
<p>What&rsquo;s Julia, you ask?</p>
<p>Well, for the impatient, it is a fast, dynamic, reproducible, composable, general, open source programming language, with an ecosystem covering visualization, data science, machine learning, scientific domains, parallel computing and, of course, general purpose development <em>and</em> web development. For the curious, check <a href="https://julialang.org/" target="_blank">julialang.org</a>.</p>
<p>Coming back to the OSS project, my contribution was more of an esthetic one, changing the way a set data structure is rendered, specifically displaying its elements in a chunk-wise manner. This change involved writing some Julia code, some React/JavaScript code and some HTML and CSS code.</p>
<p>It&rsquo;s important to mention, that Julia is not my main programming language, I did <em>meet</em> Julia in late 2020, but didn&rsquo;t do any serious development in it, and neither is React as a JavaScript framework. Nevertheless, I was able to implement the change and <a href="https://github.com/fonsp/Pluto.jl/pull/926" target="_blank">get it accepted into the main branch, which got released shortly after</a>.</p>
<p>I mentioned above, that contributing to OSS can be a daunting business, but, despite that, there are still ways to make the process more comfortable, here is how you could do it:</p>
<ul>
<li>improve the documentation, by correcting typos, adding examples, explaining notions in a clearer way etc.</li>
<li>improve the code coverage</li>
<li>go for the issues, which are labeled with <em>good first issue</em>, the Pluto.jl repository uses this label to let people know of stuff which can be worked on if you hadn&rsquo;t worked before on such projects</li>
<li>browse the issues and see if you can find one, which makes sense to you, without having to go into the eerie implementation details</li>
</ul>
<p>Start small and don&rsquo;t give up, keep persevering, and your <strong>first Pull Request(PR)</strong> will be accepted in no time.</p>
<p>Contributing to OSS, doesn&rsquo;t necessarily bring you money, but it does bring you experience, which you can eventually monetize. With a community as Pluto.jl has, you can get all the experience you need.</p>
<p>May your contributions be easily accepted and your work recognized!</p>
<p>Happy coding!</p>
]]></content>
        </item>
        
        <item>
            <title>Nine Months Later</title>
            <link>https://vladflore.tech/posts/2021/05/nine-months-later/</link>
            <pubDate>Fri, 07 May 2021 00:00:00 +0000</pubDate>
            
            <guid>https://vladflore.tech/posts/2021/05/nine-months-later/</guid>
            <description>&lt;p&gt;&amp;hellip;if you were thinking about screaming little humans, I am afraid I will disappoint you and it might be that this post is not for you.&lt;/p&gt;
&lt;p&gt;If you are still reading, then you might be one of those people, who thought of something else what could have happened in a period of nine months. I salute you and encourage you to read on!&lt;/p&gt;
&lt;p&gt;2020 was a special year, for the world and for me as well, on one side we had that &lt;em&gt;end of the world kind of global infestation&lt;/em&gt; thing, on the other side I managed to make some changes, which hopefully will pay-off in the near future, dare saying some of them have already payed-off.&lt;/p&gt;</description>
            <content type="html"><![CDATA[<p>&hellip;if you were thinking about screaming little humans, I am afraid I will disappoint you and it might be that this post is not for you.</p>
<p>If you are still reading, then you might be one of those people, who thought of something else what could have happened in a period of nine months. I salute you and encourage you to read on!</p>
<p>2020 was a special year, for the world and for me as well, on one side we had that <em>end of the world kind of global infestation</em> thing, on the other side I managed to make some changes, which hopefully will pay-off in the near future, dare saying some of them have already payed-off.</p>
<p>As of 01.06.2020 I joined the club of those unemployed, a.k.a I left the company I had been working for the last 12 years of my life and decided to take a well deserved break from that <em>nine to five&hellip;ish</em> lifestyle. I took that decision some time before the Coronavirus comfortably settled down to its new home&hellip;Europe, Germany.</p>
<p>Before you ask why I left the company after 12 years of employment, stay assured that&rsquo;s a whole new story, which might become a new <a href="">blog post</a> in the near future. It suffices to say that after 12 years it kind of became clear what the future had in store for me and that <em>that</em> wasn&rsquo;t compatible anymore with my aspirations.</p>
<p>At this point, you might think <em>ok, ok, no job, but definitely, already on the search for a new one, maybe even already employed, and if unemployed then definitely registered as such at the Federal Employment Agency, a.k.a, Bundesagentur für Arbeit, right?!?</em>. Well, no, and no!</p>
<p>To clarify the above a bit more, I didn&rsquo;t plan to immediately continue with working for a new employer, I did want to take time off and see to my own things, more on this a bit later on. As for the <em>gemeldet als arbeitslos</em> and hence, I guess, benefit from money support from the state, I just wasn&rsquo;t interested in that hassle. I had some savings and I was willing to use those to cover the payments I still had to make, including the health insurance, the pension insurance and other living expenses. This was and is a valid, legal way of taking time off from work, albeit a bit expensive (stuff paid by the employer, becomes your responsibility), and the employment agency doesn&rsquo;t need to know about it, except for their statistics, but other than that&hellip;no earnings, no taxes, except for health and pension.</p>
<p>Now, on to what I meant with <em>take time off and see to my own things</em>, initially it was planned as a period of resetting, contemplating the future, learning new things, focus on physical exercising, getting in shape, exploring the world and just recharging with positive energy, energy others feasted on while I was employed. Well, karma had other plans for the world and such I was more or less confined to my apartment and had to rethink my new, well deserved <em>freedom</em>.</p>
<p>I am a software engineer, I have the computer science education (bachelor and master) behind me, and I have been working in the field of web development, with a focus on backend, for <code>1100</code> years ;). As such, spending time in front of the laptop and doing geeky stuff fits like a glove, reason why turning to my trustworthy laptop and start diving into all sorts of IT related subjects was as natural as it could be!</p>
<p>Now, I need to mention, that I am not an expert in any of the subjects I will be mentioning below, but I am familiar with them, with some more than with others. This kind of immersion into different subjects is not an easy thing to do, and it will not make you an expert, it would be childish to say the opposite, it <strong>will</strong> broaden your knowledge though, maybe even deepen it, that&rsquo;s for sure, and this kind of horizontal expansion, as opposed to a vertical one, turned out to be exactly what I needed.</p>
<p>One more thing before going further, we, as software engineers, as <strong>responsible</strong> software engineers, need to constantly learn and hone our engineering skills, we need to stay on top of this never-ending and always evolving field of IT, otherwise we risk becoming obsolete, which means, we risk becoming unemployed. There is another aspect here, it has to do with one&rsquo;s comfort zone, and the idea of finding something that works for you, never gets obsolete, and sticking with it until you retire. That could also work, but it is definitely not my style. More on this in <a href="">a future blog post</a>.</p>
<p>This being said, here are some of the things I tackled and dedicated some time and attention to.</p>
<h2 id="blogging">Blogging</h2>
<p>I (re-)started with blogging at the beginning of 2020, it involved some work and getting accustomed to some new tools, but after figuring all that out, it felt, and still does, kind of natural. Because the design muses were absent at my birth, I decided to go with a default theme/look/design, that I could use with <a href="https://jekyllrb.com/" target="_blank">Jekyll</a>, I bought myself a domain, connected it with GitHub and voilà&hellip;you can read my thoughts!</p>
<p>Btw, writing is a time-consuming process and doesn&rsquo;t work all the time, if you add in the fact that I have little time for it, or would it rather be bad time management?!, one could easily understand why the blog is sort of&hellip;rarefied.</p>
<h2 id="programming-languages">Programming languages</h2>
<p>Aah, yes, programming languages, you know, those languages you use to tell a computer what to do&hellip;there are plenty of them out there, and it is my intention to learn them all&hellip;just kidding, ain&rsquo;t going to do that, although it surely sounds appealing.</p>
<p>I personally started with Pascal, this was in high school, then continued with C, C++ and C++ - - a.k.a. Java, at the university. There were some other languages along the way, but in the end Java stuck to me and remained one of my go-to languages when I wanted to make my computer do something for me&hellip;, and it also pays the bills, so yay Java.</p>
<p>Other than that, my appetite for other languages kind of grew bigger, and such I learned some Python, gave JavaScript another chance, started with Kotlin (I am using it at my current job), learned some Julia&hellip;and was getting very confused when I was switching between the languages.</p>
<p>Remember my go-to language, well, learned some more of it too, and got two certifications. This 25+ years old language is still in top 5 in the <a href="https://www.tiobe.com/tiobe-index/" target="_blank">TIOBE Programming Community index</a> and its two releases per year cadence makes things a bit more challenging to keep up with it&hellip;, but you know, bills are kind of important&hellip; :)</p>
<h2 id="the-art-of-writing-code">The art of writing code</h2>
<p>You know how they say, we write code for humans not for computers. While this is true, not many of us, those bestowed with understanding computer programs, really get the gist of it, in the end that code is intended to be understood by computers, rather than by humans&hellip;which complicates things for other&hellip;wait for it&hellip;humans!</p>
<p>Writing code in that way that you can say <em>it is for humans</em> is not necessarily an easy task to do, most of the time you get the algorithm working, it does what it is supposed to do, or at least it looks like it, and the next second you might think your job is done. NO! Your job is not done! Not by far, now you should make sure that the code is also written for your fellow programmers, colleagues or not.</p>
<p>There are all sorts of resources out there that can teach you how to properly write code, and I do not mean the syntax and how idiomatic your code is, while those are important aspects, obviously, there is more to writing code, than we might want to admit. It has to read like a poem, they say, it has to be a pleasure to work with. So <strong>stop</strong> doing the following, and you will be way ahead of others:</p>
<ul>
<li>mutilate names</li>
<li>use way too generic names for your functions and variables</li>
<li>cram in lots of functionality into a class or method</li>
<li>over-engineer code to the point the functionality you were implementing is not recognizable anymore</li>
<li>being ignorant to the surroundings of where you are touching some code a.k.a leave the campground cleaner than you found it</li>
</ul>
<p>Start with the above, and your fellow programmers will thank you.</p>
<h2 id="competitive-programming">Competitive programming</h2>
<p>Another thing I had no idea it existed, is competitive programming, I remember watching a YouTube video of some guy solving problems and writing code faster
than I can write normal English text. I cannot recall anymore how I got there, but I know I liked it and something in my mind was keep bugging me to learn more about it,
and so I did.</p>
<p>The thing is, that you cannot <em>just start</em> solving complex algorithmic problems, it requires months, maybe years of practice, and some serious algorithmic muscles.</p>
<p>All hyped as I was, I started looking around, googling about this thing, watching videos of others solving problems and took quite a serious interest into algorithms and data structures&hellip;
you kind of need them to be able to solve problems efficiently. There are lots of resources out there, one just needs the time, and the willingness to go through them.</p>
<p>Challenging yourself is a good thing, sometimes you will feel really smart, sometimes really dumb&hellip;just saying. Below are some online platforms where you can train/compete, and even make some money:</p>
<ul>
<li><a href="https://codeforces.com/" target="_blank">codeforces</a></li>
<li><a href="https://leetcode.com/" target="_blank">leetcode</a></li>
<li><a href="https://www.codewars.com/" target="_blank">codewars</a></li>
<li><a href="https://www.hackerrank.com/" target="_blank">hackerrank</a></li>
<li><a href="https://www.jetbrains.com/academy/" target="_blank">jetbrains academy</a></li>
<li><a href="https://adventofcode.com/" target="_blank">advent of code</a></li>
<li><a href="https://codingcompetitions.withgoogle.com/codejam" target="_blank">codejam</a></li>
</ul>
<h2 id="algorithms-and-data-structures">Algorithms and data structures</h2>
<p>You may like it, or you may hate it, but you need them! Any self-respecting software engineer should know some basics algorithms and data structures and should be prepared to look them up
either online or in some CS textbook. Internet has no shortage of information on them and people have created entire businesses around them, plus if you want to work at one of the FAANG(Facebook, Amazon, Apple, Netflix, Google) companies
you definitely need to be comfortable solving algorithmic problems.</p>
<p>Truth be told, if you do HTML and CSS you most likely do not need them, but as soon as you start writing code, you have to deal with algorithms,
maybe not with the complicated ones, but definitely with some common ones. In the end it depends on what you are doing as a software engineer.</p>
<p>Here the Internet is again full of resources, some of the most notable ones being:</p>
<ul>
<li><a href="https://www.coursera.org/learn/algorithms-part1" target="_blank">Coursera, Algorithms, Part 1</a></li>
<li><a href="https://www.coursera.org/learn/algorithms-part2" target="_blank">Coursera, Algorithms, Part 2</a></li>
<li><a href="https://www.coursera.org/specializations/algorithms" target="_blank">Coursera, Algorithms specialization</a></li>
</ul>
<h2 id="getting-comfortable-with-the-command-line">Getting comfortable with the command line</h2>
<p>The cool kids use the command line not the graphical user interface! Now you know!</p>
<p>If you are still reading, know that getting comfortable with the command line is not an easy thing. It has a lot of benefits and will make you look like a God, but it is not an easy thing to really master it.</p>
<p>Considering the learning curve, sometimes it might be better to just use the God damn mouse and click your way through all that. You will be doing it to the detriment of losing some popularity points, though.</p>
<p>In my attempt to master the command line, I renounced at Windows, installed a fresh copy of Ubuntu and started&hellip;clicking my way through it, I am kidding, diligently typing in commands
and hopping for the best. You should give it a try too!</p>
<h2 id="software-design-and-architecture">Software design and architecture</h2>
<p>As software developers we <em>still</em> get the chance to write code, if you are lucky enough and are not stuck in some meetings, that never seem to end. At some point in your career you may want to level up and start thinking about how to design and architect an application, or the code you are writing. There are good reasons to do that, I mean projects have failed because of bad architectures and designs, or at least swallowed way too much money than they should have.</p>
<p>Again, the Internet is full of resources about this subject, one of those is this <a href="https://www.coursera.org/specializations/software-design-architecture" target="_blank">Coursera specialization</a>.</p>
<p>I am strong believer of continuous improvement, as a professional, and as well as a human being. Online courses are, now more than never, in a boom, some are for free, some require some small payment, some cost quite a lot of money, but all of them can teach you something if you are willing to learn. So, learn! Invest in yourself!</p>
<h2 id="creating-a-portfolio--side-projects">Creating a portfolio / side projects</h2>
<p>In Romanian there is this saying, <em>teoria ca teoria, dar practica ne omoară</em>, which more or less translates to <em>theory is one thing, practice another</em>. Of course, you have to read, to inform yourself, to see what others think about something, but you also have to try things out, apply what you learned, build something.</p>
<p>Side projects are a good think, you get to build something, to apply what you learned, and you will eventually end up with a portfolio you can show off, but all of this requires time and effort. It is kind of a double-edged sword.</p>
<p>When looking for a new job, it is quite common to see that they are requiring from you to show them your portfolio, your GitHub account or similar. While this is fine, they should also understand that not having one, doesn&rsquo;t mean you are not capable of developing applications, writing code or solving problems, or that you are not interested into programming. Each and every one of us has their life, their time, and not having a GH profile doesn&rsquo;t make you any less capable or prepared to handle stuff.</p>
<p>I personally have a bunch of projects on GH, of all sorts, some bigger, some smaller, some I would show off, some not. It is rather a place to save the stuff I am working on, than something to show off. So, practice, build something, but do not obsess over it, live your life too, you only have one!</p>
<h2 id="frameworks-and-the-like-for-developing-web-applications">Frameworks and the like for developing web applications</h2>
<p>I have been in the field of developing web applications from the very beginning of my career life, in all sorts of capacities, so web application development is the field I know most, as opposed to, I don&rsquo;t know, compilers, desktop applications, machine learning and such.</p>
<p>I am mostly interested into Spring Framework and its plethora of projects, but as life has it, you do not always get to work with what you are interested into, I guess this depends entirely on you. Other than targeting the JVM environment, I worked with NodeJs and its ecosystem, mostly in my side projects or while going through some course or class or workshop. You can build some serious stuff with it, but I&rsquo;d rather prefer using Spring and remain in the JVM ecosystem - Java, Kotlin.</p>
<p>There are lots of other frameworks other than these two, it kind of depends on the main programming language you are using. Choose one or two and build something, get better at it and be curious&hellip;and patient&hellip;and resilient&hellip;frameworks and such tend to spring up like mushrooms after the rain.</p>
<h2 id="cloud">Cloud</h2>
<p>Yes, the Cloud, that thing which makes everybody&rsquo;s life easier, which looks cool on your CV, and promises lots of money. While that might be true, do not forget, it&rsquo;s more a case of passing on responsibilities to someone else, there are still some physical boxes stacked somewhere, as they say, it&rsquo;s just someone else&rsquo;s computer.</p>
<p>Cloud and cloud computing is not something of recent times, the idea kind of started around 1960-1970, with the mainframes, they didn&rsquo;t call it <em>cloud</em> back then, but it was, in its core, kind of similar to todays interpretation of the word. Cloud computing in its modern context occurred in 2006, check <a href="https://www.technologyreview.com/2011/10/31/257406/who-coined-cloud-computing/#:~:text=The%20notion%20of%20network-based,term%20to%20an%20industry%20conference." target="_blank">this link</a> for more on this.</p>
<p>Though I have heard about cloud, I didn&rsquo;t actually use it, up until like 3-4 years ago, when I became more aware of what Amazon is offering and what other competitors are pushing forward.</p>
<p>Fast-forward to last year, I started with an Udacity program, to learn more about what it means to be a cloud developer, and learn more about this piece of technology. I also have in plan to get some official recognition in this field, but firstly I need more knowledge and experience.</p>
<h2 id="machine-learning">Machine learning</h2>
<p>Machine learning, the cherry on the cake, the thing which could change our lives for better. Looking at the whole Artificial Intelligence domain, this ML subfield, draws a lot of attention and turns a lot of heads.</p>
<p>When it comes to AI, some say it is the future of humanity some that it is its doom. Believe what you want, this field is, in my opinion, GOD DAMN AWESOME!</p>
<p>I had my first encounter with AI while I was studying CS at the university, I did my master in Informatics with a focus on artificial intelligence and distributed computing, but that was pretty much it. I haven&rsquo;t actually applied it in real life, and have kind of lost contact with it.</p>
<p>Last year, 2020, the year of damnation, I took an interest into AI field in general and ML in particular. I had some time on my hands, so I decided to look more closely at it. OMG! I freaking love it! Sadly, it&rsquo;s not something to finish in a couple of days or weeks, it&rsquo;s a huge field in itself with educational programs and literature to consume and it is continuously evolving.</p>
<p>As always, there are tons of information out there, Universities have made public parts of their resources, courses, classes, programs and the like. I am particularly intrigued by MIT and Stanford, which offer some cool programs to start with, or dive even deeper into this field. Coursera has a bunch of courses and specializations on this too, and <em>new</em> programming languages emerge, promising better and faster implementation support for all those AI algorithms. Of course, the dominant language remains Python, but others are quite promising too.</p>
<p>Unfortunately, this field remains more of a hobby for me, than anything else. If I started with it, I&rsquo;d have to start from the very beginning. Maybe, I will be one of those web application developers turned into ML engineers&hellip;time will tell!</p>
<h2 id="final-words">Final words</h2>
<p>As you can see there was/is a lot going on, and as I said earlier, this didn&rsquo;t make me an expert in any of those fields, but it did broaden my knowledge and offered me some new views and takes on the complexity and beauty of software engineering.</p>
<p>Around the end of 2020 I started thinking about finding a new job, a remote one, not necessarily because of the Coronavirus, but rather because of the advantages and learning experiences it brings with. Finding a job is not an easy task, of course it&rsquo;s an experience more or less unique to every person, but it is definitely not a walk in the park. I might put together a <a href="">new post</a> detailing this experience too.</p>
<p>Fast-forward, 01.03.2021, new job, new position, and a feeling of accomplishment to accompany me for the foreseeable future.</p>
<p>That&rsquo;s it, folks!</p>
<p>Stay safe and healthy and never stop learning!</p>
]]></content>
        </item>
        
        <item>
            <title>Java 11</title>
            <link>https://vladflore.tech/posts/2020/09/java-11/</link>
            <pubDate>Tue, 22 Sep 2020 00:00:00 +0000</pubDate>
            
            <guid>https://vladflore.tech/posts/2020/09/java-11/</guid>
            <description>&lt;p&gt;But &lt;a href=&#34;https://www.oracle.com/java/technologies/javase-downloads.html&#34; target=&#34;_blank&#34;&gt;Java&lt;/a&gt; is already at version 15, why talk about 11 ?! Well,&amp;hellip;but before that, a note of caution:
considering the release cycle of Java nowadays, it might be that the current version of Java at the time you are reading this
is bigger than 15, it was 15 when I wrote this post!&lt;/p&gt;
&lt;p&gt;Now, let&amp;rsquo;s continue&amp;hellip;&lt;/p&gt;
&lt;p&gt;Java 11 is the current (see note of caution above) LTS version, and will stay like that until Java 17 appears, which should be somewhere around the end of 2021, which is then the new LTS version (all of this hold true iff Oracle doesn&amp;rsquo;t change something in the whole release plan).&lt;/p&gt;</description>
            <content type="html"><![CDATA[<p>But <a href="https://www.oracle.com/java/technologies/javase-downloads.html" target="_blank">Java</a> is already at version 15, why talk about 11 ?! Well,&hellip;but before that, a note of caution:
considering the release cycle of Java nowadays, it might be that the current version of Java at the time you are reading this
is bigger than 15, it was 15 when I wrote this post!</p>
<p>Now, let&rsquo;s continue&hellip;</p>
<p>Java 11 is the current (see note of caution above) LTS version, and will stay like that until Java 17 appears, which should be somewhere around the end of 2021, which is then the new LTS version (all of this hold true iff Oracle doesn&rsquo;t change something in the whole release plan).</p>
<p>Oracle&rsquo;s latest <a href="https://education.oracle.com/java-se-11-developer/pexam_1Z0-819" target="_blank">certification</a> related to Java is for version 11, again, if they do not change anything, by the time you are reading this.</p>
<p>Besides, Java 11 has lots of new cool features, some of which I will be addressing in this post. Please note, that some features reached maturity with <em>this</em> version and were included as stable enhancements in the language.</p>
<p>For a complete, detailed and kinda scary compilation of all the changes check <a href="https://cr.openjdk.java.net/~iris/se/11/latestSpec/apidiffs/overview-summary.html" target="_blank">this link</a>.</p>
<p>In this post I&rsquo;ll be giving a short intro with examples about <a href="https://openjdk.java.net/jeps/330" target="_blank">JEP 330</a> and <em>shebang</em> files.</p>
<h4 id="environment-configuration">Environment configuration</h4>
<pre tabindex="0"><code>OS: Ubuntu 20.04.1 LTS
</code></pre><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>$ java --version
</span></span><span style="display:flex;"><span>openjdk 11.0.8 2020-07-14
</span></span><span style="display:flex;"><span>OpenJDK Runtime Environment AdoptOpenJDK <span style="color:#f92672">(</span>build 11.0.8+10<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>OpenJDK 64-Bit Server VM AdoptOpenJDK <span style="color:#f92672">(</span>build 11.0.8+10, mixed mode<span style="color:#f92672">)</span>
</span></span></code></pre></div><p>I use <a href="https://sdkman.io/" target="_blank">sdkman</a> to manage the versions of Java I use on my system and as such I have this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>$ whereis java
</span></span><span style="display:flex;"><span>java: /etc/java /usr/share/java /home/vlad/.sdkman/candidates/java/11.0.8.hs-adpt/bin/java
</span></span><span style="display:flex;"><span>$ which java
</span></span><span style="display:flex;"><span>/home/vlad/.sdkman/candidates/java/current/bin/java
</span></span><span style="display:flex;"><span>$ ll /home/vlad/.sdkman/candidates/java/
</span></span><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span>drwxr-xr-x <span style="color:#ae81ff">5</span> vlad vlad <span style="color:#ae81ff">4096</span> Sep <span style="color:#ae81ff">21</span> 23:22 ./
</span></span><span style="display:flex;"><span>drwxr-xr-x <span style="color:#ae81ff">5</span> vlad vlad <span style="color:#ae81ff">4096</span> Jun <span style="color:#ae81ff">30</span> 17:24 ../
</span></span><span style="display:flex;"><span>drwxr-xr-x <span style="color:#ae81ff">9</span> vlad vlad <span style="color:#ae81ff">4096</span> Jul <span style="color:#ae81ff">15</span> 11:08 11.0.8.hs-adpt/
</span></span><span style="display:flex;"><span>drwxr-xr-x <span style="color:#ae81ff">9</span> vlad vlad <span style="color:#ae81ff">4096</span> Jul <span style="color:#ae81ff">15</span> 11:13 14.0.2.hs-adpt/
</span></span><span style="display:flex;"><span>drwxr-xr-x <span style="color:#ae81ff">8</span> vlad vlad <span style="color:#ae81ff">4096</span> Jul <span style="color:#ae81ff">28</span> 17:21 8.0.265.hs-adpt/
</span></span><span style="display:flex;"><span>lrwxrwxrwx <span style="color:#ae81ff">1</span> vlad vlad <span style="color:#ae81ff">14</span> Sep <span style="color:#ae81ff">21</span> 23:21 current -&gt; 11.0.8.hs-adpt/
</span></span></code></pre></div><p>Now, on to some cool feature of Java 11&hellip;</p>
<h3 id="launch-single-file-source-code-programs">Launch single-file source-code programs</h3>
<p>As per <a href="https://openjdk.java.net/jeps/330" target="_blank">JEP 330</a> we now have the possibility to launch single-file source-code programs.</p>
<p>Let&rsquo;s code the simplest, politest Java program:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Greeter</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">main</span>(String<span style="color:#f92672">[]</span> args){
</span></span><span style="display:flex;"><span>    System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(<span style="color:#e6db74">&#34;Hello &#34;</span> <span style="color:#f92672">+</span> args<span style="color:#f92672">[</span>0<span style="color:#f92672">]</span> <span style="color:#f92672">+</span> <span style="color:#e6db74">&#34;!&#34;</span>);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Normally we would need to compile it with <code>javac</code> and get that <code>.class</code> file and then run it with <code>java</code> to see the greeting,
but now we can just do:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>$ java Greeter.java Vlad
</span></span><span style="display:flex;"><span>Hello Vlad!
</span></span></code></pre></div><p>Now let&rsquo;s turn this into a <em>shebang file</em> and use it like a script, a Java Script&hellip;mind the gap ;)</p>
<p>The main idea is to add a line (contains the path to the java binary) similar to this <code>#!/home/vlad/.sdkman/candidates/java/11.0.8.hs-adpt/bin/java --source 11</code>
at the beginning of a file and then the Java code after it, make the new file executable and execute it like any other sh file.
By the way, we can choose any name we want for the script file.</p>
<p>Content of <code>greet</code> file:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#f92672">!/</span>home<span style="color:#f92672">/</span>vlad<span style="color:#f92672">/</span>.<span style="color:#a6e22e">sdkman</span><span style="color:#f92672">/</span>candidates<span style="color:#f92672">/</span>java<span style="color:#f92672">/</span>11.<span style="color:#a6e22e">0</span>.<span style="color:#a6e22e">8</span>.<span style="color:#a6e22e">hs</span><span style="color:#f92672">-</span>adpt<span style="color:#f92672">/</span>bin<span style="color:#f92672">/</span>java <span style="color:#f92672">--</span>source 11
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Greeter</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">main</span>(String<span style="color:#f92672">[]</span> args){
</span></span><span style="display:flex;"><span>        System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(<span style="color:#e6db74">&#34;Hello &#34;</span> <span style="color:#f92672">+</span> args<span style="color:#f92672">[</span>0<span style="color:#f92672">]</span> <span style="color:#f92672">+</span> <span style="color:#e6db74">&#34;!&#34;</span>);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>make it executable:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>$ chmod u+x greet
</span></span></code></pre></div><p>and execute it:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>$ ./greet Vlad
</span></span><span style="display:flex;"><span>Hello Vlad!
</span></span></code></pre></div><p>Let&rsquo;s spice things up a bit and implement another more complex example: this time we want to take some text, line by line,
and display only the lines that match a given regular expression (basically a simplified version of <code>grep</code> command).</p>
<p>Content of <code>grep</code> file:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">#</span><span style="color:#f92672">!/</span>home<span style="color:#f92672">/</span>vlad<span style="color:#f92672">/</span>.<span style="color:#a6e22e">sdkman</span><span style="color:#f92672">/</span>candidates<span style="color:#f92672">/</span>java<span style="color:#f92672">/</span>11.<span style="color:#a6e22e">0</span>.<span style="color:#a6e22e">8</span>.<span style="color:#a6e22e">hs</span><span style="color:#f92672">-</span>adpt<span style="color:#f92672">/</span>bin<span style="color:#f92672">/</span>java <span style="color:#f92672">--</span>source 11
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> java.io.BufferedReader;
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> java.io.IOException;
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> java.io.InputStreamReader;
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> java.util.regex.Pattern;
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> java.util.stream.Stream;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Grep</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">main</span>(String<span style="color:#f92672">[]</span> args) <span style="color:#66d9ef">throws</span> IOException {
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// some arguments validation</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (args.<span style="color:#a6e22e">length</span> <span style="color:#f92672">&lt;</span> 1 <span style="color:#f92672">||</span> args.<span style="color:#a6e22e">length</span> <span style="color:#f92672">&gt;</span> 2) {
</span></span><span style="display:flex;"><span>            showUsage();
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">return</span>;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> option <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;&#34;</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> strPattern <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// some more arguments validation and extraction of the actual arguments</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (args.<span style="color:#a6e22e">length</span> <span style="color:#f92672">==</span> 1) {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">if</span> (args<span style="color:#f92672">[</span>0<span style="color:#f92672">]</span>.<span style="color:#a6e22e">startsWith</span>(<span style="color:#e6db74">&#34;-&#34;</span>)) {
</span></span><span style="display:flex;"><span>                showUsage();
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">return</span>;
</span></span><span style="display:flex;"><span>            } <span style="color:#66d9ef">else</span> {
</span></span><span style="display:flex;"><span>                strPattern <span style="color:#f92672">=</span> args<span style="color:#f92672">[</span>0<span style="color:#f92672">]</span>;
</span></span><span style="display:flex;"><span>            }
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (args.<span style="color:#a6e22e">length</span> <span style="color:#f92672">==</span> 2) {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">if</span> (args<span style="color:#f92672">[</span>0<span style="color:#f92672">]</span>.<span style="color:#a6e22e">startsWith</span>(<span style="color:#e6db74">&#34;-&#34;</span>)) {
</span></span><span style="display:flex;"><span>                option <span style="color:#f92672">=</span> args<span style="color:#f92672">[</span>0<span style="color:#f92672">]</span>;
</span></span><span style="display:flex;"><span>                strPattern <span style="color:#f92672">=</span> args<span style="color:#f92672">[</span>1<span style="color:#f92672">]</span>;
</span></span><span style="display:flex;"><span>            } <span style="color:#66d9ef">else</span> {
</span></span><span style="display:flex;"><span>                showUsage();
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">return</span>;
</span></span><span style="display:flex;"><span>            }
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// is it a case-insensitive search</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> isCaseSensitive <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (option.<span style="color:#a6e22e">equals</span>(<span style="color:#e6db74">&#34;-i&#34;</span>)) {
</span></span><span style="display:flex;"><span>            isCaseSensitive <span style="color:#f92672">=</span> <span style="color:#66d9ef">false</span>;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> reader <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> BufferedReader(<span style="color:#66d9ef">new</span> InputStreamReader(System.<span style="color:#a6e22e">in</span>));
</span></span><span style="display:flex;"><span>        Stream<span style="color:#f92672">&lt;</span>String<span style="color:#f92672">&gt;</span> lines <span style="color:#f92672">=</span> Stream.<span style="color:#a6e22e">empty</span>();
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (reader.<span style="color:#a6e22e">ready</span>()) {
</span></span><span style="display:flex;"><span>            lines <span style="color:#f92672">=</span> reader.<span style="color:#a6e22e">lines</span>();
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> regex <span style="color:#f92672">=</span> (isCaseSensitive <span style="color:#f92672">?</span> <span style="color:#e6db74">&#34;&#34;</span> : <span style="color:#e6db74">&#34;(?i)&#34;</span>) <span style="color:#f92672">+</span> <span style="color:#e6db74">&#34;.*&#34;</span> <span style="color:#f92672">+</span> strPattern <span style="color:#f92672">+</span> <span style="color:#e6db74">&#34;.*&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// new Java 11 feature</span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// see https://cr.openjdk.java.net/~iris/se/11/latestSpec/apidiffs/java/util/regex/Pattern.html</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">var</span> asMatchPredicate <span style="color:#f92672">=</span> Pattern.<span style="color:#a6e22e">compile</span>(regex).<span style="color:#a6e22e">asMatchPredicate</span>();
</span></span><span style="display:flex;"><span>        lines.<span style="color:#a6e22e">filter</span>(asMatchPredicate).<span style="color:#a6e22e">forEach</span>(System.<span style="color:#a6e22e">out</span>::println);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">showUsage</span>() {
</span></span><span style="display:flex;"><span>        System.<span style="color:#a6e22e">out</span>.<span style="color:#a6e22e">println</span>(<span style="color:#e6db74">&#34;Usage: ./grep [-i] PATTERN&#34;</span>);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Make the file executable and then you can execute it like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>$ echo -e <span style="color:#e6db74">&#34;aaa\nbbb\nccc&#34;</span> | ./grep -i CCC
</span></span><span style="display:flex;"><span>ccc
</span></span><span style="display:flex;"><span>$ echo -e <span style="color:#e6db74">&#34;aaa\nbbb\nccc&#34;</span> | ./grep -i C<span style="color:#f92672">{</span>3<span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>ccc
</span></span><span style="display:flex;"><span>$ echo -e <span style="color:#e6db74">&#34;aaa\nbbb\nccc\n&#34;</span> &gt; content
</span></span><span style="display:flex;"><span>$ cat content | ./grep -i CCC
</span></span><span style="display:flex;"><span>ccc
</span></span></code></pre></div><p>There you have it, scripting in Java has never been easier.</p>
<p>The examples are available <a href="https://github.com/vladflore/java11" target="_blank">in this GitHub repo</a>.</p>
<p>Happy coding in Java 11!</p>
]]></content>
        </item>
        
        <item>
            <title>Code Kata</title>
            <link>https://vladflore.tech/posts/2020/06/code-kata/</link>
            <pubDate>Sun, 28 Jun 2020 00:00:00 +0000</pubDate>
            
            <guid>https://vladflore.tech/posts/2020/06/code-kata/</guid>
            <description>&lt;p&gt;Lately I&amp;rsquo;ve been taking a keen interest in the idea of &lt;em&gt;writing code and getting better at it&lt;/em&gt;, and what I mean by this is not just
the fact of &lt;em&gt;writing code&lt;/em&gt; itself and &lt;em&gt;making it work&lt;/em&gt;, but also improving your &lt;em&gt;coding skills&lt;/em&gt;, and &lt;em&gt;the way you code&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;When we write code we tend to concentrate on the code itself, on solving the problem, not necessarily on the way we produce that code,
let alone how we navigate it&amp;hellip;one can always use the mouse right? If you are working professionally in a project you don&amp;rsquo;t always have the time to &lt;em&gt;think&lt;/em&gt; about
the way you write code. Writing it, making it work and getting it accepted (only &lt;strong&gt;clean code&lt;/strong&gt; should have the privilege of reaching the main development line) is enough of a challenge.&lt;/p&gt;</description>
            <content type="html"><![CDATA[<p>Lately I&rsquo;ve been taking a keen interest in the idea of <em>writing code and getting better at it</em>, and what I mean by this is not just
the fact of <em>writing code</em> itself and <em>making it work</em>, but also improving your <em>coding skills</em>, and <em>the way you code</em>.</p>
<p>When we write code we tend to concentrate on the code itself, on solving the problem, not necessarily on the way we produce that code,
let alone how we navigate it&hellip;one can always use the mouse right? If you are working professionally in a project you don&rsquo;t always have the time to <em>think</em> about
the way you write code. Writing it, making it work and getting it accepted (only <strong>clean code</strong> should have the privilege of reaching the main development line) is enough of a challenge.</p>
<p>So, what then? Well, you could have a pet project, which could give you the time to <em>take a step back</em>, <em>reflect</em>, <em>think</em> about <em>how</em> you are producing code.
This could indeed work, the challenge is to have an idea to get you started and keep you motivated to continue. It is for sure a way to improve your craft, but we could do
even better than that. <strong>Code Kata</strong>s for the win!</p>
<p>A <a href="https://en.wikipedia.org/wiki/Kata" target="_blank">Kata</a> is, according to Wikipedia</p>
<blockquote>
<p>a detailed choreographed pattern of martial arts movements made to be practised alone, and within groups and in unison when training&quot;.</p>
</blockquote>
<p>A <a href="http://codekata.com" target="_blank">Code Kata</a> tries to bring the element of practice to the software development. It&rsquo;s when/where you practice the skill you want to acquire
or improve.</p>
<p>If you want to take a deeper dive into this, check <a href="https://www.amazon.com/Coding-Dojo-Handbook-Emily-Bache/dp/919811803X" target="_blank">this book by Emily Bache</a>, where you can find more on code katas, the notion of coding dojo und much more.
Do not forget to check the <a href="https://github.com/emilybache" target="_blank">GH repository</a>, for some refactoring katas, that you could do - multiple programming languages supported.</p>
<p>You want to practice on your own or in a group, <a href="https://cyber-dojo.org/" target="_blank">check this site</a>!</p>
<p>The idea is that by doing katas you get to hon your coding skills, and pretty much everything else related to this that you want to improve, navigating and
editing a text file, getting better and faster at writing code, writing more professional (clean-)code, learning an IDE, or some other text editing tool, like vim.
The possibilities are unlimited.</p>
<p>Another point worth mentioning is that you can also take on some more difficult tasks, like algorithmic problem solving, and improve your problem
solving skills, brushing upon those algorithms you have probably not used anymore since college/university, learning new ones, getting reads for a
technical interview for top companies and so on.</p>
<p>Have a look at these links (there are many more out there, just google <em>coding challenges</em>) and give it a try:</p>
<ul>
<li><a href="https://www.hackerrank.com" target="_blank">hakerrank</a></li>
<li><a href="https://www.codewars.com" target="_blank">codewars</a></li>
<li><a href="https://leetcode.com/" target="_blank">leetcode</a></li>
</ul>
<p>Another resource worth mentioning, which I totally love, is <a href="https://www.jetbrains.com/academy/" target="_blank">JetBrains Academy</a>. You can become a fully fledged Java Developer by taking the
Java Developer track. They also offer similar tracks for Python and Kotlin. The best of it is that you can learn to program by creating
working applications. You also get daily challenges which bring you points also known as gems, which you then can spend. Overall is a wonderful experience,
one you should not miss.</p>
<p>As you can see, there are tons of resources to get you going as a programmer or to help you improve as one, you just have to dedicate time to it
and to practice, because, as we all know, practice makes perfect!</p>
<p>Now, go and sharpen your skills and do not be afraid to experiment and learn new things!</p>
]]></content>
        </item>
        
        <item>
            <title>SonarQube on AWS EC2</title>
            <link>https://vladflore.tech/posts/2020/06/sonarqube-on-aws-ec2/</link>
            <pubDate>Thu, 04 Jun 2020 00:00:00 +0000</pubDate>
            
            <guid>https://vladflore.tech/posts/2020/06/sonarqube-on-aws-ec2/</guid>
            <description>&lt;p&gt;In this post I will share my experience with installing SonarQube on an AWS EC2 instance. What you&amp;rsquo;ll see below are some steps and hints I followed when setting up a SonarQube Server on an EC2 machine.&lt;/p&gt;
&lt;h2 id=&#34;the-motivation-behind&#34;&gt;The motivation behind&lt;/h2&gt;
&lt;p&gt;I wanted a SonarQube Server running in the cloud so that my GitHub projects could benefit of it. It is always a good idea to have some quality checks performed on your code and some way to drill down through them and get an idea on how good or bad your code is. I also didn&amp;rsquo;t want to set up my own cloud, so I just sticked with AWS EC2 solution, despite the fact that it is not always for free.&lt;/p&gt;</description>
            <content type="html"><![CDATA[<p>In this post I will share my experience with installing SonarQube on an AWS EC2 instance. What you&rsquo;ll see below are some steps and hints I followed when setting up a SonarQube Server on an EC2 machine.</p>
<h2 id="the-motivation-behind">The motivation behind</h2>
<p>I wanted a SonarQube Server running in the cloud so that my GitHub projects could benefit of it. It is always a good idea to have some quality checks performed on your code and some way to drill down through them and get an idea on how good or bad your code is. I also didn&rsquo;t want to set up my own cloud, so I just sticked with AWS EC2 solution, despite the fact that it is not always for free.</p>
<p>Make sure to check the documentation and the billing policies to not have any surprises at the end of the month. In case you do not need the instances to run all the time you can stop them and only start them when you need them. A stopped instance is billed differently and less than a running one.</p>
<p>As I said, I want to use Sonar for my GitHub projects, which means I want it configured specifically to my needs, which are:</p>
<ul>
<li>the quality checks (history) should be persisted, a.k.a, an in-memory database will not suffice. I will use PostgreSQL 12.</li>
<li>I want mutation testing (MT) enabled and I want to use the MT rules together with the default rules to check the code. As for the language I will initially start with Java.</li>
</ul>
<p>Having said this, let&rsquo;s start with the installation.</p>
<h2 id="step-1">Step 1</h2>
<h3 id="get-an-aws-ec2-instance-up-and-running">Get an AWS EC2 instance up and running.</h3>
<p>There is not much to say here, go to the <a href="https://console.aws.amazon.com/" target="_blank">AWS Console</a>, check the documentation and follow the steps, it&rsquo;s pretty intuitive and no brainer at all. After having done that - the instance is running and you can SSH into it, proceed with the next step.</p>
<h2 id="step-2">Step 2</h2>
<h3 id="prepare-the-ec2-instance-for-sonarqube-installation">Prepare the EC2 instance for SonarQube installation.</h3>
<p>You won&rsquo;t have pretty much anything pre-installed so you&rsquo;ll have to do it yourself.</p>
<blockquote>
<p><strong><em>NOTE:</em></strong> most of the commands require sudo access, so&hellip;you have been warned!</p>
</blockquote>
<h3 id="update-the-system">Update the system</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>sudo apt update
</span></span><span style="display:flex;"><span>sudo apt upgrade
</span></span></code></pre></div><h3 id="install-unzip-tool">Install unzip tool</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>sudo apt install unzip
</span></span></code></pre></div><h3 id="install-java-11">Install Java 11</h3>
<p>SonarQube 8.3 requires Java - Oracle JRE 11 or OpenJDK 11 - installed on the machine, I&rsquo;ll go with OpenJDK.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>sudo apt install openjdk-11-jdk
</span></span></code></pre></div><h3 id="install-postgresql-12">Install PostgreSQL 12</h3>
<p>Bbefore running the command <em>add the PostgreSQL apt repository</em> as documented <a href="https://www.postgresql.org/download/linux/ubuntu/" target="_blank">here</a>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>sudo apt install postgresql-12
</span></span></code></pre></div><h3 id="prepare-postgresql-for-sonarqube">Prepare PostgreSQL for SonarQube</h3>
<p>This basically means creating the user and the database.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span><span style="color:#75715e"># change current user to postgres</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># (this was created for you as part of the PostgreSQL installation)</span>
</span></span><span style="display:flex;"><span>sudo su - postgres
</span></span><span style="display:flex;"><span><span style="color:#75715e"># go into PostgreSQL</span>
</span></span><span style="display:flex;"><span>psql
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#75715e">--- create the user
</span></span></span><span style="display:flex;"><span><span style="color:#66d9ef">CREATE</span> <span style="color:#66d9ef">USER</span> sonarqube <span style="color:#66d9ef">WITH</span> PASSWORD <span style="color:#e6db74">&#39;yourPassword&#39;</span>;
</span></span><span style="display:flex;"><span><span style="color:#75715e">--- create the database
</span></span></span><span style="display:flex;"><span><span style="color:#66d9ef">CREATE</span> <span style="color:#66d9ef">DATABASE</span> sonarqube <span style="color:#66d9ef">OWNER</span> sonarqube;
</span></span><span style="display:flex;"><span><span style="color:#75715e">--- grant the privileges
</span></span></span><span style="display:flex;"><span><span style="color:#66d9ef">GRANT</span> <span style="color:#66d9ef">ALL</span> <span style="color:#66d9ef">PRIVILEGES</span> <span style="color:#66d9ef">ON</span> <span style="color:#66d9ef">DATABASE</span> sonarqube <span style="color:#66d9ef">TO</span> sonarqube;
</span></span><span style="display:flex;"><span><span style="color:#75715e">--- exit PostgreSQL
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">\</span>q
</span></span></code></pre></div><h3 id="add-inbound-rule-for-the-security-group-the-instance-belongs-to">Add inbound rule for the security group the instance belongs to</h3>
<p>In order to allow requests to be made to SonarQube you have to add an inbound rule for the security group the EC2 instance belongs to. Find the security group your instance has (on the <code>Instances</code> page, check for the <code>Security Groups</code> column in the table which displays your instances, go to that SG and edit the <code>Inbound Rules</code> by adding a new one for <code>TCP</code> and port <code>9000</code>).</p>
<h2 id="step-3">Step 3</h2>
<h3 id="download-the-sonarqube-server">Download the SonarQube Server.</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>wget https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-8.3.0.34182.zip
</span></span><span style="display:flex;"><span>unzip sonarqube-8.3.0.34182.zip
</span></span><span style="display:flex;"><span><span style="color:#75715e"># move the unzipped folder under /opt</span>
</span></span><span style="display:flex;"><span>sudo mv sonarqube-8.3.0.34182 /opt/sonarqube
</span></span></code></pre></div><h2 id="step-4">Step 4</h2>
<h3 id="create-user-for-sonarqube">Create user for SonarQube.</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>sudo adduser --system --no-create-home --group --disabled-login sonarqube
</span></span><span style="display:flex;"><span>sudo chown -R sonarqube:sonarqube /opt/sonarqube
</span></span></code></pre></div><h2 id="step-5">Step 5</h2>
<h3 id="configure-sonarqube-properties-and-launch-scripts">Configure SonarQube properties and launch scripts.</h3>
<p>Edit <code>sonar.properties</code> and add the following properties:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>vi /opt/sonarqube/conf/sonar.properties
</span></span></code></pre></div><pre tabindex="0"><code>sonar.jdbc.username=sonarqube
sonar.jdbc.password=yourPassword
sonar.jdbc.url=jdbc:postgresql://localhost/sonarqube
sonar.web.javaAdditionalOpts=-server
sonar.web.host=0.0.0.0
</code></pre><p>Edit <code>sysctl.conf</code> and set the property <code>vm.max_map_count</code> to <code>262144</code>. SonarQube will most likely not start without it!</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>vi /etc/sysctl.conf
</span></span></code></pre></div><pre tabindex="0"><code>vm.max_map_count=262144
</code></pre><p>Edit <code>sonar.sh</code> and set the variable <code>RUN_AS_USER</code> to <code>sonarqube</code>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>vi /opt/sonarqube/bin/linux-x86-64/sonar.sh
</span></span></code></pre></div><pre tabindex="0"><code>RUN_AS_USER=sonarqube
</code></pre><p>At this point you should have everything in place to be able to start the SonarQube and access it in the browser.</p>
<h3 id="start-sonarqube">Start SonarQube</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span><span style="color:#75715e"># navigate to the Sonar installation location</span>
</span></span><span style="display:flex;"><span>cd /opt/sonarqube/bin/linux-x86-64
</span></span><span style="display:flex;"><span><span style="color:#75715e"># start Sonar</span>
</span></span><span style="display:flex;"><span>./sonar.sh start
</span></span></code></pre></div><p>Call <code>http://&lt;IPv4 Public IP&gt;:9000/</code> in the browser, where <code>IPv4 Public IP</code> stands for the public IP, which you can take from the Description information of your EC2 instance.
You should see your SonarQube page.</p>
<p>Now let&rsquo;s configure Sonar.</p>
<h3 id="configure-sonarqube">Configure SonarQube</h3>
<p>First step is to <em>enable the mutation testing support</em>, which means that you have to <em>install a plugin</em>.
For this, login with the default credentials <code>admin/admin</code>, go to <code>Administration -&gt; Marketplace</code> and search for <code>Mutation Analysis</code> <a href="https://github.com/devcon5io/mutation-analysis-plugin" target="_blank">plugin</a> and install it.
Restart the server.</p>
<p><img src="/images/sonar-mt-plugin.png" alt="sonar-mt-plugin"></p>
<p>Next, we need to create a new <em>quality profile</em>, which will contain the <em>default SonarQube Java rules</em> and the <em>Mutation Analysis rules</em> and set it as the <em>default profile for Java</em>.</p>
<p>Follow the steps listed in <a href="https://dzone.com/articles/mutation-testing-with-sonarqube" target="_blank">this article</a> under the section <em>Enable the Mutation Analysis Rules</em> to achieve the above mentioned.</p>
<p>When finished it should look something similar to this:</p>
<p><img src="/images/sonar-mt-java-rules.png" alt="sonar-mt-plugin"></p>
<p>Now SonarQube should be able to interpret the mutation testing results too.</p>
<p>Before drilling down through your project and hunting down your mutations you have to upload the mutation analysis for the project in question.</p>
<p>I am using Maven as a build automation tool for my project and my <code>pom.xml</code> is updated accordingly.</p>
<p>At a minimum, you need the <code>pitest-junit5-plugin</code> dependency, the <code>sonar-maven-plugin</code> plugin and the <code>pitest-maven</code> plugin. For Java code coverage do not forget about <code>jacoco-maven-plugin</code>.</p>
<p>Check the <a href="https://github.com/vladflore/gildedrose-refactoring-kata/blob/master/pom.xml" target="_blank">GitHub repo</a> to see how the pom.xml looks like.</p>
<p>After your project is all set up, the following command should suffice to perform a code analysis of your code. Note that the value for <code>sonar.host.url</code> should be changed
accordingly to contain the IP of your EC2 instance hosting the SonarQube Server.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>mvn clean verify org.pitest:pitest-maven:mutationCoverage sonar:sonar -Dsonar.host.url<span style="color:#f92672">=</span>http://&lt;IPv4 Public IP&gt;:9000
</span></span></code></pre></div><p>And voilà the analysis of my project at that point in time (including the mutation analysis):</p>
<p><img src="/images/sonar-analysis.png" alt="sonar-mt-plugin"></p>
<p>Now go write those unit tests, kill those mutants and reach a 90%+ code coverage. I dare you! ;)</p>
<p>Happy code crafting!</p>
]]></content>
        </item>
        
        <item>
            <title>Shell Magic</title>
            <link>https://vladflore.tech/posts/2020/03/shell-magic/</link>
            <pubDate>Wed, 25 Mar 2020 00:00:00 +0000</pubDate>
            
            <guid>https://vladflore.tech/posts/2020/03/shell-magic/</guid>
            <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;NOTE 1:&lt;/em&gt;&lt;/strong&gt; This page contains some shell &lt;em&gt;magic&lt;/em&gt; which I came across in my daily business. I will update this page continuously and this will be reflected on this page in the date information displayed under the post name.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;NOTE 2:&lt;/em&gt;&lt;/strong&gt; Please be advised that some commands listed here could have unwanted effects if you are not completely sure of what they are doing and how they are doing it.
Some of them might also require sudo access, so I am just going to assume that you know what you are doing. You have been warned!&lt;/p&gt;</description>
            <content type="html"><![CDATA[<blockquote>
<p><strong><em>NOTE 1:</em></strong> This page contains some shell <em>magic</em> which I came across in my daily business. I will update this page continuously and this will be reflected on this page in the date information displayed under the post name.</p>
</blockquote>
<blockquote>
<p><strong><em>NOTE 2:</em></strong> Please be advised that some commands listed here could have unwanted effects if you are not completely sure of what they are doing and how they are doing it.
Some of them might also require sudo access, so I am just going to assume that you know what you are doing. You have been warned!</p>
</blockquote>
<h2 id="11-from-uppercase-to-lowercase-and-from-space-to-underscore">11. From uppercase to lowercase and from space to underscore</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>echo <span style="color:#e6db74">&#39;Building REST services with Spring&#39;</span> | tr <span style="color:#e6db74">&#39;[:upper:]&#39;</span> <span style="color:#e6db74">&#39;[:lower:]&#39;</span> | tr <span style="color:#e6db74">&#39; &#39;</span> <span style="color:#e6db74">&#39;_&#39;</span> | xclip -sel c
</span></span></code></pre></div><p>Transform <code>tr</code> uppercase letters <code>[:upper:]</code> to lowercase <code>[:lower:]</code>, then replace the space <code> </code> with an underscore <code>_</code> and finally copy <code>xclip</code> the result to clipboard <code>-sel c</code>. After this you can paste the text wherever you need it. To prove the usefulness of this, instead of copying the result into the clipboard, pipe it into <code>xargs</code> to, for instance, create a folder, like: <code>...| xargs mkdir -p</code>.</p>
<hr>
<h2 id="10-execute-a-program-periodically">10. Execute a program periodically</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>watch du -sh &lt;folder&gt;
</span></span></code></pre></div><p>Execute the <code>du</code> command periodically, every 2 seconds, until interrupted. The command displays only the total size <code>-s</code> of the <code>&lt;folder&gt;</code>, in a human readable format <code>-h</code>.</p>
<hr>
<h2 id="9-display-file-space-usage-in-human-readable-format">9. Display file space usage in human readable format</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>du -hc . | sort -rh | head -5
</span></span></code></pre></div><p>Display size in human readable format <code>-h</code>, producing a grand total <code>-c</code>, then sort the output in reversed order <code>-r</code> by comparing human readable sizes <code>-h</code>, and finally taking only the first five lines of the output.</p>
<hr>
<h2 id="8-search-for-a-pattern-inside-files">8. Search for a pattern inside files</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>grep -rnw . -e <span style="color:#e6db74">&#39;pattern&#39;</span>
</span></span></code></pre></div><p>Search in the current <code>.</code> directory, recursively <code>-r</code>, matching <code>-e</code> the pattern <code>pattern</code>, considering only whole words <code>-w</code>, displaying the line number <code>-n</code> of the match.</p>
<hr>
<h2 id="7-forcibly-removing-all-directories-and-their-content-recursively">7. Forcibly removing all directories and their content recursively</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>ls -l | grep <span style="color:#e6db74">&#39;^d&#39;</span> | awk <span style="color:#e6db74">&#39;{print $9}&#39;</span> | xargs rm -rf
</span></span></code></pre></div><p>In plain English, list the content of the current directory <code>ls</code> using the long listing format <code>-l</code>, filter out everything else that is not a directory <code>grep '^d'</code>, extract the 9^th^ column (the last containing the name of the directory) <code>awk '{print $9}'</code>, pass each name of the directory as an argument <code>xargs</code> to the command <code>rm</code>, which removes recursively <code>-r</code> and forcibly <code>-f</code> the respective directory.</p>
<hr>
<h2 id="6-switching-between-github-remote-urls-https-vs-ssh">6. Switching between GitHub remote URLs (HTTPS vs. SSH)</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>git remote -v
</span></span><span style="display:flex;"><span>git remote set-url origin git@github.com:USERNAME/REPOSITORY.git
</span></span><span style="display:flex;"><span>git remote set-url origin https://github.com/USERNAME/REPOSITORY.git
</span></span></code></pre></div><p>First we check what kind of remote URLs we have, using option <code>-v</code> of command <code>git remote</code>,
afterwards we change the remote URL to either HTTPS or SSH using one of the last two commands
(note the two different URL styles for setting the remote name <code>origin</code>). Do not forget
to replace the <code>USERNAME</code> and <code>REPOSITORY</code> with the real values.</p>
<hr>
<h2 id="5-searching-for-files-and-creating-an-archive-out-of-them">5. Searching for files and creating an archive out of them</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>find . -type f <span style="color:#ae81ff">\(</span> -name file1 -o -name file2 <span style="color:#ae81ff">\)</span> | zip -@ -j files
</span></span><span style="display:flex;"><span>mv files.zip ~/tmp
</span></span><span style="display:flex;"><span>cd $_
</span></span><span style="display:flex;"><span>xdg-open .
</span></span></code></pre></div><p>First we search in the current <code>.</code> directory for entries denoting files <code>-type f</code> having the name <code>-name</code> <em>file1</em> or <code>-o</code> <em>file2</em>.
The <code>zip</code> command takes the list of files <code>-@</code> and creates an archive with the name <em>files</em> containing only the files without
storing the directories where they reside. After moving <code>mv</code> the archive to the <em>tmp</em> directory we <code>cd</code> into it, <code>$_</code> references the
last argument of the previous command, and open <code>xdg-open</code> the current directory <code>.</code> with the appropriate program - in my case this is <em>Files</em>.</p>
<hr>
<h2 id="4-manage-processes-from-the-terminal">4. Manage processes from the Terminal</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span><span style="color:#75715e"># display Linux processes</span>
</span></span><span style="display:flex;"><span>top
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># top improved, you might need to install it</span>
</span></span><span style="display:flex;"><span>htop
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># list all running processes and look for a specific process</span>
</span></span><span style="display:flex;"><span>ps -A | grep chrome
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># display processes in a tree like format</span>
</span></span><span style="display:flex;"><span>pstree
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># look up a process based on name</span>
</span></span><span style="display:flex;"><span>pgrep chome
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># kills process identified by the PID, use -9 or -KILL to force kill</span>
</span></span><span style="display:flex;"><span>kill PID
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># kill process given its name</span>
</span></span><span style="display:flex;"><span>pkill chrome
</span></span><span style="display:flex;"><span>killall chrome
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># allows killing graphical programs</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># run it and your cursor will turn into x, then click a program&#39;s window</span>
</span></span><span style="display:flex;"><span>xkill
</span></span></code></pre></div><hr>
<h2 id="3-print-content-of-path-line-by-line">3. Print content of $PATH line-by-line</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>echo $PATH | tr <span style="color:#e6db74">&#39;:&#39;</span> <span style="color:#e6db74">&#39;\n&#39;</span>
</span></span></code></pre></div><p>Pipes the content, obtained via <code>echo</code>, of the <code>PATH</code> variable into the translate <code>tr</code> command which
replaces each occurrence of <code>:</code> with a new line <code>\n</code>.</p>
<p>Another example:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>echo line1:line2 | tr <span style="color:#e6db74">&#39;:&#39;</span> <span style="color:#e6db74">&#39;\n&#39;</span>
</span></span><span style="display:flex;"><span>line1
</span></span><span style="display:flex;"><span>line2
</span></span></code></pre></div><hr>
<h2 id="2-show-all-users">2. Show all users</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>cat /etc/passwd | awk -F: <span style="color:#e6db74">&#39;{print$1}&#39;</span>
</span></span></code></pre></div><p>The content of the file <code>passwd</code> is pipped into the <code>awk</code>, which takes each line
and splits it into columns by the defined <code>-F</code> separator <code>:</code>
printing out the first value (the user name).</p>
<hr>
<h2 id="1-show-all-hidden-files">1. Show all hidden files</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>ls -lap | grep -v / | awk <span style="color:#e6db74">&#39;{print $9}&#39;</span> | grep <span style="color:#e6db74">&#39;^\.&#39;</span>
</span></span></code></pre></div><p>List <code>ls</code> all <code>-a</code> content of the current directory using the long listing format <code>-l</code> appending <code>-p</code> a forward slash <code>/</code> if the entry is a directory, then print only those lines which do not end with a forward slash (<code>grep</code> performs a pattern matching, while <code>-v</code> inverts the match). <code>awk</code> prints out the nineth column of the line - the name, and the last <code>grep</code> shows only those which begin with a <code>.</code>.</p>
]]></content>
        </item>
        
        <item>
            <title>Hello World</title>
            <link>https://vladflore.tech/posts/2020/02/hello-world/</link>
            <pubDate>Mon, 10 Feb 2020 00:00:00 +0000</pubDate>
            
            <guid>https://vladflore.tech/posts/2020/02/hello-world/</guid>
            <description>&lt;p&gt;Hello Internet,&lt;/p&gt;
&lt;p&gt;so this is my first blog post, which I hope will be one of many more to come. This is more of a &lt;em&gt;hello world&lt;/em&gt; kind of post,
a way to cut my teeth into blogging and see if it&amp;rsquo;s something I would like doing.&lt;/p&gt;
&lt;p&gt;Should you wonder by now why &lt;em&gt;hello world&lt;/em&gt;,
well just ask someone who works in IT and has learned at least one programming language.&lt;/p&gt;</description>
            <content type="html"><![CDATA[<p>Hello Internet,</p>
<p>so this is my first blog post, which I hope will be one of many more to come. This is more of a <em>hello world</em> kind of post,
a way to cut my teeth into blogging and see if it&rsquo;s something I would like doing.</p>
<p>Should you wonder by now why <em>hello world</em>,
well just ask someone who works in IT and has learned at least one programming language.</p>
<p>The majority of the posts will be of technical nature and will server primarily the purpose of conveying knowledge
that I gathered or stumbled upon over the time.</p>
<p>Quite often, I find myself in the position of having to do something I have already done
before, and quite often I regret not having documented that something&hellip;This blog is about changing all that and allowing me
and others to tap into that information I once used/had in order to make use of it again.</p>
<p>I guess time will tell if this is a worthwhile endeavor or not.</p>
<p>Happy reading!</p>
]]></content>
        </item>
        
        <item>
            <title>Software Craftsmanship</title>
            <link>https://vladflore.tech/posts/2020/02/software-craftsmanship/</link>
            <pubDate>Mon, 10 Feb 2020 00:00:00 +0000</pubDate>
            
            <guid>https://vladflore.tech/posts/2020/02/software-craftsmanship/</guid>
            <description>&lt;p&gt;Last year I had the opportunity to put together and hold a presentation at a conference organized
by the &lt;a href=&#34;https://www.virtual7.de/&#34; target=&#34;_blank&#34;&gt;company&lt;/a&gt; I am currently working for. As you might have guessed from the post&amp;rsquo;s title
it was a presentation about the &lt;strong&gt;craftsmanship&lt;/strong&gt; behind &lt;strong&gt;creating software&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Creating software is no easy task, creating software &lt;strong&gt;responsibly&lt;/strong&gt; is even harder, but this should not discourage one to do so.&lt;/p&gt;
&lt;p&gt;By adhering to some healthy coding habits one can and will write code that will not make others cringe when looking at it.
Remember, &lt;strong&gt;we write code for people not for computers&lt;/strong&gt;.&lt;/p&gt;</description>
            <content type="html"><![CDATA[<p>Last year I had the opportunity to put together and hold a presentation at a conference organized
by the <a href="https://www.virtual7.de/" target="_blank">company</a> I am currently working for. As you might have guessed from the post&rsquo;s title
it was a presentation about the <strong>craftsmanship</strong> behind <strong>creating software</strong>.</p>
<p>Creating software is no easy task, creating software <strong>responsibly</strong> is even harder, but this should not discourage one to do so.</p>
<p>By adhering to some healthy coding habits one can and will write code that will not make others cringe when looking at it.
Remember, <strong>we write code for people not for computers</strong>.</p>
<p>The presentation is powered by <a href="https://revealjs.com/#/" target="_blank">reveal.js framework</a>, can be watched <a href="https://vladflore.github.io/software-craftsmanship/#/" target="_blank">here</a> and it can be found at this <a href="https://github.com/vladflore/software-craftsmanship.git" target="_blank">link</a> on GitHub.</p>
<p>Happy code crafting!</p>
]]></content>
        </item>
        
    </channel>
</rss>
