<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Irvin Gil</title>
    <description>The latest articles on DEV Community by Irvin Gil (@ehrbhein).</description>
    <link>https://dev.to/ehrbhein</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1068224%2F1af085ac-51ad-448f-a2e8-a365380d8c85.png</url>
      <title>DEV Community: Irvin Gil</title>
      <link>https://dev.to/ehrbhein</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ehrbhein"/>
    <language>en</language>
    <item>
      <title>A Year of Gratitude: Reflecting on 2025</title>
      <dc:creator>Irvin Gil</dc:creator>
      <pubDate>Mon, 08 Dec 2025 15:24:27 +0000</pubDate>
      <link>https://dev.to/ehrbhein/a-year-of-gratitude-reflecting-on-2025-jnf</link>
      <guid>https://dev.to/ehrbhein/a-year-of-gratitude-reflecting-on-2025-jnf</guid>
      <description>&lt;p&gt;As the year draws to a close, I want to take a moment to look back and appreciate the wins I've achieved, as well as the learnings I'll carry with me into the new year. I'm posting this ahead of Christmas so I can focus on other things—I'll be going on vacation back to our hometown where there's little to no internet connection, which is why I'm writing this now.&lt;/p&gt;

&lt;p&gt;This year was a roller coaster, a test, a lesson, and most of all, a blessing.&lt;br&gt;
It was a roller coaster because it brought both ups and downs. A test because it taught me to stay prepared and keep a sharp mind. A lesson because the challenges I faced were filled with insights—both big and small. And a blessing because it opened doors of opportunity and allowed me to continue providing for the people who depend on me.&lt;/p&gt;

&lt;p&gt;Here are some of the things that went really well for me this year:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;✏️ &lt;strong&gt;Supported my siblings through another year of education&lt;/strong&gt; - Just as I did last year, I've been able to continue supporting my siblings through college, and I'm incredibly proud that they've reached their third year. This is a big deal for me and my family because we struggled financially when I was going through college. Now that I'm able to help, I wanted to ease that burden. By shouldering the allowance and expenses for my siblings, I've been able to make things significantly easier for my parents—and that means the world to me.&lt;/li&gt;
&lt;li&gt;⬆️ &lt;strong&gt;Leveled up in my career&lt;/strong&gt; - I got promoted this November, and it's one of the things I've been praying for all year. I am deeply grateful for this opportunity and challenge. I'm also proud to say that all those hours of grinding and doing work that sometimes went unnoticed have finally paid off.&lt;/li&gt;
&lt;li&gt;🏠 &lt;strong&gt;Moved into a more comfortable apartment with my partner&lt;/strong&gt; - We feel incredibly fortunate to have found a spacious rental with so much room for what we're paying. Given its size, we could have easily paid twice the amount if it were located in the city. This has been one of the best things to happen to us this year. We now have a home where we can comfortably host guests, and the owners are genuinely nice and welcoming. Plus, the location is both accessible and secure, which gives us peace of mind. &lt;/li&gt;
&lt;li&gt;🖥️ &lt;strong&gt;Improved and upgraded my workstation&lt;/strong&gt; - Buying things for myself has always been challenging since a portion of my earnings goes toward supporting my siblings. It's been this way since I got my first job after college. But this year, I was able to save enough to upgrade my workstation with a standing desk and mesh chair. Even better, I was also able to buy equipment for my partner's workstation. I see this as an investment in both of us, especially since we work from home. Having ergonomic equipment that reduces long-term health issues feels like a real win.&lt;/li&gt;
&lt;li&gt;🪪 &lt;strong&gt;Applied for and received my passport&lt;/strong&gt; - This was one of my partner's and my goals from last year that we hadn't managed to make time for. We challenged ourselves to finally allot time to process and apply for our passports before the year ended. After navigating all the unknowns and compromises, we finally claimed them in Cebu during the first week of December. This is one of our "basin diay"—even though we don't really need it at the moment, we agreed it's good to have. When opportunities come knocking, we want to be prepared.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Lessons I'm Carrying Forward
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pair patience with persistence&lt;/strong&gt; - This year, I had many things I wanted to achieve and accomplish. There were countless times when I was shown that it wasn't the right time for certain things. I struggled to process and accept those signals that said "not yet." So instead, even when the signs weren't clear, I kept doing what needed to be done and used my free time to pursue things I wanted. I learned that boredom and disinterest easily creep in when you complain too much. The lesson? Be patient. If it's not time yet, redirect your energy elsewhere.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;In our lowest moments, we feel God's presence most clearly&lt;/strong&gt; - This is a simple yet often overlooked truth that I think everyone experiences. When I receive blessings, it's easy to say "thank God for this," but the deep emotion and closeness to God aren't always there—I still feel somewhat distant. It's in the moments when I'm down and feeling helpless that I truly feel God's presence and guidance. And that's beautiful. I'm not saying we need to be sad all the time to feel close to God. Rather, I'm recognizing how those desperate moments can transform our perspective and guide our actions afterward. It reminds me of &lt;a href="https://www.goodreads.com/quotes/1281591-when-we-reach-our-lowest-point-we-are-open-to" rel="noopener noreferrer"&gt;this quote&lt;/a&gt; from The Legend of Korra. I've come to accept that this is one of God's ways of guiding us. It proves that God is speaking to us—we just need to listen.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Never make decisions when emotions are running high&lt;/strong&gt; - I've made many poor decisions this year—from choosing the wrong words in a conversation to saying yes to something simply because I was happy in the moment. It was only when I paid closer attention that I noticed these mistakes. They can take many forms: a heated argument, or committing to a family event when you're not truly available. The impact becomes apparent when you end up hurting others or putting yourself in an uncomfortable position. The key lesson? Give yourself time to reflect before making a decision—not the kind where you're choosing your next meal, but the kind where you're committing your time, money, or attention to something important. Write it down, take a walk, and come back to it when you're thinking clearly. Bad timing isn't always what ruins your day; more often, it's bad decisions. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Focus on what truly adds value&lt;/strong&gt; - I picked up this lesson rather late this year, but I'm committed to mastering it. There are so many distractions in our lives, especially with technology and the internet—it's incredibly easy to lose focus. I've been battling the urge to procrastinate and waste time scrolling through social media. Instead, I've challenged myself to read books, complete online courses that will give me crucial skills at work, and even tackle menial tasks like doing my own laundry and checking things off my list. Starting is often the hardest part of anything—but I think what's even harder is identifying which things are truly "valuable" to you, and then actually doing them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Health truly is wealth&lt;/strong&gt; - This is another simple yet often overlooked lesson. This year, I've met and talked with many people who shared their experiences with me. What I've observed, especially with older people, is how their health conditions limit what they can do. Many have dietary restrictions that constrain their daily lives. Even more striking, I witnessed a colleague having to leave his role and resign because his health was affecting his performance. These experiences have reinforced for me that health truly is wealth.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Social and family connections are noise—but essential noise&lt;/strong&gt; - This ties into my earlier lesson about focusing on what's valuable. As Filipinos, our families often ask and expect much from us. Some people view this as a toxic trait, and I'd agree when it reaches a suffocating level. But for me personally, it's an essential noise. It reminds me that my family acknowledges who I've become and wants me to be part of the good things happening in their lives. I left my parents' home long ago, but their visits and our lunches together—with meals cooked from vegetables they've grown back home—transport me back to when I was just a boy. They remind me that whether I fail or succeed in life, my family is always looking out for me. And for that, I'm deeply grateful. &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A Note of Thanks
&lt;/h2&gt;

&lt;p&gt;Aside from the good things that have happened and the blessings I've received this year, I want to thank the people—whose names are too many to mention or even recall—who have helped me achieve all these great things. None of this would have been possible if I were alone. I owe my success to the people around me who supported me every step of the way.&lt;/p&gt;

&lt;p&gt;Regardless of the challenges we've faced this year, I hope that whoever reads this will also take time to count their blessings and be thankful for the experiences and learnings they've accumulated throughout the year.&lt;/p&gt;

&lt;p&gt;Happy holidays, and I wish you all a merry Christmas and a happy new year. 🎅🎄🦌🎆❄️&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frljbi454yldy5y7xs8f7.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frljbi454yldy5y7xs8f7.jpg" alt="ians-graduation" width="800" height="451"&gt;&lt;/a&gt;&lt;br&gt;Here is a picture of my family during my brother Ian's graduation this year. Me being on the left-most side in the photo.
  &lt;/p&gt;

</description>
      <category>devjournal</category>
      <category>motivation</category>
      <category>watercooler</category>
    </item>
    <item>
      <title>A comprehensive guide to List in Java</title>
      <dc:creator>Irvin Gil</dc:creator>
      <pubDate>Fri, 07 Nov 2025 14:37:44 +0000</pubDate>
      <link>https://dev.to/ehrbhein/a-comprehensive-guide-to-lists-in-java-1fa9</link>
      <guid>https://dev.to/ehrbhein/a-comprehensive-guide-to-lists-in-java-1fa9</guid>
      <description>&lt;p&gt;&lt;em&gt;We are taking a deep dive into Lists in Java and its two common implementations: ArrayList and LinkedList. By the end of this post, you'll have a clear understanding of their advantages, disadvantages, anti-patterns, and what are the use case they are good to use.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Table of contents
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
ArrayList 

&lt;ul&gt;
&lt;li&gt;
Core Characteristics &lt;/li&gt;
&lt;li&gt;
Thread Safety &amp;amp; Concurrency &lt;/li&gt;
&lt;li&gt;
Common Pitfalls and best practices &lt;/li&gt;
&lt;li&gt;
Comparison with alternatives &lt;/li&gt;
&lt;li&gt;
Exception Handling &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

LinkedList 

&lt;ul&gt;
&lt;li&gt;
Core architecture &lt;/li&gt;
&lt;li&gt;
Performance Characteristics &lt;/li&gt;
&lt;li&gt;
Thread Safety &amp;amp; Concurrency &lt;/li&gt;
&lt;li&gt;
Dequeue Operations &lt;/li&gt;
&lt;li&gt;
When to use LinkedList VS ArrayList &lt;/li&gt;
&lt;li&gt;
Common LinkedList Anti-Patterns &lt;/li&gt;
&lt;li&gt;
Exception Handling &lt;/li&gt;
&lt;li&gt;
Use case matrix and Best Practices &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Comparison and Summary: List &lt;/li&gt;

&lt;li&gt;

References &lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;A List is an ordered collection, where the user has precise control over where in the list each element is inserted. The user can access elements by their integer index (position in the list), and search for elements in the list.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Maintains insertion order&lt;/li&gt;
&lt;li&gt;Allows duplicate elements&lt;/li&gt;
&lt;li&gt;Supports null elements (implementation dependent)&lt;/li&gt;
&lt;li&gt;Supports bi-directional traversal via ListIterator&lt;/li&gt;
&lt;li&gt;Lists (like Java arrays) are zero based.&lt;/li&gt;
&lt;li&gt;An ordered collection with precise control over element insertion positions&lt;/li&gt;
&lt;li&gt;Extends &lt;code&gt;SequencedCollection&amp;lt;E&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unlike &lt;a href="https://docs.oracle.com/javase/8/docs/api/java/util/Set.html" rel="noopener noreferrer"&gt;sets&lt;/a&gt;, lists typically allow duplicate elements. More formally, lists typically allow pairs of elements e1 and e2 such that e1.equals(e2), and they typically allow multiple null elements if they allow &lt;em&gt;null&lt;/em&gt; elements at all. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It is not inconceivable that someone might wish to implement a list that prohibits duplicates, by throwing runtime exceptions when the user attempts to insert them, but we expect this usage to be rare.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Unmodifiable Lists&lt;/strong&gt; (using &lt;code&gt;List.of()&lt;/code&gt; and &lt;code&gt;List.copyOf()&lt;/code&gt;):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Elements cannot be added, removed, or replaced&lt;/li&gt;
&lt;li&gt;Disallow null elements&lt;/li&gt;
&lt;li&gt;Are serializable if all elements are serializable&lt;/li&gt;
&lt;li&gt;Implement &lt;code&gt;RandomAccess&lt;/code&gt; interface&lt;/li&gt;
&lt;li&gt;Are value-based (treat equal instances as interchangeable)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Common implementation of the list interface
&lt;/h3&gt;

&lt;p&gt;&lt;a id="list-point-1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  ArrayList
&lt;/h4&gt;

&lt;p&gt;&lt;a id="list-point-1-1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  Core Characteristics
&lt;/h5&gt;

&lt;p&gt;&lt;strong&gt;Performance Profile&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Constant Time O(1)&lt;/strong&gt;: &lt;code&gt;size()&lt;/code&gt;, &lt;code&gt;isEmpty()&lt;/code&gt;, &lt;code&gt;get()&lt;/code&gt;, &lt;code&gt;set()&lt;/code&gt;, &lt;code&gt;getFirst()&lt;/code&gt;, &lt;code&gt;getLast()&lt;/code&gt;, &lt;code&gt;removeLast()&lt;/code&gt;, &lt;code&gt;iterator()&lt;/code&gt;, &lt;code&gt;listIterator()&lt;/code&gt;, &lt;code&gt;reversed()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amortized Constant Time&lt;/strong&gt;: &lt;code&gt;add()&lt;/code&gt;, &lt;code&gt;addLast()&lt;/code&gt; - adding n elements requires O(n) time total&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Linear Time O(n)&lt;/strong&gt;: All other operations (search, insert at position, remove by index/object)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Low constant factor&lt;/strong&gt; compared to &lt;code&gt;LinkedList&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Memory Management&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic resizing&lt;/strong&gt;: Capacity grows automatically as elements are added&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Growth policy&lt;/strong&gt;: Not specified, but adding elements has constant amortized cost&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Capacity optimization&lt;/strong&gt;: Use &lt;code&gt;ensureCapacity(int)&lt;/code&gt; before bulk additions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory trimming&lt;/strong&gt;: Use &lt;code&gt;trimToSize()&lt;/code&gt; to minimize storage after removals&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a id="list-point-1-2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  Thread Safety &amp;amp; Concurrency
&lt;/h5&gt;

&lt;p&gt;&lt;strong&gt;Not Thread-Safe&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple threads accessing concurrently require external synchronization&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Synchronized wrapper&lt;/strong&gt;: &lt;code&gt;Collections.synchronizedList(new ArrayList(...))&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Must synchronize on wrapper object for iteration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Fail-Fast Iterators&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Throw &lt;code&gt;ConcurrentModificationException&lt;/code&gt; on structural modification during iteration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structural modifications&lt;/strong&gt;: add, remove, resize operations (not &lt;code&gt;set()&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Use iterator's own &lt;code&gt;remove()&lt;/code&gt;/&lt;code&gt;add()&lt;/code&gt; methods for safe modification&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Null Handling&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Permits null elements&lt;/strong&gt; (unlike unmodifiable lists)&lt;/li&gt;
&lt;li&gt;Search operations use &lt;code&gt;Objects.equals()&lt;/code&gt; for comparison&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cloning &amp;amp; Serialization&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;clone()&lt;/code&gt; returns &lt;strong&gt;shallow copy&lt;/strong&gt; (elements not cloned)&lt;/li&gt;
&lt;li&gt;Implements &lt;code&gt;Serializable&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Implements &lt;code&gt;RandomAccess&lt;/code&gt; marker interface&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a id="list-point-1-3"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  Common Pitfalls and best practices
&lt;/h5&gt;

&lt;p&gt;&lt;strong&gt;Performance optimization&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Bad: Frequent insertions at beginning&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// O(n) each time = O(n²) total&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Good: Use LinkedList for frequent insertions, or reverse logic&lt;/span&gt;
&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;LinkedList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;temp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// O(1) amortized&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;Collections&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;reverse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;temp&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// O(n) once&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Safe concurrent modification&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Bad: ConcurrentModificationException risk&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;remove&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Throws exception&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Good: Use iterator's remove method&lt;/span&gt;
&lt;span class="nc"&gt;Iterator&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;iterator&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;hasNext&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;remove&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Safe&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Better: Use removeIf (Java 8+)&lt;/span&gt;
&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;removeIf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Memory efficiency&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Good: Trim after bulk removals&lt;/span&gt;
&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;removeIf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;trimToSize&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Reduce memory footprint&lt;/span&gt;

&lt;span class="c1"&gt;// Good: Pre-size collections&lt;/span&gt;
&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;inputSize&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a id="list-point-1-4"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  Comparison with alternatives
&lt;/h5&gt;

&lt;p&gt;&lt;strong&gt;ArrayList vs LinkedList&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ArrayList&lt;/strong&gt;: Better for random access, iteration, memory efficiency&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LinkedList&lt;/strong&gt;: Better for frequent insertions/deletions in middle&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;ArrayList vs Vector&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ArrayList&lt;/strong&gt;: Unsynchronized, better performance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vector&lt;/strong&gt;: Synchronized, legacy, generally avoid&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;ArrayList vs Unmodifiable Lists&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ArrayList&lt;/strong&gt;: Mutable, allows nulls, larger memory footprint&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;List.of()&lt;/strong&gt;: Immutable, no nulls, optimized, value-based&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a id="list-point-1-5"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  Exception Handling
&lt;/h5&gt;

&lt;p&gt;&lt;strong&gt;Common Exceptions&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;IndexOutOfBoundsException&lt;/code&gt;: Invalid index access&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;NoSuchElementException&lt;/code&gt;: &lt;code&gt;getFirst()&lt;/code&gt;/&lt;code&gt;getLast()&lt;/code&gt; on empty list&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ConcurrentModificationException&lt;/code&gt;: Concurrent structural modification&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;NullPointerException&lt;/code&gt;: Null collection passed to constructor/addAll&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Validation Patterns&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Safe access patterns&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isEmpty&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getFirst&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Safe&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Bounds checking&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Safe&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a id="list-point-2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  LinkedList
&lt;/h4&gt;

&lt;p&gt;&lt;a id="list-point-2-1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  &lt;strong&gt;Core Architecture&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;&lt;strong&gt;Doubly-Linked List Implementation&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Node Structure&lt;/strong&gt;: Each element contains data + forward/backward pointers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory Layout&lt;/strong&gt;: Non-contiguous memory allocation (unlike &lt;code&gt;ArrayList&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a id="list-point-2-2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  Performance Characteristics
&lt;/h5&gt;

&lt;p&gt;&lt;strong&gt;Time Complexities&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Constant Time O(1)&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;addFirst()&lt;/code&gt;, &lt;code&gt;addLast()&lt;/code&gt;, &lt;code&gt;removeFirst()&lt;/code&gt;, &lt;code&gt;removeLast()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;getFirst()&lt;/code&gt;, &lt;code&gt;getLast()&lt;/code&gt;, &lt;code&gt;peekFirst()&lt;/code&gt;, &lt;code&gt;peekLast()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;size()&lt;/code&gt;, &lt;code&gt;isEmpty()&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Linear Time O(n)&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;get(index)&lt;/code&gt;, &lt;code&gt;set(index, element)&lt;/code&gt; - &lt;strong&gt;traversal required&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;add(index, element)&lt;/code&gt;, &lt;code&gt;remove(index)&lt;/code&gt; - &lt;strong&gt;traversal + insertion/deletion&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;indexOf()&lt;/code&gt;, &lt;code&gt;lastIndexOf()&lt;/code&gt;, &lt;code&gt;contains()&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Index-Based Access Optimization&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// LinkedList optimizes traversal by choosing shortest path&lt;/span&gt;
&lt;span class="c1"&gt;// For index &amp;lt; size/2: traverse from beginning&lt;/span&gt;
&lt;span class="c1"&gt;// For index &amp;gt;= size/2: traverse from end&lt;/span&gt;
&lt;span class="no"&gt;E&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Automatically optimized&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a id="list-point-2-3"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  Thread Safety &amp;amp; Concurrency
&lt;/h5&gt;

&lt;p&gt;&lt;strong&gt;Not Thread-Safe&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No internal synchronization&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Synchronized wrapper&lt;/strong&gt;: &lt;code&gt;Collections.synchronizedList(new LinkedList&amp;lt;&amp;gt;())&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Must synchronize on wrapper object for iteration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Fail-Fast Iterators&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Bad: Will throw ConcurrentModificationException&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;linkedList&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;linkedList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;remove&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Structural modification during iteration&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Good: Use iterator's remove method&lt;/span&gt;
&lt;span class="nc"&gt;Iterator&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;linkedList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;iterator&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;hasNext&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;remove&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Safe structural modification&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a id="list-point-2-4"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  Dequeue Operations
&lt;/h5&gt;

&lt;p&gt;&lt;strong&gt;Stack operations&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// LIFO (Last In, First Out)&lt;/span&gt;
&lt;span class="n"&gt;linkedList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;        &lt;span class="c1"&gt;// Add to front&lt;/span&gt;
&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;top&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;linkedList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;pop&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;   &lt;span class="c1"&gt;// Remove from front&lt;/span&gt;

&lt;span class="c1"&gt;// Equivalent operations&lt;/span&gt;
&lt;span class="n"&gt;linkedList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addFirst&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;    &lt;span class="c1"&gt;// Same as push()&lt;/span&gt;
&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;linkedList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;removeFirst&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Same as pop()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Queue operations&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// FIFO (First In, First Out)&lt;/span&gt;
&lt;span class="n"&gt;linkedList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;offer&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;       &lt;span class="c1"&gt;// Add to end&lt;/span&gt;
&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;linkedList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;poll&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Remove from front&lt;/span&gt;

&lt;span class="c1"&gt;// Null-safe variants&lt;/span&gt;
&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;peek&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;linkedList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;peek&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;      &lt;span class="c1"&gt;// Returns null if empty&lt;/span&gt;
&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;linkedList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;element&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Throws NoSuchElementException if empty&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a id="list-point-2-5"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  When to use LinkedList VS ArrayList
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Excellent for frequent insertions/deletions at ends&lt;/span&gt;
&lt;span class="nc"&gt;Deque&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;deque&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;LinkedList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
&lt;span class="n"&gt;deque&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addFirst&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"item1"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// O(1)&lt;/span&gt;
&lt;span class="n"&gt;deque&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addLast&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"item2"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// O(1)&lt;/span&gt;

&lt;span class="c1"&gt;// Good for frequent insertions/deletions in middle (if you have iterator)&lt;/span&gt;
&lt;span class="nc"&gt;ListIterator&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;linkedList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;listIterator&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;someIndex&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newElement&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// O(1) at iterator position&lt;/span&gt;

&lt;span class="c1"&gt;// Stack/Queue operations&lt;/span&gt;
&lt;span class="nc"&gt;Stack&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;stack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;LinkedList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Use as stack&lt;/span&gt;
&lt;span class="nc"&gt;Queue&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;queue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;LinkedList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Use as queue&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;LinkedList Disadvantages&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Poor for random access&lt;/span&gt;
&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;linkedList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// O(n) - must traverse 1000 nodes&lt;/span&gt;

&lt;span class="c1"&gt;// Higher memory overhead per element&lt;/span&gt;
&lt;span class="c1"&gt;// Each node: data + 2 pointers (next/previous) + object overhead&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a id="list-point-2-6"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  Common LinkedList Anti-Patterns
&lt;/h5&gt;

&lt;p&gt;&lt;strong&gt;Avoid random access&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Bad: O(n²) complexity&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;linkedList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;linkedList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Each get() is O(n)&lt;/span&gt;
    &lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Good: O(n) complexity&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;linkedList&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Enhanced for-loop uses iterator&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Avoid size based decisions&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Bad: Inefficient size checks in loops&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;linkedList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  &lt;span class="c1"&gt;// size() is O(1) but unnecessary&lt;/span&gt;
    &lt;span class="n"&gt;linkedList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;removeFirst&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Good: Direct empty check&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;linkedList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isEmpty&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;linkedList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;removeFirst&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a id="list-point-2-7"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  Exception Handling
&lt;/h5&gt;

&lt;p&gt;&lt;strong&gt;Common exceptions&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;IndexOutOfBoundsException&lt;/code&gt;: Invalid index access (&lt;code&gt;get()&lt;/code&gt;, &lt;code&gt;set()&lt;/code&gt;, &lt;code&gt;add(index)&lt;/code&gt;, &lt;code&gt;remove(index)&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;NoSuchElementException&lt;/code&gt;: Empty list access (&lt;code&gt;getFirst()&lt;/code&gt;, &lt;code&gt;getLast()&lt;/code&gt;, &lt;code&gt;removeFirst()&lt;/code&gt;, &lt;code&gt;removeLast()&lt;/code&gt;, &lt;code&gt;element()&lt;/code&gt;, &lt;code&gt;pop()&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ConcurrentModificationException&lt;/code&gt;: Concurrent structural modification during iteration&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;NullPointerException&lt;/code&gt;: Null collection in constructor&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Safe Access patterns&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Safe first/last access&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;linkedList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isEmpty&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;linkedList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getFirst&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Safe&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;linkedList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getLast&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;   &lt;span class="c1"&gt;// Safe&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Null-safe queue operations&lt;/span&gt;
&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;linkedList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;poll&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;     &lt;span class="c1"&gt;// Returns null if empty&lt;/span&gt;
&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;peek&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;linkedList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;peek&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;     &lt;span class="c1"&gt;// Returns null if empty&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a id="list-point-2-8"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  Use case matrix and Best Practices
&lt;/h5&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operation Type&lt;/th&gt;
&lt;th&gt;LinkedList&lt;/th&gt;
&lt;th&gt;ArrayList&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Sequential Access&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Excellent&lt;/td&gt;
&lt;td&gt;✅ Excellent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Random Access&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ Poor O(n)&lt;/td&gt;
&lt;td&gt;✅ Excellent O(1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Insert/Delete at Ends&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Excellent O(1)&lt;/td&gt;
&lt;td&gt;✅ Good (amortized)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Insert/Delete in Middle&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Good O(1) at position&lt;/td&gt;
&lt;td&gt;❌ Poor O(n)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Memory Usage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ Higher overhead&lt;/td&gt;
&lt;td&gt;✅ Lower overhead&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cache Performance&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ Poor locality&lt;/td&gt;
&lt;td&gt;✅ Excellent locality&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Stack/Queue Operations&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Perfect fit&lt;/td&gt;
&lt;td&gt;✅ Usable&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;LinkedList Best Practices&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Use LinkedList when&lt;/strong&gt;: Frequent insertions/deletions, stack/queue operations, unknown size with many modifications&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use ArrayList when&lt;/strong&gt;: Random access needed, memory efficiency important, mostly read operations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Always use enhanced for-loops&lt;/strong&gt; or iterators for traversal&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consider ArrayDeque&lt;/strong&gt; for pure stack/queue operations (often better performance)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Synchronize externally&lt;/strong&gt; for concurrent access&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use fail-fast behavior&lt;/strong&gt; for debugging, not program logic&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a id="list-point-3"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Comparison and summary: List
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Hierarchy of the list interface&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface List
class LinkedList
class ArrayList
class Stack
class Vector

LinkedList ..|&amp;gt; List : implements
ArrayList ..|&amp;gt; List
Stack --|&amp;gt; Vector
Vector ..|&amp;gt; List

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;th&gt;ArrayList&lt;/th&gt;
&lt;th&gt;LinkedList&lt;/th&gt;
&lt;th&gt;Reason&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Random Access (get/set by index)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ &lt;strong&gt;Choose&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;❌ Avoid&lt;/td&gt;
&lt;td&gt;ArrayList: O(1) vs LinkedList: O(n)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Sequential Iteration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Good&lt;/td&gt;
&lt;td&gt;✅ Good&lt;/td&gt;
&lt;td&gt;Both are O(n), ArrayList has better cache locality&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Insert/Delete at Beginning&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ Slow&lt;/td&gt;
&lt;td&gt;✅ &lt;strong&gt;Choose&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;ArrayList: O(n) vs LinkedList: O(1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Insert/Delete at End&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ &lt;strong&gt;Choose&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;✅ Good&lt;/td&gt;
&lt;td&gt;ArrayList: O(1) amortized vs LinkedList: O(1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Insert/Delete in Middle&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ Slow&lt;/td&gt;
&lt;td&gt;✅ &lt;strong&gt;Choose&lt;/strong&gt; (if you have position)&lt;/td&gt;
&lt;td&gt;ArrayList: O(n) vs LinkedList: O(1) at iterator position&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Memory Efficiency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ &lt;strong&gt;Choose&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;❌ Higher overhead&lt;/td&gt;
&lt;td&gt;ArrayList: contiguous arrays vs LinkedList: node objects&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cache Performance&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ &lt;strong&gt;Choose&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;❌ Poor locality&lt;/td&gt;
&lt;td&gt;ArrayList: excellent cache locality&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Stack/Queue Operations&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Usable&lt;/td&gt;
&lt;td&gt;✅ &lt;strong&gt;Choose&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;LinkedList implements Deque interface&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Unknown Size, Many Modifications&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ May resize frequently&lt;/td&gt;
&lt;td&gt;✅ &lt;strong&gt;Choose&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;LinkedList grows dynamically without copying&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;🧠 Recommendations&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Default Choice: ArrayList&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Use ArrayList as your default List implementation&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Better performance for most common operations&lt;/li&gt;
&lt;li&gt;Lower memory overhead&lt;/li&gt;
&lt;li&gt;Better cache locality&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Switch to LinkedList when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Frequent insertions/deletions at the beginning&lt;/li&gt;
&lt;li&gt;Using as a stack, queue, or deque&lt;/li&gt;
&lt;li&gt;Frequent insertions/deletions in the middle with iterator&lt;/li&gt;
&lt;li&gt;Unknown size with many structural modifications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Consider ArrayDeque when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Primary use case is stack or queue operations&lt;/li&gt;
&lt;li&gt;Often provides better performance than LinkedList for deque operations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Migration Path&lt;/strong&gt;&lt;br&gt;
When changing between implementations, ensure your code doesn't rely on implementation-specific behavior:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Good: Program to interface&lt;/span&gt;
&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;createList&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;  &lt;span class="c1"&gt;// Factory method&lt;/span&gt;

&lt;span class="c1"&gt;// Avoid: Direct implementation coupling  &lt;/span&gt;
&lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;arrayList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;  &lt;span class="c1"&gt;// Hard to change later&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a id="list-point-4"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt; &lt;a href="https://docs.oracle.com/en/java/javase/25/docs/api//java.base/java/util/List.html" rel="noopener noreferrer"&gt;https://docs.oracle.com/en/java/javase/25/docs/api//java.base/java/util/List.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; &lt;a href="https://docs.oracle.com/en/java/javase/25/docs/api//java.base/java/util/ArrayList.html" rel="noopener noreferrer"&gt;https://docs.oracle.com/en/java/javase/25/docs/api//java.base/java/util/ArrayList.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; &lt;a href="https://docs.oracle.com/en/java/javase/25/docs/api//java.base/java/util/LinkedList.html" rel="noopener noreferrer"&gt;https://docs.oracle.com/en/java/javase/25/docs/api//java.base/java/util/LinkedList.html&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>java</category>
      <category>performance</category>
    </item>
    <item>
      <title>A comprehensive guide to Map in Java</title>
      <dc:creator>Irvin Gil</dc:creator>
      <pubDate>Sat, 01 Nov 2025 15:03:45 +0000</pubDate>
      <link>https://dev.to/ehrbhein/a-comprehensive-guide-to-usage-of-map-in-java-10ja</link>
      <guid>https://dev.to/ehrbhein/a-comprehensive-guide-to-usage-of-map-in-java-10ja</guid>
      <description>&lt;p&gt;&lt;em&gt;In this post, we take a closer look at Maps in Java, examining each implementation of the Map interface 🔍. By the end, you'll have a clearer understanding of the use cases for each class—and when to use ✅ or avoid them 🙅‍♂️.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A Map is an object that maps keys to values. A map cannot contain duplicate keys; each key can map to at most one value.&lt;/p&gt;

&lt;p&gt;The interface provides 3 collection views which allows it's contents to be viewed as:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;set of keys&lt;/li&gt;
&lt;li&gt;collection of values&lt;/li&gt;
&lt;li&gt;or set of key-value mappings&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The &lt;em&gt;order&lt;/em&gt; of a map is defined as the order in which the iterators on the map's collection views return their elements.&lt;br&gt;
Implementations such as &lt;code&gt;TreeMap&lt;/code&gt; make specific guarantees to their order; others, like &lt;code&gt;HashMap&lt;/code&gt; does not.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;⚠️ Great care must be exercised if mutable objects are used as map keys. The behavior of a map is not specified if the value of an object is changed in a manner that affects equals comparisons while the object is a key in the map. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Unmodifiable Map
&lt;/h3&gt;

&lt;p&gt;Unmodifiable maps are immutable map instances created using static factory methods like &lt;code&gt;Map.of()&lt;/code&gt;, &lt;code&gt;Map.ofEntries()&lt;/code&gt;, and &lt;code&gt;Map.copyOf()&lt;/code&gt;. These provide a convenient way to create read-only maps.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Characteristics&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;1. &lt;strong&gt;Immutability&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keys and values &lt;strong&gt;cannot be added, removed, or updated&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Any mutator method calls will throw &lt;code&gt;UnsupportedOperationException&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;However, if contained keys/values are themselves mutable, the map behavior may appear inconsistent&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;2. &lt;strong&gt;Null Restrictions&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Null keys and values are disallowed&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Attempts to create with null keys/values result in &lt;code&gt;NullPointerException&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;This is stricter than regular HashMap which allows nulls&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;3. &lt;strong&gt;Duplicate Key Prevention&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Duplicate keys are &lt;strong&gt;rejected at creation time&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Results in &lt;code&gt;IllegalArgumentException&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Ensures map integrity from the start&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;4. &lt;strong&gt;Iteration Order&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Iteration order is unspecified and subject to change&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Don't rely on any particular ordering&lt;/li&gt;
&lt;li&gt;Different from LinkedHashMap which maintains insertion order&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;5. &lt;strong&gt;Value-Based Nature&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Instances are value-based - treat equal instances as interchangeable&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't use for synchronization&lt;/strong&gt; - unpredictable behavior may occur&lt;/li&gt;
&lt;li&gt;Don't make assumptions about instance identity&lt;/li&gt;
&lt;li&gt;Factories may create new instances or reuse existing ones&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best Practices&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Good Use Cases&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Configuration data that shouldn't change&lt;/li&gt;
&lt;li&gt;Constant lookup tables&lt;/li&gt;
&lt;li&gt;API responses that should remain immutable&lt;/li&gt;
&lt;li&gt;Default values or fallback data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;❌ &lt;strong&gt;Avoid When&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You need to modify the map after creation&lt;/li&gt;
&lt;li&gt;You need null keys or values&lt;/li&gt;
&lt;li&gt;You require specific iteration order&lt;/li&gt;
&lt;li&gt;You need to use the map for synchronization&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Common Pitfalls&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Assuming mutability&lt;/strong&gt;: Remember these maps are completely immutable&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Null handling&lt;/strong&gt;: Unlike HashMap, nulls will cause exceptions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Iteration order&lt;/strong&gt;: Don't rely on any specific order&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Synchronization&lt;/strong&gt;: Don't use for thread synchronization primitives&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Identity assumptions&lt;/strong&gt;: Don't rely on object identity, use &lt;code&gt;.equals()&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Performance Notes&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generally more memory-efficient than regular HashMap for small, fixed datasets&lt;/li&gt;
&lt;li&gt;Optimized for read operations&lt;/li&gt;
&lt;li&gt;No overhead for modification tracking since they're immutable&lt;/li&gt;
&lt;li&gt;Iteration performance is predictable: O(size) rather than O(capacity)&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Common known implementation classes of Map Interface
&lt;/h3&gt;

&lt;h4&gt;
  
  
  HashMap
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;HashTable&lt;/code&gt; implementation of the &lt;code&gt;Map&lt;/code&gt; interface&lt;/li&gt;
&lt;li&gt;provides all of the optional map operations and permits &lt;code&gt;null&lt;/code&gt; values and the &lt;code&gt;null&lt;/code&gt; key. It's the roughly the equivalent to &lt;code&gt;HashTable&lt;/code&gt;, except that it's unsynchronized and permits null)&lt;/li&gt;
&lt;li&gt;Note that this implementation is &lt;strong&gt;not synchronized&lt;/strong&gt;. If multiple threads access a hash map concurrently, and at least one of the threads modifies the map structurally, it &lt;em&gt;must&lt;/em&gt; be synchronized externally. (A structural modification is any operation that adds or deletes one or more mappings; merely changing the value associated with a key that an instance already contains is not a structural modification.) This is typically accomplished by synchronizing on some object that naturally encapsulates the map. If no such object exists, the map should be "wrapped" using the &lt;a href="https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#synchronizedMap-java.util.Map-" rel="noopener noreferrer"&gt;&lt;code&gt;Collections.synchronizedMap&lt;/code&gt;&lt;/a&gt; method. This is best done at creation time, to prevent accidental unsynchronized access to the map:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;  &lt;span class="nc"&gt;Map&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Collections&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;synchronizedMap&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;(...));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Makes no guarantees as to the order of the map; and does guarantee that the order will remain constant over time.&lt;/li&gt;
&lt;li&gt;provides constant time performance for operations: &lt;code&gt;get&lt;/code&gt; and &lt;code&gt;put&lt;/code&gt; (&lt;code&gt;O(1)&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Iteration over collections view requires time proportional to the "capacity" of the instance (number of buckets) plus the size (the number of key-value mapping).

&lt;ul&gt;
&lt;li&gt;Thus, it's very important not to set the initial capacity too high (or the load factor too low) if iteration performance is important.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h4&gt;
  
  
  TreeMap
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;A Red-Black tree based &lt;a href="https://docs.oracle.com/javase/8/docs/api/java/util/NavigableMap.html" rel="noopener noreferrer"&gt;&lt;code&gt;NavigableMap&lt;/code&gt;&lt;/a&gt; implementation. The map is sorted according to the &lt;a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html" rel="noopener noreferrer"&gt;natural ordering&lt;/a&gt; of its keys, or by a &lt;a href="https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html" rel="noopener noreferrer"&gt;&lt;code&gt;Comparator&lt;/code&gt;&lt;/a&gt; provided at map creation time, depending on which constructor is used.&lt;/li&gt;
&lt;li&gt;This implementation provides &lt;code&gt;log(n)&lt;/code&gt; time cost for the &lt;code&gt;containsKey&lt;/code&gt;, &lt;code&gt;get&lt;/code&gt;, &lt;code&gt;put&lt;/code&gt; and &lt;code&gt;remove&lt;/code&gt; operations&lt;/li&gt;
&lt;li&gt;This map implementation is &lt;strong&gt;not synchronized&lt;/strong&gt;. But can be synchronized by wrapping it with &lt;code&gt;Collections.synchronizedSortedMap&lt;/code&gt; method, which is best done at creation time, to prevent accidental unsynchronized access to the map.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;  &lt;span class="nc"&gt;SortedMap&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Collections&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;synchronizedSortedMap&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TreeMap&lt;/span&gt;&lt;span class="o"&gt;(...));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Works best if sorting is important in the implementation use case. But trades some performance for &lt;code&gt;put&lt;/code&gt;, &lt;code&gt;get&lt;/code&gt; and &lt;code&gt;remove&lt;/code&gt; operations&lt;/li&gt;
&lt;/ul&gt;




&lt;h4&gt;
  
  
  HashTable
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;This class implements a hash table, which maps keys to values. Any non-&lt;code&gt;null&lt;/code&gt; object can be used as a key or as a value (null objects are not allowed to be used as keys or values).&lt;/li&gt;
&lt;li&gt;To successfully store and retrieve objects from a hashtable, the objects used as keys must implement the &lt;code&gt;hashCode&lt;/code&gt; method and the &lt;code&gt;equals&lt;/code&gt; method.&lt;/li&gt;
&lt;li&gt;An instance of &lt;code&gt;Hashtable&lt;/code&gt; has two parameters that affect its performance: &lt;em&gt;initial capacity&lt;/em&gt; and &lt;em&gt;load factor&lt;/em&gt;.

&lt;ul&gt;
&lt;li&gt;Capacity

&lt;ul&gt;
&lt;li&gt;The &lt;em&gt;capacity&lt;/em&gt; is the number of &lt;em&gt;buckets&lt;/em&gt; in the hash table, and the &lt;em&gt;initial capacity&lt;/em&gt; is simply the capacity at the time the hash table is created.&lt;/li&gt;
&lt;li&gt;Note that the hash table is &lt;em&gt;open&lt;/em&gt;: in the case of a "hash collision", where a single bucket stores multiple entries, which must be searched sequentially.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Load factor

&lt;ul&gt;
&lt;li&gt;The load factor is a measure of how full the hash table is allowed to get before its capacity is automatically increased.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;The initial capacity and load factor parameters are merely hints to the implementation. The exact details as to when and whether the rehash method is invoked are implementation-dependent.&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;li&gt;Unlike the new collection implementations, &lt;strong&gt;Hashtable is synchronized&lt;/strong&gt;. 

&lt;ul&gt;
&lt;li&gt;If a thread-safe implementation is not needed, it is recommended to use &lt;a href="https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/HashMap.html" rel="noopener noreferrer"&gt;&lt;code&gt;HashMap&lt;/code&gt;&lt;/a&gt; in place of &lt;code&gt;Hashtable&lt;/code&gt;. &lt;/li&gt;
&lt;li&gt;If a thread-safe highly-concurrent implementation is desired, then it is recommended to use ConcurrentHashMap in place of Hashtable.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h4&gt;
  
  
  SortedMap
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;a href="https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/Map.html" rel="noopener noreferrer"&gt;&lt;code&gt;Map&lt;/code&gt;&lt;/a&gt; that further provides a &lt;em&gt;total ordering&lt;/em&gt; on its keys. The map is ordered according to the &lt;a href="https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/lang/Comparable.html" rel="noopener noreferrer"&gt;natural ordering&lt;/a&gt; of its keys, or by a &lt;a href="https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/Comparator.html" rel="noopener noreferrer"&gt;&lt;code&gt;Comparator&lt;/code&gt;&lt;/a&gt; typically provided at sorted map creation time.&lt;/li&gt;
&lt;li&gt;All keys inserted into a sorted map must implement the &lt;code&gt;Comparable&lt;/code&gt; interface (or be accepted by the specified comparator).&lt;/li&gt;
&lt;li&gt;SortedMap does not allow null keys or null values. If we insert a null key or value it will throw an error.&lt;/li&gt;
&lt;li&gt;The primary class that implements SortedMap is TreeMap.&lt;/li&gt;
&lt;/ul&gt;




&lt;h4&gt;
  
  
  LinkedHashMap
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Differs from &lt;code&gt;HashMap&lt;/code&gt; implementation as it maintains doubly-linked list running through it's entries.This linked list defines the encounter order (the order of iteration), which is normally the order in which keys were inserted into the map (&lt;em&gt;insertion-order&lt;/em&gt;).

&lt;ul&gt;
&lt;li&gt;This linked list defines the encounter order (the order of iteration), which is normally the order in which keys were inserted into the map (&lt;em&gt;insertion-order&lt;/em&gt;).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;The reverse-ordered view of this map is in the opposite order, with the youngest entry appearing first and the eldest entry appearing last (use or &lt;code&gt;reversed()&lt;/code&gt; method).&lt;/li&gt;

&lt;li&gt;The encounter order of entries already in the map can be changed by using the &lt;code&gt;putFirst&lt;/code&gt; and &lt;code&gt;putLast&lt;/code&gt; methods.&lt;/li&gt;

&lt;li&gt;This class provides all of the optional &lt;code&gt;Map&lt;/code&gt; and &lt;code&gt;SequencedMap&lt;/code&gt; operations, and it permits null elements.&lt;/li&gt;

&lt;li&gt;It is not thread-safe; to synchronize it, use &lt;a href="https://www.geeksforgeeks.org/java/collections-synchronizedmap-method-in-java-with-examples/" rel="noopener noreferrer"&gt;Collections.synchronizedMap()&lt;/a&gt;.&lt;/li&gt;

&lt;li&gt;It provides constant-time performance (&lt;code&gt;O(1)&lt;/code&gt;) for the basic operations (add, contains and remove)&lt;/li&gt;

&lt;li&gt;Performance is likely to be just slightly below that of &lt;code&gt;HashMap&lt;/code&gt;, this is due to the expense of maintaining a linked list.&lt;/li&gt;

&lt;/ul&gt;

&lt;h5&gt;
  
  
  Re-insertion in LinkedHashMap
&lt;/h5&gt;

&lt;p&gt;Refers to the action of calling the &lt;code&gt;put(key, value)&lt;/code&gt; method with a &lt;strong&gt;key that already exists&lt;/strong&gt; in the map.&lt;/p&gt;

&lt;p&gt;When you call map.put(existingKey, newValue), the map checks if the existingKey is already present.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If it is, the &lt;strong&gt;old value&lt;/strong&gt; associated with that key is &lt;strong&gt;replaced&lt;/strong&gt; by the &lt;code&gt;newValue&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;put()&lt;/code&gt; method actually &lt;strong&gt;returns the &lt;em&gt;previous&lt;/em&gt; value&lt;/strong&gt; that was associated with the key, or &lt;code&gt;null&lt;/code&gt; if the key was new.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;  &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Integer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;scores&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
  &lt;span class="n"&gt;scores&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Alice"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Key is "Alice", value is 90&lt;/span&gt;

  &lt;span class="c1"&gt;// Key Re-insertion (Update)&lt;/span&gt;
  &lt;span class="nc"&gt;Integer&lt;/span&gt; &lt;span class="n"&gt;oldValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;scores&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Alice"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;95&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Key "Alice" exists, value is updated to 95 &lt;/span&gt;
  &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;oldValue&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// oldValue will be 90&lt;/span&gt;

  &lt;span class="c1"&gt;// The map now contains: {"Alice": 95}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, if you call &lt;code&gt;put()&lt;/code&gt; with an existing key in a &lt;code&gt;LinkedHashMap&lt;/code&gt;, the value is replaced, but the &lt;strong&gt;insertion order is NOT affected&lt;/strong&gt;. The key remains in its original position in the iteration order.&lt;/p&gt;




&lt;h4&gt;
  
  
  Comparison of LinkedHashMap and HashMap in terms of iteration
&lt;/h4&gt;

&lt;h5&gt;
  
  
  The HashMap Iteration: Proportional to Capacity (Buckets)
&lt;/h5&gt;

&lt;p&gt;A &lt;code&gt;HashMap&lt;/code&gt; is a classic Hash Table. It is internally implemented as an &lt;strong&gt;array of buckets&lt;/strong&gt; (also called slots or an entry table).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Iteration Process:&lt;/strong&gt; To iterate over a &lt;code&gt;HashMap&lt;/code&gt;, the iterator must:

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Traverse the entire array of buckets&lt;/strong&gt; (i.e., iterate from index 0 to &lt;code&gt;capacity - 1&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Check if a bucket is empty or contains an entry.&lt;/li&gt;
&lt;li&gt;If a bucket contains a linked list or tree of entries (due to hash collisions), it must then traverse that internal structure to find the actual key-value pairs.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Complexity: The time required is proportional to:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  O(Capacity + Size)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Problem with Overcapacity:&lt;/strong&gt; If you create a &lt;code&gt;HashMap&lt;/code&gt; with a large capacity but only insert a few entries (a low &lt;strong&gt;load factor&lt;/strong&gt;), the iterator still has to check all those empty buckets. This makes iteration inefficient.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Terms&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Capacity - The total size of the underlying array (number of buckets).&lt;/li&gt;
&lt;li&gt;Size - The actual number of key-value pairs stored in the map.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h5&gt;
  
  
  The LinkedHashMap Iteration: Proportional to Size (Entries)
&lt;/h5&gt;

&lt;p&gt;A &lt;code&gt;LinkedHashMap&lt;/code&gt; is a &lt;strong&gt;subclass of &lt;code&gt;HashMap&lt;/code&gt;&lt;/strong&gt; that adds an extra structure to solve the iteration problem and guarantee order.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Internal Structure:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;It has the same &lt;strong&gt;array of buckets (Hash Table)&lt;/strong&gt; as &lt;code&gt;HashMap&lt;/code&gt; for fast &lt;code&gt;get()&lt;/code&gt; and &lt;code&gt;put()&lt;/code&gt; operations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Crucially, it also maintains a separate, non-circular, doubly-linked list&lt;/strong&gt; that connects &lt;em&gt;every single entry&lt;/em&gt; in the map, in the order they were inserted (or accessed).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Iteration Process:&lt;/strong&gt; To iterate over a &lt;code&gt;LinkedHashMap&lt;/code&gt;, the iterator simply:

&lt;ol&gt;
&lt;li&gt;Starts at the head of the &lt;strong&gt;doubly-linked list&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Follows the &lt;code&gt;next&lt;/code&gt; reference from one entry to the next until it reaches the end of the list.&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Complexity:&lt;/strong&gt; The iteration only involves visiting the actual entries, regardless of how large the underlying bucket array is or how many buckets are empty.
&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  O(Size)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h6&gt;
  
  
  Summary Table
&lt;/h6&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
    &lt;thead&gt;
        &lt;tr&gt;
            &lt;td&gt;Feature&lt;/td&gt;
            &lt;td&gt;&lt;code&gt;HashMap&lt;/code&gt;&lt;/td&gt;
            &lt;td&gt;&lt;code&gt;LinkedHashMap&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;b&gt;Data Structure&lt;/b&gt;&lt;/td&gt;
            &lt;td&gt;Hash Table (array of buckets/lists/trees)&lt;/td&gt;
            &lt;td&gt;Hash Table &lt;b&gt;PLUS&lt;/b&gt; a Doubly-Linked List&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;b&gt;Guaranteed Order?&lt;/b&gt;&lt;/td&gt;
            &lt;td&gt;No (chaotic/unspecified)&lt;/td&gt;
            &lt;td&gt;Yes (Insertion Order or Access Order)&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;b&gt;Iteration Time&lt;/b&gt;&lt;/td&gt;
            &lt;td&gt;
                &lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;O&lt;/span&gt;&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&lt;span&gt;Capacity&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;Size&lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;/td&gt;
            &lt;td&gt;
                &lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;O&lt;/span&gt;&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&lt;span&gt;Size&lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;b&gt;Cost of Overhead&lt;/b&gt;&lt;/td&gt;
            &lt;td&gt;Lower memory footprint&lt;/td&gt;
            &lt;td&gt;
                Slightly higher memory (to store the &lt;code&gt;before&lt;/code&gt; and
                &lt;code&gt;after&lt;/code&gt; pointers for the linked list)
            &lt;/td&gt;
        &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h4&gt;
  
  
  Comparison and Summary
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Visualization Map Hierarchy&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8j89g8rjf3dypau850pz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8j89g8rjf3dypau850pz.png" alt="Visualization Map Hierarchy" width="565" height="298"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# plantuml
interface Map&amp;lt;K,V&amp;gt;
class HashMap&amp;lt;K,V&amp;gt;
class HashTable&amp;lt;K,V&amp;gt;
interface SortedMap&amp;lt;K,V&amp;gt;
class LinkedHashMap&amp;lt;K,V&amp;gt;
class TreeMap&amp;lt;K,V&amp;gt;


HashMap ..|&amp;gt; Map : null allowed
HashTable --|&amp;gt; Map : synchronized. null not allowed
SortedMap --|&amp;gt; Map : sorted
LinkedHashMap ..|&amp;gt; HashMap
TreeMap ..|&amp;gt; SortedMap

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;HashMap&lt;/th&gt;
&lt;th&gt;Hashtable&lt;/th&gt;
&lt;th&gt;TreeMap&lt;/th&gt;
&lt;th&gt;LinkedHashMap&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Accessing map element that rely on sorting&lt;/td&gt;
&lt;td&gt;❌ No sorting capability&lt;/td&gt;
&lt;td&gt;❌ No sorting capability&lt;/td&gt;
&lt;td&gt;✅ &lt;strong&gt;Best choice&lt;/strong&gt; - Natural ordering or custom Comparator&lt;/td&gt;
&lt;td&gt;❌ No sorting capability&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Accessing map element that rely on ordering of elements&lt;/td&gt;
&lt;td&gt;❌ No guaranteed order (chaotic)&lt;/td&gt;
&lt;td&gt;❌ No guaranteed order&lt;/td&gt;
&lt;td&gt;✅ Sorted order (ascending by default)&lt;/td&gt;
&lt;td&gt;✅ &lt;strong&gt;Best choice&lt;/strong&gt; - Insertion order or access order&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Constant time performance for &lt;code&gt;get&lt;/code&gt; and &lt;code&gt;put&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;✅ &lt;strong&gt;O(1)&lt;/strong&gt; average case&lt;/td&gt;
&lt;td&gt;✅ &lt;strong&gt;O(1)&lt;/strong&gt; average case&lt;/td&gt;
&lt;td&gt;❌ &lt;strong&gt;O(log n)&lt;/strong&gt; guaranteed&lt;/td&gt;
&lt;td&gt;✅ &lt;strong&gt;O(1)&lt;/strong&gt; average case&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost of overhead&lt;/td&gt;
&lt;td&gt;✅ &lt;strong&gt;Lowest&lt;/strong&gt; - Basic hash table&lt;/td&gt;
&lt;td&gt;✅ Low - Hash table + synchronization&lt;/td&gt;
&lt;td&gt;❌ &lt;strong&gt;Highest&lt;/strong&gt; - Red-Black tree structure&lt;/td&gt;
&lt;td&gt;❌ Higher - Hash table + doubly-linked list&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Iteration time&lt;/td&gt;
&lt;td&gt;❌ &lt;strong&gt;O(Capacity + Size)&lt;/strong&gt; - Can be expensive if capacity &amp;gt;&amp;gt; size&lt;/td&gt;
&lt;td&gt;❌ &lt;strong&gt;O(Capacity + Size)&lt;/strong&gt; - Can be expensive if capacity &amp;gt;&amp;gt; size&lt;/td&gt;
&lt;td&gt;✅ &lt;strong&gt;O(Size)&lt;/strong&gt; - Proportional to number of entries&lt;/td&gt;
&lt;td&gt;✅ &lt;strong&gt;O(Size)&lt;/strong&gt; - Proportional to number of entries&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Synchronized&lt;/td&gt;
&lt;td&gt;❌ &lt;strong&gt;Not synchronized&lt;/strong&gt; - Manual synchronization required&lt;/td&gt;
&lt;td&gt;✅ &lt;strong&gt;Fully synchronized&lt;/strong&gt; - Thread-safe&lt;/td&gt;
&lt;td&gt;❌ &lt;strong&gt;Not synchronized&lt;/strong&gt; - Manual synchronization required&lt;/td&gt;
&lt;td&gt;❌ &lt;strong&gt;Not synchronized&lt;/strong&gt; - Manual synchronization required&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;HashMap&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Best for&lt;/strong&gt;: General-purpose mapping with fastest performance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Structure&lt;/strong&gt;: Hash table (array of buckets)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Null support&lt;/strong&gt;: Allows null keys and values&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Thread safety&lt;/strong&gt;: Not synchronized&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Hashtable&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Best for&lt;/strong&gt;: Legacy applications requiring thread-safe maps&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Structure&lt;/strong&gt;: Hash table with synchronization&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Null support&lt;/strong&gt;: Does NOT allow null keys or values&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Thread safety&lt;/strong&gt;: Fully synchronized (all methods)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;TreeMap&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Best for&lt;/strong&gt;: Sorted maps, range operations, navigation methods&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Structure&lt;/strong&gt;: Red-Black tree (self-balancing BST)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Null support&lt;/strong&gt;: No null keys (but allows null values)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Special methods&lt;/strong&gt;: &lt;code&gt;firstKey()&lt;/code&gt;, &lt;code&gt;lastKey()&lt;/code&gt;, &lt;code&gt;headMap()&lt;/code&gt;, &lt;code&gt;tailMap()&lt;/code&gt;, &lt;code&gt;subMap()&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;LinkedHashMap&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Best for&lt;/strong&gt;: Maintaining insertion/access order with good performance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Structure&lt;/strong&gt;: Hash table + doubly-linked list&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Null support&lt;/strong&gt;: Allows null keys and values&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Order modes&lt;/strong&gt;: Insertion-order (default) or access-order&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Special feature&lt;/strong&gt;: Can implement LRU cache with &lt;code&gt;removeEldestEntry()&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Recommendations:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;For sorting requirements&lt;/strong&gt;: Use &lt;strong&gt;TreeMap&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;For ordering requirements&lt;/strong&gt;: Use &lt;strong&gt;LinkedHashMap&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;For maximum performance&lt;/strong&gt;: Use &lt;strong&gt;HashMap&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;For thread safety&lt;/strong&gt;: Use &lt;strong&gt;ConcurrentHashMap&lt;/strong&gt; (modern) or &lt;strong&gt;Hashtable&lt;/strong&gt; (legacy)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;For LRU cache&lt;/strong&gt;: Use &lt;strong&gt;LinkedHashMap&lt;/strong&gt; with access-order mode&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/TreeMap.html" rel="noopener noreferrer"&gt;https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/TreeMap.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/LinkedHashMap.html" rel="noopener noreferrer"&gt;https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/LinkedHashMap.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/HashMap.html" rel="noopener noreferrer"&gt;https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/HashMap.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/Hashtable.html" rel="noopener noreferrer"&gt;https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/Hashtable.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>java</category>
      <category>programming</category>
    </item>
    <item>
      <title>My Thoughts on Productivity – Being Fast or Being Comprehensive</title>
      <dc:creator>Irvin Gil</dc:creator>
      <pubDate>Thu, 21 Aug 2025 04:31:12 +0000</pubDate>
      <link>https://dev.to/ehrbhein/my-thoughts-on-productivity-being-fast-or-being-comprehensive-28k4</link>
      <guid>https://dev.to/ehrbhein/my-thoughts-on-productivity-being-fast-or-being-comprehensive-28k4</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; In this post, I’ll share my personal perspective on productivity: Is it better to be fast, or to be comprehensive? While my experiences as a software developer shape much of this discussion, I believe these ideas are relevant across many fields.&lt;/p&gt;

&lt;p&gt;The main reason I wrote this post is that I’ve recently reflected on my own performance at work. With the constant pressure of deadlines and the need to close tickets each sprint, I started to question which approach to productivity I should use. After some time contemplating, I’ve identified a few key points about both approaches, and when each might be most appropriate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Going Fast 🏎️ – The Need for Speed
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia4.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExYWd4cmRqaXk5cXdoaGx6ZTlweHQ1cWx1ZmI3NWNuNDIyZXMxa2U2aSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2FU3OMplvODpSNMxiwmK%2Fgiphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia4.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExYWd4cmRqaXk5cXdoaGx6ZTlweHQ1cWx1ZmI3NWNuNDIyZXMxa2U2aSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2FU3OMplvODpSNMxiwmK%2Fgiphy.gif" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Does This Make Sense? 🤷‍♂️
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;SLA and Performance Metrics&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Service level agreements (SLAs) and key performance indicators (KPIs) are common ways to measure productivity. When these metrics are the focus, it’s natural for people to aim to close as many tickets as quickly as possible.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Deadlines and Quotas&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In many roles, especially software development, strict deadlines are the norm. The demands of clients and stakeholders often can’t be pushed back, so delivering solutions quickly is sometimes necessary to meet expectations.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Freeing Up Time for Other Tasks or Teams&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Completing tasks quickly is often seen as a sign of productivity. In environments where teams depend on each other, finishing your work promptly can help others move forward with theirs.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Potential Pitfalls (I think 🤔)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;🤖 This approach can create a culture where people only do what’s asked, similar to a production line, without considering the broader impact after their part is done.&lt;/li&gt;
&lt;li&gt;🥷 In software development, focusing solely on speed may look productive—more tickets closed, more stories completed—but without thorough reviews and QA, quickly shipped code can introduce issues that surface later.&lt;/li&gt;
&lt;li&gt;🩹 The pressure to move fast can lead to short-term fixes or “band-aid” solutions, which may result in technical debt or require rework in future sprints.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Being Comprehensive 🧩 – Striving for Completeness
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia3.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExNGp4YmhqZGFqNG9jYmF4dHh3aGUzdzJnb2hwYnR4d3RkdmZpOHEzZiZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2F9PaC2UWEsnIG6nXcsn%2Fgiphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia3.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExNGp4YmhqZGFqNG9jYmF4dHh3aGUzdzJnb2hwYnR4d3RkdmZpOHEzZiZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2F9PaC2UWEsnIG6nXcsn%2Fgiphy.gif" width="480" height="303"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What Is This About? 🤔
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Mindfulness and Questioning the "Why"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Being mindful when working on tasks means seeking input from relevant people and ensuring alignment. This may require more communication, but it’s essential for effective collaboration. Mindfulness also means respecting your teammates’ work and boundaries, especially when working together on a feature.&lt;/p&gt;

&lt;p&gt;Asking “why” decisions are made is equally important. Understanding the reasoning behind choices helps us proceed carefully and make informed decisions, aligning with the team’s goals rather than just our own.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Ownership&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Taking responsibility for your work means ensuring features don’t break existing functionality. Even after deployment and testing, it’s important to consider potential edge cases.&lt;/p&gt;

&lt;p&gt;Ownership also involves being aware of how your changes affect the system and anticipating any new behaviors they might introduce.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Writing and Surfacing Documentations&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Beyond meeting acceptance criteria and testing, writing documentation is crucial. It’s easy to overlook documentation, especially as implementations change during review and testing. However, documentation should be part of the acceptance criteria to ensure changes are communicated to users, other developers and non-technical members of the team.&lt;/p&gt;

&lt;p&gt;If there are technical debts that are incurred during the development of a feature. Writing documentation helps preserve the context of why such decisions were made in the first place. So when time comes to revisit it, the documentation is updated with the context needed to "pay" the tech debt.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The Potential Pitfalls of Being Comprehensive 🕳️
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;🧐 Trying to address every possible scenario can lead to over-optimization. During research, it’s easy to get sidetracked by information outside the current task’s scope, which can be inefficient.&lt;/li&gt;
&lt;li&gt;😵‍💫 Being thorough can sometimes lead to overthinking, resulting in analysis paralysis and hesitation to implement solutions. It’s easy to fall into a rabbit hole of ideas, worrying about potential conflicts.&lt;/li&gt;
&lt;li&gt;🐌 This approach can be slower and may require multiple iterations before a task is considered complete. Ensuring quality and completeness often means double- and triple-checking your work, which can delay progress on the project board.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  So, Which Approach Should I Choose?
&lt;/h2&gt;

&lt;p&gt;For me, using a combination of both approaches would be best. But it depends on the situation.&lt;/p&gt;

&lt;p&gt;If you have the time to work on a feature, try to be comprehensive and cover as much ground as possible. Ask questions and seek clarity—this will help you gain a solid understanding of the feature, the product, and the business logic. Strive for completeness without over-engineering your solution. Write documentation for the features you develop, and consider setting up monitoring and telemetry to track their performance.&lt;/p&gt;

&lt;p&gt;If you’re working on something urgent, such as a critical bug or incident, prioritize speed and aim to resolve the issue as quickly as possible. However, it’s important to “clean up” afterward: document the steps you took so that others—both technical and non-technical—can understand what happened. Practices like root cause analysis and incident post-mortems are valuable for building a habit of documenting incidents and sharing knowledge.&lt;/p&gt;

&lt;p&gt;Ultimately, it’s about choosing the right approach for the situation or even a little mix of both. The key is to quickly assess and decide which method to use for each task. There are no hard rules—just conventions and best practices. Discover what works for you, stick with it while it works, and be willing to adapt it 😉👍.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Factors for burnout as a software developer - part 2</title>
      <dc:creator>Irvin Gil</dc:creator>
      <pubDate>Sat, 14 Jun 2025 14:29:37 +0000</pubDate>
      <link>https://dev.to/ehrbhein/factors-for-burnout-as-a-software-developer-part-2-3jgf</link>
      <guid>https://dev.to/ehrbhein/factors-for-burnout-as-a-software-developer-part-2-3jgf</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; I’m continuing my series of posts discussing my personal take on the factors that contribute to developer burnout. I’ll also be sharing potential workarounds and my thoughts on how to address these issues before they take a toll. This is the second part of the series—if you haven’t read the first post, you can check it out &lt;a href="https://dev.to/ehrbhein/factors-for-burnout-as-a-software-developer-part-1-1l43"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The factors I’ll be covering in this post mainly reflect my experience working at a mid-to-large-sized software company, where multiple teams manage and develop different components of a distributed microservices architecture. That said, these insights may not fully apply to developers working in smaller teams or at startups.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔄 Managing dependencies
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What it looks like?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Waiting for another team to complete their part before you can release a feature or continue work on your end.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Imagine a scenario where two systems need to be integrated. Your team is responsible for one of the systems. As planning progresses, it becomes clear that the other team, which manages the second system, needs to develop an API to expose the necessary functionality for integration. At first glance, it may seem like your team has to wait for that API to be completed before starting integration work.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Repeated back-and-forth communication about issues that need fixing—issues that fall outside your team's scope and require action from another team.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;These are situations where the other team has completed a feature, but when your team begins integration, issues are discovered in the feature’s flows that need to be resolved on their side.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Failing, or being at risk of failing, to meet release commitments because necessary work is still pending with another team.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This is often a consequence of the above scenarios. Bottlenecks can occur when one team is blocked, waiting for another team to fix an issue—ultimately jeopardizing release deadlines.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Why I think this is a problem for developers is that, when this happens, you—as one of the developers on the team—end up feeling "stuck" and unable to ship the feature because something else needs to be fixed first. You might think this isn't a big deal, but issues like this slowly build up frustration over time and can eventually lead to burnout.&lt;/p&gt;

&lt;h3&gt;
  
  
  What can we do about it?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Acknowledge that dependencies are often unavoidable—plan proactively to communicate and track them effectively.&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;In any collaborative effort involving multiple developers, it's essential to establish clear communication guidelines and rules. This ensures everyone working on a feature stays aligned and informed, especially when discussions or changes occur.&lt;/li&gt;
&lt;li&gt;Collaboration tools like Confluence, Notion, or even Google Docs can be incredibly helpful. Choose tools that allow team members to comment, suggest edits, and contribute to shared specification documents.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Establish team agreements on expected timelines (ETAs) for shared dependencies.&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Sometimes, the other team may already be committed to different priorities and may not have resources immediately available to support your feature. This is especially common in large organizations where multiple efforts run in parallel.&lt;/li&gt;
&lt;li&gt;Instead of pushing for immediate developer resource allocation, ask the owning team for a clear commitment on when they can deliver the needed functionality. This fosters mutual respect and helps with realistic planning.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Shift the mindset from "us vs. them" to a collaborative "we."&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;At the end of the day, when we ship features, customers don’t see which team built which part—they see the company as a single entity delivering a solution.&lt;/li&gt;
&lt;li&gt;Recognizing this can help foster a sense of shared ownership and accountability across teams. Adopting a collaborative mindset builds stronger working relationships and better outcomes.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Practice empathy&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Don’t lose sight of the "human factor," especially in large teams. Some developers may be ramping up, learning new systems, or still figuring out solutions to their tasks.&lt;/li&gt;
&lt;li&gt;Show empathy and offer support where you can. Even small suggestions or a fresh perspective can help others get “unstuck” and move forward more confidently&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  🙀 Lack of context and the feeling of being left behind
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What does it look like?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Efforts are being made across the department or the wider organization that you're either unaware of or lack context about&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You've been working on a feature story of your own for a week. During stand-ups, others are discussing something that seems important to the team, but you know nothing about it. You stay focused on your own feature and hesitate to dig deeper into what else is happening&lt;/strong&gt;.

&lt;ul&gt;
&lt;li&gt;Some prime examples of this include conversations between product managers and senior developers about potential features that are being scoped and planned. Other examples can come in the form of cross-team developer efforts, such as framework version upgrades or improvements to the CI/CD workflow.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;You've been on a long holiday (two weeks), and when you return, it feels like &lt;em&gt;a lot&lt;/em&gt; has changed or been introduced during your absence&lt;/strong&gt;.

&lt;ul&gt;
&lt;li&gt;I’ve personally experienced this, and when I got back from holiday, it genuinely felt like I had been gone for too long. 🫠. &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Now, why I think this is a contributing factor to burnout is because the feeling of falling behind can be mentally draining for developers. As time goes on and more unfamiliar topics keep coming up in conversations, you can gradually develop a sense of “fear of missing out.” Many good developers—especially those who are committed to continuous learning—fall into the trap of trying to learn everything, which often leads to information overload.&lt;/p&gt;

&lt;p&gt;As a result, even though they make an effort to understand a wide range of topics, they often end up with only surface-level knowledge. In the worst cases, this can lead to frustration and mental fatigue from trying to absorb too much information in a short period of time. Most of the time, they don’t truly grasp the deeper meaning of the concepts they’re trying to learn.&lt;/p&gt;

&lt;h3&gt;
  
  
  What can we do about it?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Don't be too hard on yourself.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understand that you don’t have to learn everything at once—and most of the people you work with feel the same way. This is a common truth in the software industry, where things are constantly evolving: new tools, frameworks, and trends emerge all the time. What matters is not taking shortcuts—sit down, put in the effort, focus on learning the things you find valuable, and take things one step at a time.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Ask incremental questions.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ask questions that might seem basic. When you get an answer, follow up. Refine your questions based on what you've learned, and keep iterating until you can connect the dots and concepts. In a healthy software development team, no question is a dumb question.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Write things down and add them to your to-do list.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The phrase "out of sight, out of mind" definitely applies here. Writing things down—especially through journaling or note-taking—gives you the ability to revisit them when you have time. Maintaining a to-do list with topics you want to explore helps you stay connected to ideas you’re curious about, even if you can’t dive into them right away.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Block time on your calendar to read and explore topics that interest you.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This ties back to your to-do list. The best way to gain real understanding is to read source documents yourself—especially the ones everyone else is referencing. It may feel strange to take time to “just read” when you’re expected to write code and close tickets during company time, but investing that time pays off. Being informed directly, rather than secondhand, gives you clearer insight and builds long-term confidence.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  🗣️ Too many meetings / interactions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What does it look like?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Spending a significant amount of time chatting with other employees.&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;This might not be much of a problem in a remote work setup. But in an office environment—especially one where people feel comfortable casually interacting across roles—it can quickly consume your time. In open-office setups, spontaneous conversations are even more common and can easily lead to unintended distractions.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Frequently being asked to jump on a call to "take a look" at something or to explain a concept.&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;This often happens within your own team, but occasionally someone in a non-technical role will request a “quick 10-minute” meeting—which then stretches into 40 minutes as the conversation gets sidetracked. And let’s face it: being asked to jump on a call ASAP can break your momentum and focus. Once the call is over, you have to switch your context back to what you were doing—which eats up even more of your time.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;A large portion of your schedule/calendar blocked by meetings.&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;As you become a senior or more experienced member of the team, you’re often invited to more meetings than junior developers. These may include feature specification reviews, product planning sessions, and cross-functional syncs. Your input becomes important to ensure technical feasibility and to provide insights into how the feature will work end to end.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;I think this is a problem that often isn’t taken seriously enough. The core issue is context switching, which is a limitation all humans face—our brains need time to catch up and adjust to the information we consume and process, and too much of it becomes mentally exhausting. Simply being aware of this is just the first step; there are practical ways we can reduce excessive context switching and, in turn, improve our focus at work.&lt;/p&gt;

&lt;h3&gt;
  
  
  What can we do about it?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Be mindful of your time and set clear boundaries.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A commonly recommended strategy is to block off the time of day when you're most productive. This requires self-awareness—knowing when you naturally focus best. Once you identify that window, protect it by avoiding unnecessary meetings and distractions. Personally, I block off my morning hours, when I’m most energized and focused, so I can do deep work before the rest of the day fills up with interactions.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Find a balance—be willing to compromise, but make sure to write things down to avoid losing context.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Note-taking and journaling are incredibly valuable in software development. I strongly advocate for taking notes during meetings and discussions. This habit keeps your mind engaged and helps you maintain a clear grasp of what's being talked about. Notes also serve as a reliable reference point you can revisit anytime to recall decisions or discussions.&lt;/li&gt;
&lt;li&gt;Remember, you don’t have to say yes to every meeting invitation. Assess the purpose and ask yourself: &lt;em&gt;Does my presence add value for the team—and for me?&lt;/em&gt; It's okay to decline or request a summary when appropriate.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Don’t skip preparation.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Make it a practice to block 10 minutes before each meeting to prepare and collect your thoughts. This short buffer helps your brain shift context and gets you mentally ready—think of it as a warm-up before a workout or a marathon.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Practice empathy—especially for yourself.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This may sound familiar, but it's worth repeating: &lt;em&gt;Don’t be too hard on yourself.&lt;/em&gt; It's easy to get lost in the work and feel like you're not doing enough, or that you're not processing things quickly enough to keep up. In those moments, pause. Slow down, breathe, and appreciate the effort you've already put in. Progress often takes more time than we give ourselves credit for.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  🧘 Conclusion
&lt;/h2&gt;

&lt;p&gt;Burnout in software development often stems from more than just workload—it’s rooted in how we collaborate, communicate, and manage our time. In this post, I unpacked how managing inter-team dependencies, lack of context, and excessive meetings contribute to developer burnout—especially within larger, distributed software organizations.&lt;/p&gt;

&lt;p&gt;While these challenges are hard to eliminate, they can be managed through intentional practices like setting boundaries, improving cross-team alignment, and giving yourself space to learn and reset. Ultimately, fostering a collaborative, context-rich, and balanced work environment helps us build better software without compromising developer well-being.&lt;/p&gt;

&lt;p&gt;Although these shifts in mindset and habits may seem small, I believe they can make a significant difference in creating a healthier, more sustainable experience for software developers.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Officially a Benefexer: My Journey from Probation to Becoming the First Backend Software Engineer in the Cebu Office</title>
      <dc:creator>Irvin Gil</dc:creator>
      <pubDate>Sat, 30 Nov 2024 16:21:50 +0000</pubDate>
      <link>https://dev.to/ehrbhein/officially-a-benefexer-my-journey-from-probation-to-becoming-the-first-backend-software-engineer-hdo</link>
      <guid>https://dev.to/ehrbhein/officially-a-benefexer-my-journey-from-probation-to-becoming-the-first-backend-software-engineer-hdo</guid>
      <description>&lt;p&gt;&lt;strong&gt;TLDR:&lt;/strong&gt; I wanted to share snippets of my journey in battling the struggles of onboarding and the anxiety of being a probationary employee. I am not aiming to brag in this post but rather to inspire others in the tech and IT industry who are going through similar struggles as I did. I wanted to share some insights and perspectives that I learned and leveraged during my time on probation, in hopes that it will help others see the silver lining amidst the challenges they're facing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Onboarding
&lt;/h2&gt;

&lt;p&gt;Looking back at my first week, the benefex culture left a great impression on me regarding how they welcome new joiners to the company. Tech and office gear are provided to you as part of the welcome kit. I can't remember where I took the photo of the welcome kit, but they have something like the standard gift given to you on your first day 😅.&lt;/p&gt;

&lt;p&gt;The first week was filled with sessions that focused on the company values, rules and safety regulations, and, most of all, security policies. I was with four other people; there were five of us in the new joiner's batch at that time, and they were also fun to hang out with.&lt;/p&gt;

&lt;p&gt;As soon as I was given access to developer resources, I immediately got to work exploring the knowledge base while being careful not to make any changes to moving resources and tickets. It's like being a toddler again and exploring the nooks and crannies of a new house, but with awareness this time, of course 😊. Being a new joiner, I have my "I-am-new" card to play, which basically grants me the privilege to sit in meetings and ask people questions while their patience is at the "oh, you're new here" level. And the additional literal piece of mind and "can-chill-in-the-middle-of-the-shift" buff effects 🪄. But I know it won't last for long. I've been told several times to "take it at a learning pace" by others in the office as I am constantly seeking ways to get busy, or "look busy." And you know what? They were right; responsibilities will eventually come after you've grown into the role. So it's really about finding the balance between grinding on the job and taking things at a learning pace to avoid stressing yourself out.&lt;/p&gt;

&lt;h3&gt;
  
  
  First month
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Copping up with the timezone problem
&lt;/h4&gt;

&lt;p&gt;I am assigned to work with a remote team from the GMT+2 timezone (EU location), which is the timezone of our company's main office. I am on UTC+8 timezone by the way. I was made aware of this a month before I officially joined the company. What I did was strategize a plan for learning and developing new habits over a span of 1-2 weeks. I used time-blocking on my calendar to act as reminders for when I would eat and when I should sleep. The work to be done would still fall on me personally, of course, to develop the discipline to follow the things that I set.&lt;/p&gt;

&lt;p&gt;It felt really weird at first, since I am accustomed to waking up at 5 or 6 AM and getting out of bed. When I was learning this new schedule, I had to wake up at 9 AM to get 7-8 hours of sleep. I was bad at it for the first week, and I really tried to push myself to stay up until 12 or 1 AM. But hey, "if there's a will, there's a way." So, I got my act together and forced myself to follow the new schedule, all while making adjustments to my habits to ensure I didn't affect the number of hours I slept. I stopped doom scrolling and watching series an hour before I went to sleep, and I also made some changes to encourage drowsiness before bed, such as turning the lights completely off and not engaging with devices an hour before sleep.&lt;/p&gt;

&lt;p&gt;By the time I joined the company, I was already accustomed to the schedule. I am still working on it to this day, but I'd say that I was good enough at it when I joined the company. Enough to last the whole shift, at least 😄.&lt;/p&gt;

&lt;h4&gt;
  
  
  The onboarding developer experience
&lt;/h4&gt;

&lt;p&gt;Now we get to one of the best parts, the developer experience. Now the developer culture in benefex is great in a way that they give you the creative freedom on how you work and deliver your tasks. They'd let you choose your device, and what operating system you can use as long as you adhere to the security policies and company guidelines. I pushed my hardest to negotiate with the IT team that i be permitted to install and use Ubuntu-linux on my work laptop. And they agreed, but they could not promise the support when something breaks. TBH, i somehow low-key regret i did not choose the MacOS option till this day. That could be my only ticket to work on an apple device and i clearly missed it. But in my defense, i choose to work with Ubuntu because i've already have a developer workflow setup for it that is easy to re-setup again and again, so yeah, i traded of the opportunity to get my hands on an apple device for my own comfort.&lt;/p&gt;

&lt;p&gt;When it comes to setting up your developer environment, they have a runbook that you can follow on what things you can install and the options that you can use to setup the dependencies of the different tech stacks that are used for software development. I personally added my own flavor to the guide since the one that they got was for macOs and are using the brew package manager for installing the dependencies. And again, it's that creative freedom that they grant you for how you deliver your work. An absolute 👌.&lt;/p&gt;

&lt;p&gt;The only major thing that i noticed when working with their microservices is that they haven't really streamlined the process for running their services on local environment. I mean yeah sure, if you're a developer you can figure it out right? That is true, but the added benefit of having a streamlined way of running services saves developers from the mental drain and stress of trying to figure the system out. Patterns such as the &lt;a href="https://3musketeers.pages.dev/" rel="noopener noreferrer"&gt;three-musketeers&lt;/a&gt; helps to reduce this issues of running parts of the microservice system regardless of which environment. But yeah, i guess having the roles of developers and operations engineers separate has it's costs. And for me, this is definitely something that can be improved moving forward.&lt;/p&gt;

&lt;p&gt;It wasn't much of an issue for me getting accustomed with the tech stack on the java-springboot side of things since i myself worked on springboot microservice architecture back at my previous company. But i clearly am lacking for the application that were written in Go-lang. And i'll cover more of the things that i realize i need to learn later on.&lt;/p&gt;

&lt;h3&gt;
  
  
  Team cadence and ways of working
&lt;/h3&gt;

&lt;p&gt;My role in benefex is not really something that needs to cover a 24hour coverage so i am following the timezone of GMT+2 and their working hours. Although my line manager told me that he's open to which time i would prefer working, i still followed on my normal practiced schedule, which is mid shift in UTC+8.&lt;/p&gt;

&lt;p&gt;I must admit that i am in a bit of a shock when i started working with my team. Few words: "They don't dilly dally". They'd go and sit down and get things moving and done fast. Reviews and comments flying in and out of the github pull request. Reviews being requested in moments, the whole conversation is carried on in github and supplemented on the team channel. I was trying to catch up with things being talked about and as a new joiner, it hasn't been an easy time. This has been a shock for me since at my previous company, we dont have QA and so i would go on a ceremony for minutes to make checklist of the acceptance criterias that i need to check before conducting a code review and functionality testing. So yeah, i also had to make adjustments on how i'd do things since the process that i was accustomed to just isn't going to cut with how fast changes are being thrown back and forth through the PR.&lt;/p&gt;

&lt;p&gt;And what i find cool about working my new team is that they'd like to be straightforward on things and really take a small minute of their shift to jump in  a call to help you with your blockers. They are also very supportive and encourages people to ask questions whenever unsure so that everybody can give their thoughts and correct the understanding.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defining the learning curve
&lt;/h3&gt;

&lt;p&gt;Now one of the interesting things about the time when I joined is that the company had long planned to send two employees from the UK to Cebu to coach and work together with the newly formed engineering team in Cebu. I, along with three other guys from another engineering role, was up for the challenge of working with the team they were going to send over. Days moved on until the fateful week, when we finally got to meet Scott and Liam from the UK. Liam was set to mentor the other guys, while I worked with Scott. Scott showed me the ropes of the system stack, how we do deployments, the best practices currently being followed by the team, where we are now, and what we are trying to achieve—basically, the whole package of everything I needed to know, along with the opportunity to ask questions. I worked with them for two whole weeks and even went on trips with them on weekends during their stay in Cebu. I was really happy with all the new things I learned, though I also felt a bit lacking, as there were topics we discussed that I needed to see for myself to really understand.&lt;/p&gt;

&lt;p&gt;Some things I realized are that my knowledge of Java and Spring is still quite basic, and that the framework and language have much more to offer in terms of learning. Another point is that we are working with MongoDB, which is a NoSQL database, meaning I need to learn and get used to using it, as opposed to the relational databases I have been accustomed to, such as PostgreSQL. Lastly, there's the cloud infrastructure technology. Previously, I worked with AWS technologies for deploying and shipping software. Now, I have to learn Google Cloud Platform and Kubernetes deployment to understand how we shift and deploy software for our different products.&lt;/p&gt;

&lt;p&gt;Speaking of products, growing domain knowledge presents a whole new challenge. We have many emerging products, and although I am assigned to the API Gateway project, there will come a time when engineering resources need to be allocated to supplement the workload of other teams. Thus, I also need to account for learning the domains of these different products. To keep track of these things, I've taken the opportunity to write about my experiences and journal them, so I don't lose direction or my mind with all the information that needs to be learned.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcnt8l3pvi4l2shjshz3c.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcnt8l3pvi4l2shjshz3c.jpg" alt="product-engineering-team-ph" width="800" height="639"&gt;&lt;/a&gt;&lt;br&gt;Product engineering team PH along with Scott and Liam during one of our weekend trips.
  &lt;/p&gt;

&lt;h2&gt;
  
  
  Gaining traction
&lt;/h2&gt;

&lt;h4&gt;
  
  
  Taking on tasks and assuming ownership
&lt;/h4&gt;

&lt;p&gt;Weeks and days went by, and every day seemed like an opportunity to learn something new. Remember when I said earlier that my "new-hire" card wouldn't last forever? Well, the team decided that I should take on tasks bit by bit as part of the onboarding experience. And so I did. My first major task was addressing a tech debt by rewriting a service originally written in Go-lang into Java Spring Boot. And boy, I did not enjoy reading Go code. Maybe it was because I didn't really know it, but I made some progress by reading and familiarizing myself with some if-else patterns. Along with the help of the IDE’s IntelliSense magic, I was able to trace the code and slowly understand the logic of the application piece by piece. The way I tackled this was by drawing diagrams, mostly in C4, and also flow charts to illustrate the functions and responsibilities split between the different Go classes. I can't say I did a great job at understanding the Go code, but it was enough for me to devise a strategy for the Spring Boot implementation. We wrote a thousand lines on that rewrite, and up until now, the PR has just been stockpiled since we couldn't get QA resources to test it due to a lack of people. But since this was a tech debt task, it wasn't really major, and the Go service is stable, so it will be fine—for now at least.&lt;/p&gt;

&lt;p&gt;After that, I took on tasks to provide support by participating in code reviews. It was a good opportunity for me to learn things on the fly and understand the coding conventions we had on the engineering team as a whole. Our team was really small, with just two backend engineers, including myself, laser-focused on the project effort since it was a new and ambiguous endeavor for the company to develop APIs for integration with external systems. Bit by bit, I gained knowledge and got used to the coding style of my fellow engineer on the team, and I also received mentorship from him on things I didn't understand. With every PR merge I was involved in reviewing, I felt a sigh of relief that even if I was just checking out and reading someone else's code, I was still learning. I give myself a pat on the shoulder every time we close a ticket and mark it as done, and I try my best to maintain a professional demeanor even when things seem to be floating in the air and the situation is full of uncertainty. Because as everybody says, "we'll get there eventually."&lt;/p&gt;

&lt;h4&gt;
  
  
  Getting involved
&lt;/h4&gt;

&lt;p&gt;In my second month, I started to answer questions from other engineers who were newly hired to the team. Having been in their shoes myself, I really sympathized with their need for support, especially as new employees. I slowly began to raise my hand in meetings and ask questions about the domains when I got the chance, and asking questions helped me understand how we arrived at the current state of things. Most people tend to complain when there is something they don't understand or when things are handed to them and aren't as pretty or easy to work with. Instead of complaining, I shifted my questions to "Why was it done? What is the decision behind it?" This thinking has taught me empathy, allowing me to put myself in others' shoes and try to understand the trade-offs that were made. In software engineering, some problems are not as easy to solve as others, and that's when trade-offs and hard decisions are made. The people on the team are not shy about answering such questions, and I am really thankful for the level of openness that other engineers on the team have.&lt;/p&gt;

&lt;p&gt;Perhaps the most intimidating part of my experience as a developer at Benefex so far has been being included in the on-call alert support rotation. Now, I am not entirely scared about it, as I've held similar roles in my previous company. However, being new (just a few months) on the team gives me a daunting expectation. Scott reassured me that I can pair up with a senior engineer from the product-specific team if I need support for production access and action items. He mentioned that we just need everyone to take a share in looking into and investigating alerts to act as the primary layer of lookout and be able to triage them. So escalating to a senior team member is nothing to be ashamed of. So yes, I'm now with the other engineers on the support rota, and I’m kind of praying to the tech gods that I don’t get any incidents on my day of patrol. 😄&lt;/p&gt;

&lt;p&gt;I also became more involved in discussions on the knowledge base and made updates to pages that needed improvement. During times when I am not writing code and am looking for things to do, I read updates on the knowledge base across different areas just to stay informed about the information being revised, created, and the discussions surrounding them. I try to maintain this habit because being a developer doesn't just mean you're paid to write code. It's also our job as developers to maintain and create documentation and to get involved in the decisions that contribute to our collective efforts and products.&lt;/p&gt;

&lt;h4&gt;
  
  
  Hurdles I encountered
&lt;/h4&gt;

&lt;p&gt;Of course, my onboarding was not without its down moments. Aside from realizing the huge learning curve and knowledge gap that I needed to address, I also had to keep an eye on the things that are important and deliver value to the business. These are the items on the project board that need to be moved to "done." One way I tried to contribute was by double-checking the PRs that senior team members were working on. Even though I was just a second pair of eyes on the review, it was a great way to learn, especially when you're sometimes learning to do things on the fly.&lt;/p&gt;

&lt;p&gt;However, there was one review that I really struggled with. It involved setting up security for the gateway project, and I didn't have the knowledge of the concepts being used in the implementation. So, I took a quick course on Spring Security over the course of two days. I felt the need to complete the course quickly to grasp the material, or else I would never keep up with the conversations, and the quality of my review would suffer. I pushed myself during that time, taking notes so I could revisit the example implementations shown in the course. By the end of the two days, I was able to review the PR and found that the effort to take the course was truly worthwhile. I gained a basic understanding of the areas to focus on and how things worked, allowing me to provide feedback and request changes to improve the implementation in the PR.&lt;/p&gt;

&lt;p&gt;Another kind of problem I frequently encountered was the conversations happening between senior team members, where I often felt left out or like I was missing out. I needed to stay sharp and pay attention to things so that I could be useful, I told myself. I made some efforts to set up notifications on the team's knowledge bases to send me emails whenever there were changes to the pages, as well as updates on the team project board. I also organized my email folders so that related items were grouped together instead of just piling up in the inbox. Furthermore, I explored using GitHub notifications directly in the Chrome browser to alert me when there were conversations or PRs requesting my review, ensuring I wouldn't miss any updates.&lt;/p&gt;

&lt;p&gt;And lastly, with every new experience comes the hard struggle of understanding. Whenever I encounter a completely new concept, I feel sluggish working with it, and my progress often halts due to uncertainty and self-doubt. To combat this, i've practiced the habit of writing things down, even if I'm not getting the terms exactly right; I just write everything down. At other times, I invest time in mapping new concepts in my personal notes into diagrams that help me visualize my thoughts. Of course, some of these may not be entirely accurate since they are new to me, but translating my thoughts into something that allows me to associate concepts has been very advantageous. It also helps alleviate my tendency to overthink and doubt myself. As I write things down, I try to pep talk myself, reminding myself that "even if I haven't figured it out today, if I keep at this, I'll understand it eventually."&lt;/p&gt;

&lt;h4&gt;
  
  
  Making it official
&lt;/h4&gt;

&lt;p&gt;Three months as a Benefexer were quick, full of learning, fun, and most of all, very challenging for me. I've done things I haven't done before, such as collaborating with a lot of people in a face-to-face manner. I'd say that I haven't gotten much talking and hanging out with other people since I was mostly working remotely. I also picked up some stories and lessons from the new colleagues at the office, with whom I had deep conversations about their professional lives, which were really helpful for me as a growing professional.&lt;/p&gt;

&lt;p&gt;By my third month, I had already transitioned to a remote work setup since the role was advertised as remote. So, I am back in my apartment in the provincial region of the archipelago, which I also enjoy because I am close to my loved ones and the cost of living is much cheaper than living in the big city. My manager got a 360 review of me from the engineers that I worked with, and then I just waited.&lt;/p&gt;

&lt;p&gt;In our one-on-one, my manager happily shared with me the remarks and feedback from the other engineers, including his feedback on my performance. It was mostly positive, with some areas to improve, of course. But it was overall positive feedback ⭐. I was really overjoyed when it was made official and announced to the engineering team. I am really grateful to all the amazing people at Benefex for their support during my probationary period, along with my team and line manager.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzi8hh05k3nngdbixzsv4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzi8hh05k3nngdbixzsv4.png" alt="passing-probation-message" width="635" height="347"&gt;&lt;/a&gt;&lt;br&gt;Passing probationary message.
  &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Being a new joiner at a company has challenged me and, at the same time, made me anxious about my skills. As I conclude my narrative about how I navigated my probationary stage as a new joiner, I'd like to recap the things I have tried and learned on my journey:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;"Try to strike a balance with everything you do 🧘‍♀️"&lt;/strong&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This also applies when learning new concepts. As a new joiner, I have realized the things that I am lacking and that I need to work hard to supplement them. However, there are also things that need to be delivered that add value to the business. Having a balance between the time to learn and the time to work on delivering value is important, as too much of one can impact our performance as professionals.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;"Responsibilities will eventually come to you; take things at a learning pace 💆🏻‍♀️"&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I guess what I am trying to say here is to enjoy the time to learn when you are new to an organization. As the complexity of the role and the ways of working slowly reveal themselves, taking the right perspective and pace is important to avoid pushing yourself to the point of burnout. Onboarding only happens once when you join a new organization, so keep things interesting and fun.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;"Master the skill of developing habits and discipline 🎯"&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Change is constant when you are a developer and this also the same not matter what your profession. There's always something you are going to be chasing to learn. Mastering the skill of developing habits for learning new things, along with the discipline to keep going, creates a huge advantage for you not just as a professional but also as an individual. Don't be afraid to make adjustments to your habits if something is not working out, or if you need to change your habits for something that may benefit you, such as getting the appropriate hours of rest daily. You must build the discipline to maintain the habits that benefit you.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;"You'll figure things out eventually 😊"&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;New things are scary and weird to work with, especially since they are something you’re not used to. Bear in mind that this is part of growth, and that stepping out of your comfort zone is always the first step toward improvement. Figuring things out does not come with time alone, but with the effort you put in to try and understand something. Talking to other people and sharing your understanding can help you level the learning curve, as you can also learn from other people's perspectives on the concept. I find it surprising that I can wake up tomorrow with a more clarified understanding of something that was difficult for me to grasp yesterday. To share what I've done, I also thought hard about that concept before ending my day. This is truly an example of how we eventually figure things out.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;That being said, every onboarding experience is truly different from person to person. Even if the challenges vary for each individual, we can approach these hurdles with an optimistic perspective and a positive mindset. Thank you for reading through this long narrative post. I hope you gained something new from it and that you will be able to apply the lessons I have talked about here. Cheers, and I hope you enjoyed the read! 👋😊&lt;/p&gt;

</description>
      <category>socialmedia</category>
    </item>
    <item>
      <title>Getting started on Spring boot and MongoDB - Part 2</title>
      <dc:creator>Irvin Gil</dc:creator>
      <pubDate>Sat, 05 Oct 2024 14:46:34 +0000</pubDate>
      <link>https://dev.to/ehrbhein/getting-started-on-spring-boot-and-mongodb-part-2-2jj5</link>
      <guid>https://dev.to/ehrbhein/getting-started-on-spring-boot-and-mongodb-part-2-2jj5</guid>
      <description>&lt;p&gt;In the previous article, we worked on creating a new Spring Boot service, setting up MongoDB using Docker, and connecting the Spring Boot application to the MongoDB database.&lt;/p&gt;

&lt;p&gt;In this article, we'll focus on setting up a basic GET endpoint in our Spring Boot application to read data from the MongoDB instance running on our local machine.&lt;/p&gt;

&lt;h3&gt;
  
  
  What you'll need
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Intellij IDE - for working with code implementation&lt;/li&gt;
&lt;li&gt;Postman - for making http calls and testing the endpoint&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Creating the entity models
&lt;/h2&gt;

&lt;p&gt;In order to work with MongoDB, we need to create a POJO to represent the data in the database. Each property of the class will represent a field in our document.&lt;/p&gt;

&lt;p&gt;In the Spring Boot project, create a new directory under &lt;code&gt;src/com.${project_name}/domain/student&lt;/code&gt;. Then, create a Student Java class and add the following code to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Data&lt;/span&gt;
&lt;span class="nd"&gt;@Document&lt;/span&gt;                     &lt;span class="c1"&gt;// We implement this annotation to tell mongodb that this class represent a single document in our collection.&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Student&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

  &lt;span class="nd"&gt;@Id&lt;/span&gt;                         &lt;span class="c1"&gt;// Every document must have their own id, that is why we create am id property on the class.&lt;/span&gt;
  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;firstName&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;lastName&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="nd"&gt;@Indexed&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unique&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;       &lt;span class="c1"&gt;// We tell mongodb that this field must be unique. This will be one of our business rules on this project.&lt;/span&gt;
  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Gender&lt;/span&gt; &lt;span class="n"&gt;gender&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Address&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;favouriteSubjects&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;BigDecimal&lt;/span&gt; &lt;span class="n"&gt;totalSpentInBooks&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;LocalDateTime&lt;/span&gt; &lt;span class="n"&gt;created&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Finally, we define a constructor for the class.&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Student&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;firstName&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;lastName&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Gender&lt;/span&gt; &lt;span class="n"&gt;gender&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Address&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;favouriteSubjects&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;BigDecimal&lt;/span&gt; &lt;span class="n"&gt;totalSpentInBooks&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;LocalDateTime&lt;/span&gt; &lt;span class="n"&gt;created&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;firstName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;firstName&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lastName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lastName&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;gender&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gender&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;favouriteSubjects&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;favouriteSubjects&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;totalSpentInBooks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;totalSpentInBooks&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;created&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;created&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠️ Note: One of our business rule for this project is that every student must have a unique email address.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can notice that we have &lt;code&gt;Address&lt;/code&gt; and &lt;code&gt;Gender&lt;/code&gt; classes that we haven't defined/created yet. So let's go ahead and create them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt; &lt;span class="c1"&gt;// The contents of Address.java. Please add the contents accordingly.&lt;/span&gt;

&lt;span class="nd"&gt;@Data&lt;/span&gt;                  &lt;span class="c1"&gt;// This lombok annotation allow us to have getters and setters for each properties of the class. Lombok manages this for us so we don't have to write boiletplate code.&lt;/span&gt;
&lt;span class="nd"&gt;@AllArgsConstructor&lt;/span&gt;    &lt;span class="c1"&gt;// This lombok annotation allows us to create a new instance of the Address object without passing any arguments.&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Address&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;country&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;postCode&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// The contents of Gender.java.&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;Gender&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="no"&gt;MALE&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;FEMALE&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create separate files for each Java class. It is not best practice to combine different Java objects/classes that have entirely different contexts.&lt;/p&gt;

&lt;p&gt;Once the two classes have been created, we can resolve the error appearing in the &lt;code&gt;Student&lt;/code&gt; class.&lt;/p&gt;

&lt;h2&gt;
  
  
  MVC and implementation
&lt;/h2&gt;

&lt;p&gt;Spring MVC is a powerful framework for building web applications in Java. It follows the Model-View-Controller design pattern, which separates the application logic into three interconnected components: the model (data), the view (user interface), and the controller (business logic). This separation allows for more organized and maintainable code.&lt;/p&gt;

&lt;p&gt;For more information, you can explore the official documentation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.spring.io/spring-framework/reference/web/webmvc.html" rel="noopener noreferrer"&gt;Spring mvc documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://spring.io/projects/spring-framework" rel="noopener noreferrer"&gt;Spring framework overview&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Repository
&lt;/h3&gt;

&lt;p&gt;Create a new Java interface under the directory &lt;code&gt;src/com.${project_name}/student&lt;/code&gt; and name it &lt;code&gt;StudentRepository&lt;/code&gt;. Implement the following code in the newly created interface.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;StudentRepository&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;MongoRepository&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Student&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nc"&gt;Optional&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Student&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;findStudentByEmail&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Here, we are implementing a method that would allow us to fetch a student data that matches the email that we provide as parameter.&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are leveraging the Mongo repository to allow us to interact with the database.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;MongoRepository&lt;/code&gt; is an interface provided by Spring Data in the package &lt;code&gt;org.springframework.data.mongodb.repository.MongoRepository&lt;/code&gt; extends the &lt;code&gt;PagingAndSortingRepository&lt;/code&gt; and &lt;code&gt;QueryByExampleExecutor&lt;/code&gt; interfaces that further extend the &lt;code&gt;CrudRepository&lt;/code&gt; interface. &lt;code&gt;MongoRepository&lt;/code&gt; provides all the necessary methods which help to create a CRUD application and it also supports the custom derived query methods.&lt;/p&gt;

&lt;h3&gt;
  
  
  Service
&lt;/h3&gt;

&lt;p&gt;We define the business logic of our application in the service classes. The service class acts as a bridge between the controller and repository classes. This is a best practice design when developing Spring Boot applications. The controller must never interact directly with the database implementation, which is the repository in this case.&lt;/p&gt;

&lt;p&gt;Create a new class at the same level as the &lt;code&gt;StudentController&lt;/code&gt; and name it &lt;code&gt;StudentService&lt;/code&gt;. Then, add the following implementation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;             &lt;span class="c1"&gt;// Service classess need to be annotated with this in order for spring boot to determine that this a service class.&lt;/span&gt;
&lt;span class="nd"&gt;@AllArgsConstructor&lt;/span&gt;  &lt;span class="c1"&gt;// Since we are requireing an instance of the StudentRepository class here, we are levering lombok to do the injection for us via constructor.&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;StudentService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;StudentRepository&lt;/span&gt; &lt;span class="n"&gt;studentRepository&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Student&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getAllStudents&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// This method will be the one that is accessed by the controller so that i can fetch data from the mongodb.&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;studentRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findAll&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;   &lt;span class="c1"&gt;// with this implementation, we are following the best practice of not having the controller class directly call the database implementation (repository).&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Controller
&lt;/h3&gt;

&lt;p&gt;In Spring MVC, we define the endpoints of our application in the controller.&lt;/p&gt;

&lt;p&gt;Create a &lt;code&gt;StudentController&lt;/code&gt; Java class at the same level as the &lt;code&gt;Student&lt;/code&gt; class. Then, implement the following code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@RestController&lt;/span&gt;                                 &lt;span class="c1"&gt;// All controller classes need to be annotated with this, so that spring will know that there are endpoints on this controller class.&lt;/span&gt;
&lt;span class="nd"&gt;@AllArgsConstructor&lt;/span&gt;                             &lt;span class="c1"&gt;// We are injecting the StudentService instance into this class, and we are leveraging lombok's annotation to do this for us instead of having to implement a constructor and then annotate it with @Autowired annotation.&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;StudentController&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;StudentService&lt;/span&gt; &lt;span class="n"&gt;studentService&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Inject the instance of StudentService&lt;/span&gt;

  &lt;span class="nd"&gt;@GetMapping&lt;/span&gt;                                   &lt;span class="c1"&gt;// This mapping means that we are mapping this endpoint to a GET HTTP request. &lt;/span&gt;
  &lt;span class="nd"&gt;@RequestMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"api/v1/students"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;            &lt;span class="c1"&gt;// Here is where we difine the endpoint URI.&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Student&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;fetchAllStudents&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;studentService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getAllStudents&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Putting it all together
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Implementing code to populate the database
&lt;/h3&gt;

&lt;p&gt;For this tutorial, we need to pre-populate the data in our local MongoDB so that we have data to test and fetch.&lt;/p&gt;

&lt;p&gt;Open the class of your application with the &lt;code&gt;main&lt;/code&gt; function and add this code implementation under the same class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;  &lt;span class="cm"&gt;/*
   * @info: Succeeding application runs will throw and error when  `auto-index-creation` is enabled
   * */&lt;/span&gt;
  &lt;span class="nd"&gt;@Bean&lt;/span&gt;
  &lt;span class="nc"&gt;CommandLineRunner&lt;/span&gt; &lt;span class="nf"&gt;runner&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;StudentRepository&lt;/span&gt; &lt;span class="n"&gt;studentRepository&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;MongoTemplate&lt;/span&gt; &lt;span class="n"&gt;mongoTemplate&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="nc"&gt;Address&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Address&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"England"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"London"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"NE9"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
      &lt;span class="nc"&gt;Student&lt;/span&gt; &lt;span class="n"&gt;student&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Student&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Jamila"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Ahmed"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"jahmed@gmail.com"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Gender&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;FEMALE&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Computer Science"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="nc"&gt;BigDecimal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;TEN&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;LocalDateTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;now&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
      &lt;span class="cm"&gt;/*
       * @note: We implement a find criteria to search for existing students on the database.
       * It should only insert new student if no other students are found with the same email.
       *
       */&lt;/span&gt;
      &lt;span class="n"&gt;scanAndInsertInitialDataUsingRepository&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;studentRepository&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;student&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;};&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;scanAndInsertInitialDataUsingRepository&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;StudentRepository&lt;/span&gt; &lt;span class="n"&gt;studentRepository&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Student&lt;/span&gt; &lt;span class="n"&gt;student&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;studentRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findStudentByEmail&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;student&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getEmail&lt;/span&gt;&lt;span class="o"&gt;()).&lt;/span&gt;&lt;span class="na"&gt;ifPresentOrElse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;success&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

      &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;success&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" already exists."&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;},&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

      &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Inserting student "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;student&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;studentRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;insert&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;student&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;});&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code implementation above does the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Builds a new &lt;code&gt;Student&lt;/code&gt; object with the provided details.&lt;/li&gt;
&lt;li&gt;Interacts with MongoDB to check if there's an existing user with the specified email address. Remember our business rule for this tutorial: "every student must have a unique email address."&lt;/li&gt;
&lt;li&gt;If there is no student with the specified email address, the new student object is persisted to MongoDB. Otherwise, a log message is printed, and no further action is taken."&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Testing our application
&lt;/h3&gt;

&lt;h4&gt;
  
  
  What it looks like
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faoxpb3nytj3kshtmqrkq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faoxpb3nytj3kshtmqrkq.png" alt="high-level-overview-of-components"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you open the mongo-express app in your browser, you are actually interfacing with the MongoDB database and viewing the data directly. With Express, you can also make edits to the contents of MongoDB. This means you can edit, create, and delete documents as well as collections.&lt;/p&gt;

&lt;p&gt;When you make an HTTP request with Postman to the Spring Boot app, you are not interfacing directly with MongoDB; instead, the Spring Boot app only exposes certain functionalities that are allowed for the client. It does this via endpoints. Each CRUD operation will have an individual endpoint that allows the client to perform specific functionalities. What we have created is a REST API that exposes the functionality of fetching all the students from MongoDB.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt; There's a whole field of knowledge that deals with RESTful API designs, and I admit that our GET endpoint needs some improvements. But for the sake of simplicity, we'll just implement the specification to allow us to get all the student data from the database.&lt;/p&gt;

&lt;h4&gt;
  
  
  Start the application
&lt;/h4&gt;

&lt;p&gt;Open your terminal and run the MongoDB and application with the following commands:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;make start-db&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;make start-app&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ Note: Wait for the MongoDB database to start successfully before running the spring boot app. Or else error messages and issues will show.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Performing the postman request
&lt;/h4&gt;

&lt;p&gt;Open &lt;a href="https://www.postman.com/downloads/" rel="noopener noreferrer"&gt;postman&lt;/a&gt; and create a new request with the following details:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Request-Type: GET
URI: http://localhost:8080/api/v1/students
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;ℹ️ Info: Make sure that the application and database are successfully running before making the postman request.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhj56j340q3wqedvhmj57.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhj56j340q3wqedvhmj57.png" alt="postman-request"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also perform a curl request directly from your terminal as such:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="s1"&gt;'http://localhost:8080/api/v1/students'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1wgvxlj4bjh9g3el70tn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1wgvxlj4bjh9g3el70tn.png" alt="curl-request"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this article, we continued our work by implementing the entity models and discussing common best practices for implementing Spring Boot MVC. We added implementation code to pre-populate our MongoDB database and successfully created a simple GET endpoint to fetch that data through an HTTP call to our Spring Boot application. Congratulations! By now, you have an understanding of how to build a simple Spring Boot backend service that leverages MongoDB as the database source.&lt;/p&gt;

&lt;p&gt;I plan to create a new article to develop the remaining endpoints to achieve a complete CRUD operation for our backend service. This means creating additional endpoints to perform the other CRUD functionalities. Here is the &lt;a href="https://github.com/ehrbhein/springboot-and-mongodb" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt; for this Spring Boot project, where you can follow the configurations and implementations discussed in this tutorial.&lt;/p&gt;

&lt;p&gt;I hope you learned something new from this small tutorial series.&lt;/p&gt;

</description>
      <category>springboot</category>
      <category>mongodb</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Getting started on Spring boot and MongoDB - Part 1</title>
      <dc:creator>Irvin Gil</dc:creator>
      <pubDate>Fri, 13 Sep 2024 14:18:19 +0000</pubDate>
      <link>https://dev.to/ehrbhein/getting-started-on-spring-boot-and-mongodb-part-1-6dp</link>
      <guid>https://dev.to/ehrbhein/getting-started-on-spring-boot-and-mongodb-part-1-6dp</guid>
      <description>&lt;p&gt;As modern applications increasingly demand flexibility and scalability, the combination of Spring Boot and MongoDB has emerged as a great solution for developers. Spring Boot, a popular framework in the Java ecosystem, streamlines the process of building production-ready applications, while MongoDB, a leading NoSQL database, offers a schema-less data model that can easily accommodate varying data structures. Together, these technologies enable developers to create robust, high-performance applications with ease. In this blog, we'll be going through the basics of creating a back end service with Spring Boot and MongoDB, walk through essential setup steps, and provide a technical example to help you understand how both of these technologies work together. &lt;/p&gt;

&lt;h2&gt;
  
  
  What you'll need
&lt;/h2&gt;

&lt;p&gt;The contents of this blog work best in a Linux environment. You'll also need to have these technologies installed on your computer.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Docker-compose (required)&lt;/li&gt;
&lt;li&gt;Maven (required)&lt;/li&gt;
&lt;li&gt;Java (required)&lt;/li&gt;
&lt;li&gt;IntelliJ IDEA (optional) - for implementing your code. You can use vscode or your preferred application.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Creating the spring boot application
&lt;/h2&gt;

&lt;p&gt;Open spring initialzr on your browser (&lt;a href="https://start.spring.io/" rel="noopener noreferrer"&gt;https://start.spring.io/&lt;/a&gt;) and tweak the project with the following configurations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Project: MAVEN&lt;/li&gt;
&lt;li&gt;Language: Java&lt;/li&gt;
&lt;li&gt;Springboot version: 3.3.3&lt;/li&gt;
&lt;li&gt;Project metadata:

&lt;ul&gt;
&lt;li&gt;Packaging: JAR&lt;/li&gt;
&lt;li&gt;Java version: 21&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Dependencies:

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;spring-boot-starter-data-mongodb&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;spring-boot-starter-web&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;lombok&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Generate the project, and it will be automatically downloaded to your computer. Navigate to the ~/Downloads folder and extract the contents from the zip file.&lt;/p&gt;

&lt;p&gt;Open the project with IntelliJ IDEA. The IDE will cache and build the Maven dependencies of the application.&lt;/p&gt;

&lt;p&gt;Try to run the Spring Boot application with the command &lt;code&gt;mvn spring-boot:run&lt;/code&gt;. Don't worry if the application does not work after you run it; this is expected, as the application has no MongoDB database to connect to yet.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

com.mongodb.MongoSocketOpenException: Exception opening socket
        at com.mongodb.internal.connection.SocketStream.lambda$open$0(SocketStream.java:86) ~[mongodb-driver-core-5.0.1.jar:na]
        at java.base/java.util.Optional.orElseThrow(Optional.java:403) ~[na:na]
        at com.mongodb.internal.connection.SocketStream.open(SocketStream.java:86) ~[mongodb-driver-core-5.0.1.jar:na]
        at com.mongodb.internal.connection.InternalStreamConnection.open(InternalStreamConnection.java:201) ~[mongodb-driver-core-5.0.1.jar:na]
        at com.mongodb.internal.connection.DefaultServerMonitor$ServerMonitorRunnable.lookupServerDescription(DefaultServerMonitor.java:193) ~[mongodb-driver-core-5.0.1.jar:na]
        at com.mongodb.internal.connection.DefaultServerMonitor$ServerMonitorRunnable.run(DefaultServerMonitor.java:153) ~[mongodb-driver-core-5.0.1.jar:na]
        at java.base/java.lang.Thread.run(Thread.java:1583) ~[na:na]
Caused by: java.net.ConnectException: Connection refused
        at java.base/sun.nio.ch.Net.pollConnect(Native Method) ~[na:na]
        at java.base/sun.nio.ch.Net.pollConnectNow(Net.java:682) ~[na:na]
        at java.base/sun.nio.ch.NioSocketImpl.timedFinishConnect(NioSocketImpl.java:542) ~[na:na]
        at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:592) ~[na:na]
        at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:327) ~[na:na]
        at java.base/java.net.Socket.connect(Socket.java:751) ~[na:na]
        at com.mongodb.internal.connection.SocketStreamHelper.initialize(SocketStreamHelper.java:76) ~[mongodb-driver-core-5.0.1.jar:na]
        at com.mongodb.internal.connection.SocketStream.initializeSocket(SocketStream.java:105) ~[mongodb-driver-core-5.0.1.jar:na]
        at com.mongodb.internal.connection.SocketStream.open(SocketStream.java:80) ~[mongodb-driver-core-5.0.1.jar:na]
        ... 4 common frames omitted



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Setting up mongo and mongo-express
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Using docker compose
&lt;/h3&gt;

&lt;p&gt;Create a Docker Compose file in the root folder of the project. If you're on Linux, you can use the command &lt;code&gt;touch docker-compose.yml&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Paste this content into the Docker Compose file. I've added descriptions for each line of the code to explain what each line means:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;                                            &lt;span class="c1"&gt;# Defines the services to be run. `mongodb` will be the name of the service to run the actual database, while `mongo-express` will be the one to run the express application.&lt;/span&gt;
  &lt;span class="na"&gt;mongodb&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mongo:latest&lt;/span&gt;                              &lt;span class="c1"&gt;# Describes the image to be used when running the service. This is configured per service.&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;27017:27017"&lt;/span&gt;                                &lt;span class="c1"&gt;# Describes the port binding of the docker container with the virtual port of the host machine.&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;                                     &lt;span class="c1"&gt;# Values of environment variables are defined on this part of the config.&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;MONGO_INITDB_ROOT_USERNAME=admin&lt;/span&gt;             &lt;span class="c1"&gt;# The admin and password env variables must be followed otherwise mongo won't work properly.&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;MONGO_INITDB_ROOT_PASSWORD=password&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mongo-data:/data/db&lt;/span&gt;                          &lt;span class="c1"&gt;# We define a docker volume in here to house the data persistence for our mongodatabase. And then we bind the volume to the service.&lt;/span&gt;
  &lt;span class="na"&gt;mongo-express&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;                                     
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mongo-express:latest&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;                                  &lt;span class="c1"&gt;# This tells docker to always restart the service-container when execution is stopped.&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8081:8081"&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ME_CONFIG_MONGODB_ADMINUSERNAME=admin&lt;/span&gt;        &lt;span class="c1"&gt;# The values for the mongodb credentials must match what is defined on the database service-container (above).&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ME_CONFIG_MONGODB_ADMINPASSWORD=password&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ME_CONFIG_MONGODB_SERVER=mongodb&lt;/span&gt;             &lt;span class="c1"&gt;# Describe the server name of the database. In this case, it's the service-container that is running the mongodb.&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mongodb"&lt;/span&gt;                                    &lt;span class="c1"&gt;# This tells docker to not run `mongo-express` if `mongodb` has not started successfully. &lt;/span&gt;
&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;                                             &lt;span class="c1"&gt;# We define the volumes used by the services here.&lt;/span&gt;
  &lt;span class="na"&gt;mongo-data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;local&lt;/span&gt;



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
  
  
  Taking steps further
&lt;/h4&gt;

&lt;p&gt;You can create a Makefile to streamline the commands for starting and running the applications. Create a new file and name it &lt;code&gt;Makefile&lt;/code&gt;, and then copy this content into the file:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;

&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;start-db&lt;/span&gt;
&lt;span class="nl"&gt;start-db&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    docker compose up          &lt;span class="c"&gt;# Executes docker compose up to run the database services &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;mongodb and express&lt;span class="o"&gt;)&lt;/span&gt;.

&lt;span class="nl"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;start-app&lt;/span&gt;
&lt;span class="nl"&gt;start-app&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    mvn spring-boot:run        &lt;span class="c"&gt;# Uses maven and command to run the application. &lt;/span&gt;



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Running the database service
&lt;/h3&gt;

&lt;p&gt;You can use the Docker Compose command in your terminal, or if you have created a Makefile, you can use &lt;code&gt;make start-db&lt;/code&gt; to run the database-related services.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Thing to note:&lt;/strong&gt; &lt;em&gt;MongoDB might take a minute to fully load, which may cause the Express container to throw error messages because it cannot connect to the database&lt;/em&gt;. Just wait for a few minutes until you see these lines of code in your terminal:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

mongo-express-1  | Mongo Express server listening at http://0.0.0.0:8081
mongo-express-1  | Server is open to allow connections from anyone (0.0.0.0)
mongo-express-1  | basicAuth credentials are "admin:pass", it is recommended you change this in your config.js!



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;ℹ️ The credentials for accessing the Mongo Express app are "admin:pass". This is okay since this is just a simple tutorial. However, in the real world, we need to implement a layer of security to keep our access and data safe.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Mongo express
&lt;/h3&gt;

&lt;p&gt;Mongo Express is a web-based administrative interface designed for managing MongoDB databases. It provides a user-friendly dashboard that allows developers and database administrators to perform essential tasks such as creating and modifying databases, collections, and documents without needing to interact directly with the MongoDB shell. We'll be using the mongo express UI to interact with the mongodb database.&lt;/p&gt;

&lt;p&gt;After running the database services, you can access the mongo express on your browser at &lt;code&gt;http://localhost:8081/&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkt6mvnhlc0u4w22t2k9k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkt6mvnhlc0u4w22t2k9k.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Connecting to mongo database
&lt;/h2&gt;

&lt;p&gt;Back in IntelliJ, rename the application.properties file to application.yml.&lt;/p&gt;

&lt;p&gt;Paste this content into the application.yml file:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="na"&gt;spring&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;application&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;springboot-and-mongodb&lt;/span&gt;
  &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;mongodb&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;authentication-database&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;admin&lt;/span&gt;
      &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;admin&lt;/span&gt;
      &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;password&lt;/span&gt;
      &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;simpleDB&lt;/span&gt; &lt;span class="c1"&gt;# need to manually create this db on mongo-express&lt;/span&gt;
      &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;27017&lt;/span&gt;
      &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;localhost&lt;/span&gt;
      &lt;span class="na"&gt;auto-index-creation&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This configuration simply tells the Spring Boot application the information it needs to connect to the MongoDB database. We will be using the database simpleDB, which we will need to create manually later on.&lt;/p&gt;

&lt;p&gt;This config also sets the application port to &lt;code&gt;8080&lt;/code&gt; (the default for Spring Boot apps).&lt;/p&gt;

&lt;p&gt;You can test the application to see if it can now connect to MongoDB. &lt;strong&gt;Remember, MongoDB takes time to load, so make sure that it's properly loaded before you run the Spring Boot service.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this blog, we have gone through setting up the basic parts of building a backend service with Java Spring Boot and MongoDB. We created a new Spring Boot project, configured its dependencies and application settings, and implemented the configuration for running MongoDB and Mongo Express in a local environment using Docker. Leveraging Docker to run the database services eliminates the dependency problem of installing a MongoDB server on your local machine. This ensures that your database setup will run and be deployed on any Linux machine with the same configuration and ease.&lt;/p&gt;

&lt;p&gt;In the next part, we'll discuss implementing basic CRUD operations with the Back End service that we have created, building on the progress we've made in this blog.&lt;/p&gt;

</description>
      <category>springboot</category>
      <category>basic</category>
      <category>mongodb</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>After Nearly 2 Years, I'm Job Hopping - A Snippet of my Journey and Farewell to the Company That Launched My Software Career</title>
      <dc:creator>Irvin Gil</dc:creator>
      <pubDate>Sun, 21 Jul 2024 14:23:35 +0000</pubDate>
      <link>https://dev.to/ehrbhein/after-nearly-2-years-im-job-hopping-a-snippet-of-my-journey-and-farewell-to-the-company-that-launched-my-software-career-pb6</link>
      <guid>https://dev.to/ehrbhein/after-nearly-2-years-im-job-hopping-a-snippet-of-my-journey-and-farewell-to-the-company-that-launched-my-software-career-pb6</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; Long post ahead. I feel the need to write this blog about my current career status and the recent decision I made. I'll be job hopping and moving on to a new role at another company. I want to document this event in my life, as this will be the first time I’m doing it, and I want to put these feelings and memories into writing before they fade from my memory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Taking my shots on other opportunities
&lt;/h2&gt;

&lt;p&gt;About six to seven months ago, I began actively exploring other potential ways to earn money aside from having a full-time job. As the breadwinner among four siblings, I realized that eventually, the amount I am currently earning would not be enough to support my siblings' education.&lt;/p&gt;

&lt;p&gt;I decided to explore freelancing. I thought that maybe I had what it takes to do freelance work since, as a full-stack developer, I am quite knowledgeable about building web apps and solutions from planning to implementation. So, I watched YouTube videos and read articles on freelancing and how to get clients online as a freelancer. I also allocated some time to research how I could get a job and earn on popular freelancing platforms.&lt;/p&gt;

&lt;p&gt;I spent a lot of time figuring out how to get a client on Upwork, but the closest I got to having a potential client was when someone accepted me to deploy an open-source chatbot builder app on a virtual machine instance. Unfortunately, it didn't go well, as the client did not get back to me after I asked to set up domains for the app. Along with this, I also spent some of my time on other freelancing platforms, setting up my profile and then bidding for job/work postings day after day. I kept repeating this until I eventually gave up hope of landing a gig on freelance work platforms and decided to do something productive with my time. I enrolled in a UI/UX course on Coursera since most of the work posted on freelancing platforms is usually front-end and design-oriented.&lt;/p&gt;

&lt;p&gt;While working full-time as a developer, I also began setting up my profile on corporate career platforms such as LinkedIn and JobStreet. It was a really tough phase because I wanted to ensure that I didn't compromise my performance at work with the other efforts that I was doing on the side. Therefore, I had to make some trade-offs with my personal time outside of work. This led me to forgo mainstream entertainment and stop watching movies. The only personal time I had was when I needed to clean, go shop for food, and have conversations to catch up with my partner.&lt;/p&gt;

&lt;p&gt;However, I did not regret the time spent making my career profile presentable. I kept thinking that  maybe I am ready for mid-level developer workloads since I sometimes handled tasks at my full-time job that were a bit advanced for my current level. So, I started saving mid-level job postings and applying to company career pages from time to time. I changed my social media habits, spending more time on LinkedIn and JobStreet rather than scrolling through Facebook, TikTok, and other entertainment platforms. Additionally, I began to implement some tracking strategies on my personal email to facilitate this effort.&lt;/p&gt;

&lt;p&gt;I made it my routine to allocate time every weekend to apply for mid-level developer jobs. Some companies required applicants to take exams, and I took some on TestGorilla as part of the application process, but I ended up failing them. I also received email replies about my applications being rejected since I was applying for mid-level roles that required 3-5 years of experience as a software developer. One time, I was invited to create a functional MVP to demonstrate my front-end skills as part of the hiring assessment. Despite submitting and deploying a working prototype, the hiring team did not get back to me with the results of the assessment. The more I applied, the more rejection emails I received and this went on for weeks.&lt;/p&gt;

&lt;p&gt;I began to feel depressed again due to the negative outcomes. I decided to stop making efforts to apply for other corporate jobs. I even tried to apply for part-time front-end developer roles, but I was still rejected because they wanted someone with more experience. I felt desperate during this time and went as far as learning the basics of the NextJS framework just to fit in with the job market for React front-end developers. Eventually, I stopped caring and accepted that my current job was the only way I could earn a living.&lt;/p&gt;

&lt;p&gt;As I stopped making efforts to look for other career opportunities, I used my free time to focus on the UI/UX course I was enrolled in on Coursera. Making progress on the course somewhat comforted me; even though my job-hunting efforts were unsuccessful, I was still making progress and learning.&lt;/p&gt;

&lt;p&gt;Around that same time, my college batchmates had a conference call on Messenger, and I joined in. One of my batchmates shared hiring information and mentioned that he knew of a company looking for a Java engineer with a high salary. After some time thinking about it, I decided to take my shot and apply for jobs again.&lt;/p&gt;

&lt;h2&gt;
  
  
  Working and applying for a job in parallel
&lt;/h2&gt;

&lt;p&gt;I immediately worked on applying with the information I received from that call. Reviewing the job posting on the company's career page, it was clear they were looking for mid-level developers with 3-5 years of experience. Nevertheless, I tried to stay optimistic since the tech stack on the description was something I was very familiar with from my current job. I also reached out to someone that my batch mate knew at the company to ask about the vacant role and see if they could refer me. It was quite a desperate move, as I applied through the careers page and also reached out to someone from the company to slip in my resume.&lt;/p&gt;

&lt;p&gt;Two days later, I received an email from the recruiter inviting me to a 30-minute Zoom call, which served as the initial interview. Luckily, the recruiter's timezone was GMT+2, which meant their working hours were after working hours here in the Philippines. I scheduled the interview at a convenient time and began to prepare for the call. In preparation for the interview, I also did some research on the most frequently asked job interview questions and answered them in my own words. I would recite the answers repeatedly until I was familiar with all of them.&lt;/p&gt;

&lt;p&gt;On the day of the interview, the key questions the recruiter asked were, "Would you be okay with a full back end-related workload?" and "Do you see yourself working on back end development long term?". This hit me because I have always found myself more interested in front-end development and often engaged in side projects focused on front end. Even with my previous learning efforts, they were more aligned with front-end web development. I said "yes" to the recruiter's questions, thinking that back end work might not be so bad. I believed that with hard work and perseverance, I could learn to love back end development.&lt;/p&gt;

&lt;p&gt;After the interview, I received an email with instructions for their technical assessment, which was part of the hiring process. Although the instructions were familiar, I can't say I did a good job on understanding what was asked. Even though I am very familiar with Spring Boot, some concepts that were asked on the assessment were new to me. Nonetheless, I proceeded to create a working application, a sort of MVP, to demonstrate the functionality described in the assessment. I used my holiday time (Philippine independence day) to work on the technical assessment for this. And somehow i am pretty happy that there was a holiday since the recruiter kept on emailing me to follow up on my assessment solution. I submitted my solution at the end of that day before i got to sleep and got my response the night of the following day.&lt;/p&gt;

&lt;p&gt;I was really glad when i received the email from the recruiter. I am advancing to the interview with their principal engineer to discuss more about my solution regarding the technical assessment. What i appreciate about their response is that they really give bullet points on their feed backs both positive and negative. It just shows that they really care about their hiring candidates. A few days later, joined the Zoom call with one of their principal software engineers. This was on a weekday, during which I work from 8 AM to 5 PM. I had my interview at 7 PM, and I encountered some difficulties on the Zoom call. It turns out you need to press the "OK" button to consent to the call being recorded before you can unmute. The interviewer and I had no idea about this, so I resorted to using the chat to ask if we could use Google Meet instead of Zoom. Luckily, he was very nice and said that using Google Meet was fine.&lt;/p&gt;

&lt;p&gt;I had a really good talk with the interviewer. Since we are both technical guys, we really did relate and connected on the topics we discussed. However, despite the good conversation and feedback loop, I still feared that I might not get the role because it was clear from our talk that I somehow lacked the knowledge and understanding they expected from a mid-level developer.&lt;/p&gt;

&lt;p&gt;A few days later, I received an email regarding their decision and was very glad that they wanted to proceed with me and have a final interview. I was very happy to have reached this point, but at the same time, I was very anxious that my experience might jeopardize my chances of getting the role. My partner even gave me a pep talk, reassuring me that I still had a good chance since I received positive feedback despite my lack of work experience. She reminded me to celebrate the small wins I had achieved so far. What she said really helped me calm down and continue pressing on. And so, I kept my cool and continued to prepare for the final interview.&lt;/p&gt;

&lt;p&gt;The nice thing about their recruitment process is that they provide a comprehensive overview of the topics to be discussed during each interview, giving you a chance to prepare, which I find very valuable.&lt;/p&gt;

&lt;p&gt;During the final interview, I hopped on a zoom call with the head of operations of their Cebu office. The interview focused on cultural fit, my knowledge of the company, and what I find ideal in a work environment. Many follow-up questions were asked since I had difficulty relating to some terms. As a technical person, I sometimes struggle to understand social terms. Additionally, some questions were not developer-centered; they focused on customer and employee experience, which felt irrelevant since I have no experience in a direct customer-facing role. I was also caught looking at my notes during the interview, which I learned from my post-interview feedback. It was looking quite grim for me, and I just braced myself for the worst since my interview was on Friday. This meant I had to wait until the next week for the results, which did not help with my anxiety. On Monday, I received the good news that they are going to offer me the role of Java back end engineer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Taking the leap
&lt;/h2&gt;

&lt;p&gt;I was really glad when I received the good news via email. I immediately updated my partner, and she was very happy that I finally got a positive outcome after months of effort. The questions that lingered in my mind at then were, "Now what?" and "Do I take the job or not?"&lt;/p&gt;

&lt;p&gt;As the recruitment process was progressing, I took some time to talk to my parents about my efforts. From our talks, they advised me that I should reconsider my current situation and ask the question: "Am I ready for the changes that will result from my decision?". Secondly, they assured me that I have their full support for any decision I make regarding my career. My father said that although the main reason we seek employment is to earn a living, we should always look out for ourselves and do our research before making decisions to weigh both the pros and cons, whether big or small. He added that if I chose to proceed with moving to another company, it would also open up new doors to personal growth, which is a good thing.&lt;/p&gt;

&lt;p&gt;When I applied for the role, I paid it no big deal and just thought of it as try-and-try basis but of course with attention to the salary compensation. But as i progressed through the hiring process, there were times when I doubted my actions, as the company I was currently with also had a good culture, work environment, and a great team. Job hopping to a new company meant starting from scratch in terms of building product knowledge, understanding organizational structure, adapting to work culture, and becoming familiar with the code base, tech stack, and team dynamics. In terms of benefits and perks, I had no significant comparison since paid time off (leaves) could be easily negotiated with my current managers. I actually found some comfort in my current situation and where I was at the moment. However, the difference in salary was a significant factor.&lt;/p&gt;

&lt;p&gt;So, I said yes and accepted the offer for the role. I proceeded to draft my resignation letter the day after receiving the offer email and decided to submit my resignation on Friday of that week. The following week, I scheduled meetings with my manager, department head, and ultimately my team lead to inform them of my decision and discuss it in more detail. I emphasized my need for a higher salary, as I am the family breadwinner and actively support my siblings' educational needs. I also expressed my gratitude for the opportunities, mentorship, and growth I had experienced during my time in the company.&lt;/p&gt;

&lt;p&gt;Fortunately, my current supervisors were very supportive of my decision and understood the reasons behind it. I had shared my concerns about potential mistreatment or bullying due to my decision, and they reassured me that there was nothing to concerned about such things. As I write this article today, I can say that my current company has not shown any mistreatment despite my decision to leave the organization. My supervisors added that if someone is leaving to pursue something that benefits them, we should be happy and show our support.&lt;/p&gt;

&lt;p&gt;The week after my discussions with my supervisors, my team lead and I agreed to announce my decision on Monday during our stand-up meeting. I shared the reasons for my decision with the team and informed everyone that I would be rendering my 30-day notice in accordance with the company's policy for resigning employees. Since then, I focused more of my time on code reviews, testing, and writing documentation, and I also proactively offered help to other team members.&lt;/p&gt;

&lt;p&gt;In my last month at the company, we had our annual company summer party, which included face-to-face events scheduled for the software department throughout the week. I had the opportunity to engage and talk to some co-workers at the office during the week-long activities and catch up with everyone. Ultimately, I got to meet and work with the members of my team during this time. There were some jokes about me leaving the company, but I greatly enjoyed my time with them. I felt sad because our batch from the graduate program (internship) in 2022 was not complete during the face-to-face activities. There were three of us, but one of our batchmates couldn't join the activities for the rest of the week due to the loss of his great-grandmother. Hopefully, we will have another opportunity to catch up and exchange stories sometime in the future.&lt;/p&gt;

&lt;p&gt;One of my co-workers, Brenan, asked me if I had finally said my goodbyes to the people I worked with or knew, either in the office or remotely. I said that I try to do it as much as I can. He said that I should do it, saying goodbye to people I have been acquainted with, because I'll be doing it for myself, not for them. He explained that by doing so, I would actually be doing myself a favor that will help me move on. Interestingly, after taking his advice, I would have to agree with him. I found that it helps calm me and it sets my mind at ease to have said my farewells even to those I don't directly work with.&lt;/p&gt;

&lt;p&gt;At this point in time, I still meet people who ask why I would resign and go to another company. I would just straight up answer, "I got hired for a role with a higher salary." Saying this didn’t feel right at first, but over time, it became easier to say it directly. I also learned that most people understand and are very supportive. Some wished me luck, some said we would see each other around, and others encouraged me to do my best at my next job. For them, they might not see me around the office or see my profile on the work channel. And for me, I think I’m just starting another journey. I reminded myself to live in the present and focus on my current challenges. Sure, there are a lot of uncertainties, but I'm optimistic that I can navigate through them, as I have since I started being independent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Things that i learned as i move on
&lt;/h2&gt;

&lt;p&gt;As i finish this roller coaster narrative of a story, i would like to share some key things that i learned over the past six to seven months:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Maybe you don't need more time, only the courage to make trade offs.&lt;/strong&gt; At first, I always asked myself, "Where do I find the time to look for other opportunities?" It turns out that the time we have daily is fixed; we just need to learn how to prioritize the things we feel are important within that time. Some things I did were clocking in and out of work strictly for 9 hours daily and allotting 2 hours each day to scan LinkedIn and JobStreet. I traded the time I would normally spend watching movies to do things I felt were important. And it's okay. Sure, I missed the new movies and series, but I acquired something more valuable for me in real life.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Celebrate small wins and take note of what you learned.&lt;/strong&gt; Focusing on the main goal is good, but we should also recognize our small wins as we work towards that goal. Appreciating the steps we take will make us feel more empowered and proud of what we've accomplished. This approach is also more sustainable in the long run, especially in the real world.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;It's okay to seek greener pastures.&lt;/strong&gt; I thought people would feel bad about me just because I was looking for better career opportunities. When my partner left her previous company, she could definitely feel some changes in how she was treated. But for me, I experienced the opposite. People around me were more supportive and always said it's normal and okay to look for opportunities to better your life, and there is no shame in that.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Not all decision can be made alone.&lt;/strong&gt; It can feel heavy when you think you're making decisions or fighting battles by yourself. Talking to people who care about you and sharing your burden can ease that feeling. While it might not change the situation, it's always good to have someone to talk to, listen to your experiences, and sometimes offer a new perspective. Conversations don't have to be exclusive to difficult times; they can also be casual, like asking what they would do in your position. I really relate to this since I started talking to my parents and my partner before making decisions where I felt unsure. When I share with others, the burden somehow becomes lighter and easier to carry.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I could probably go on about the many realizations I had while actively looking for opportunities, landing a job, and being offered the role. However, I believe the points I've mentioned above are the most valuable and applicable to everyone, regardless of their current career status.&lt;/p&gt;

&lt;p&gt;By the time this article is published, I will likely be on my way or just starting to make changes to my routine, workflow, and habits to fit my new role. To the company that gave me a chance to launch my software career, I feel immense gratitude for all that I've gained during my stay. I truly appreciate all the support I've received in more ways than one.&lt;/p&gt;

&lt;p&gt;To my co-workers, my message is: "I'll be seeing you all around, and I hope that when we do, we will have more happy and fun stories to tell." The experience has been great, and working with you all has been &lt;em&gt;FUN&lt;/em&gt;.&lt;/p&gt;

</description>
      <category>career</category>
      <category>socialmedia</category>
    </item>
    <item>
      <title>Factors for burnout as a software developer - part 1</title>
      <dc:creator>Irvin Gil</dc:creator>
      <pubDate>Sat, 13 Apr 2024 23:35:36 +0000</pubDate>
      <link>https://dev.to/ehrbhein/factors-for-burnout-as-a-software-developer-part-1-1l43</link>
      <guid>https://dev.to/ehrbhein/factors-for-burnout-as-a-software-developer-part-1-1l43</guid>
      <description>&lt;p&gt;TL;DR: I'm putting together some experiences that I feel are potential contributing factors to burnout as a software developer. These are the factors that I believe can drain your energy when it comes to building software, and I'll be sharing ways that I think can be done to prevent them. At the time of writing, I have been a full stack web developer with over a year of experience in building software. So this might look like a newbie's perspective for senior devs reading this. I'm hinting at this being the first part of a to-be series of posts on the same matter.&lt;/p&gt;

&lt;p&gt;The workload as a developer is entirely different from the repetitive and redundant work that some may have imagined. This might depend on the work culture of each company. Some companies focus on specialization and assign roles that work on specific areas of the software system, while others practice full-stack development, which requires individuals to be a jack of all trades and perform multiple specialized roles. However, there are certain challenges that I think are common to this kind of work regardless of culture and practice. I am going to share some of them that I personally believe can lead to developer burnout and also share workarounds on how they could have been done better.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For starters, &lt;a href="https://www.webmd.com/mental-health/burnout-symptoms-signs#:~:text=Burnout%20is%20a%20form%20of,life%20and%20affect%20your%20health" rel="noopener noreferrer"&gt;burnout&lt;/a&gt; is a form of exhaustion caused by constantly feeling swamped. It happens when we experience too much emotional, physical, and mental fatigue for too long. In many cases, burnout is related to one's job. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  1. Massive PRs = Review hell
&lt;/h2&gt;

&lt;p&gt;While there is no definite measure of a healthy size for a pull request, one can definitely tell if a PR would be a pain to review based on the number of files and lines of code changed and the scope it covers. Ideally, pull requests should be concise and only include the required and desired changes.&lt;/p&gt;

&lt;p&gt;There are developers who, instead of just changing the lines of code needed for the feature implementation, also proceed to format the entire file on which they made their changes. The result is a lot of lines of code that have been refactored. This is not ideal, as it makes the code harder to review due to the sheer number of changes that a reviewer would need to pay attention to. These high numbers of changes also increase the cognitive load of the reviewer, as more attention to detail is now required to ensure that all the refactored code does not introduce bugs and regressions.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Cognitive load refers to &lt;strong&gt;the amount of mental effort being used in the working memory&lt;/strong&gt;"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One potential cause of massive pull requests is when feature specifications have not been sufficiently broken down into manageable tasks. Examples of such tasks include changes that span multiple modules and classes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ways to avoid having massive PRs
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;A. Separated linting from implementation.&lt;/strong&gt;&lt;br&gt;
     Linting changes is an example of this issue. Most software organizations use a code linter/formatter to maintain code quality. Applying a linter to your processes promotes adherence to specific software formatting standards and ensures uniform formatting across the codebase. If you believe that formatting an entire file is necessary, you can create a separate PR specifically for the formatting changes. This way, you can separate the concerns into two PRs with different objectives.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;B. Design and analyze first rather than diving quickly into implementation&lt;/strong&gt;&lt;br&gt;
     A common mistake in programming is underestimating the complexity of a task. This is something that no one is immune to, but it can be prevented. People often assume that if something is easy to imagine, it will also be easy to implement. However, this is not always the case in software development. Time and time again, you may find yourself discovering complexities related to your task's goals that make you reconsider your commitment to the task's deadline.&lt;/p&gt;

&lt;p&gt;The solution to this is to plan your implementation based on what is necessary and spend time researching the scope and areas where you need to make changes. To take it a step further, you can design test specifications after conducting your research. Doing this provides you with a heightened awareness of the complexity of your changes and their potential scope under the hood.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;C. Keep it simple&lt;/strong&gt;&lt;br&gt;
     If you are asked to change a listed value of static translations, do just that. Don't get sidetracked by editing CSS styles just because you feel they are not aligned with your linter's formatting. Also, make sure to review your staged changes before committing them. Do what is asked, commit, test it, and open your PR for review. Avoid including changes that are outside the scope of the request. Refraining from refactoring variables just because you think the name isn't 'clean' enough. Keeping your PRs simple makes them easier to review.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Gigantic classes
&lt;/h2&gt;

&lt;p&gt;Speaking about massive PRs, classes with over 500 lines of code come second on the list. I have worked with legacy code that has classes on the front and back end perfectly fitting this criteria, and I must say it has not been very enjoyable. These classes are full of global variables with values that are mutated throughout the class, and they are also filled with nested invocations of private functions. All this effort is made in the name of keeping related logic grouped together. While I acknowledge the advantages of this approach, it doesn't necessarily make development easy, as you have to navigate through a lot of code.&lt;/p&gt;

&lt;p&gt;My assumption regarding what causes a class to become bloated and grow to the size of a 500+ line code is that developers didn't know where to draw the line and didn't care enough to consider that the class was getting too large and needed to be split into smaller parts. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;q&gt;&lt;strong&gt;Clean code always looks like it was written by someone who cares.&lt;/strong&gt;&lt;/q&gt; --Michael Feathers  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Ways we can avoiding creating gigantic classes
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;A. Knowing when to draw the line&lt;/strong&gt;&lt;br&gt;
Proper research and planning before implementation is one way to achieve this. At first glance, one can clearly tell if a class is large. You just need to consider whether it's wise to add another block of code to it or not. This judgment can come with experience, but it's an important step in avoiding bloated classes. You can read up on the open/closed principle to learn how to add new implementations while avoiding bloating your classes at the same time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;B. Look for implementation patterns that you can use&lt;/strong&gt;&lt;br&gt;
Over the years, many patterns and designs for building software have been developed and proven to address implementation challenges. Applying patterns to your implementation helps spread and break down your code into smaller, manageable parts. Learning and leveraging these tested solutions can make your code easy to read and understand, while also providing the advantage of being easy to maintain.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Delayed reviews
&lt;/h2&gt;

&lt;p&gt;In my experience working as a developer, it's not uncommon to be working on two things in parallel at the same time. Most of the time, I would be handling one implementation task while also keeping tabs on and reviewing two pull requests. You may think of this as counterproductive since it divides my attention among multiple tasks. And you're right, handling a lot of tasks and reviews can lead to delayed reviews for developers who are dependent on me.&lt;/p&gt;

&lt;p&gt;The reason this is on the list is that delayed reviews slow down the delivery of features or bug fixes. The burden of this delay usually falls on the person who is dependent to the review or approval of their pull request.&lt;/p&gt;

&lt;h3&gt;
  
  
  How can we improve the review process
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;A. Rank reviews based on urgency and importance&lt;/strong&gt;&lt;br&gt;
In this line of work, knowing the things to do first is somewhat a skill. One method to do this is by using the &lt;a href="https://janesagenda.com/blogs/planning-201/eisenhower" rel="noopener noreferrer"&gt;Eisenhower matrix&lt;/a&gt;. When your requested change for the PR has been made by the author, the best course of action is to immediately go back to reviewing it if it's both urgent and important.".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;B. Be mindful as a reviewer&lt;/strong&gt;&lt;br&gt;
Understand that when you assign yourself as a reviewer of a PR, you're now a contributing factor to the time it takes for the tasks to be completed. This means that someone now has a dependency on your work, and they're waiting for your approval/response. Additionally, don't take code reviews personally. Avoid involving emotions or personal preferences and aspire to contribute to the effort of releasing the feature.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;C. Develop your own review process&lt;/strong&gt;&lt;br&gt;
I am pretty sure that every development team has its own way of handling review processes. However, there are limits to how effective they can be. As you take on more reviews and gain experience as a reviewer, you will realize that there's room for improvement as new challenges are discovered. When you reach this point, I believe having a personal way of conducting reviews becomes important, as it allows you to tailor the process to your liking and preferences. You may think that this could slow you down, as adding more steps to your current process will take more time to complete a review. However, the idea behind developing your own review process is &lt;strong&gt;not to dogmatically adhere to an agile process&lt;/strong&gt;, but rather to &lt;strong&gt;make our processes and adhere to them in order to make ourselves agile&lt;/strong&gt;. By realizing this, I can confidently say that having your own way of conducting code reviews is a good thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Among the contributing factors to a developer's burnout are having to review massive pull requests, maintaining/implementing new features on code bases with gigantic classes, and experiencing delayed code reviews.&lt;/p&gt;

&lt;p&gt;To avoid having massive pull requests, one approach is to separate changes for linting from actual implementation and keep the changes in the pull request simple. Another way to optimize your approach and reduce the occurrence of massive pull requests is to analyze the problem first, design your solution, and then proceed with implementation.&lt;/p&gt;

&lt;p&gt;The size of classes with extensive scopes can be reduced by having empathy as a developer and considering whether adding your code on top of an existing class is still the right thing to do. Utilizing programming design patterns can significantly decrease the creation of large classes by breaking down and decoupling code into smaller and more manageable parts. Applying SOLID principles can also prevent existing classes from becoming excessively large.&lt;/p&gt;

&lt;p&gt;To address delayed reviews, it is important to prioritize and complete review tasks based on their urgency and importance. As reviewers, we should be mindful of our responsibilities and acknowledge that someone is dependent on our response and waiting for it. It is crucial not to take code reviews personally and avoid incorporating personal preferences that go against agreed-upon best practices, both for the author and the reviewer. Lastly, having your own review process holds value as it improves the review process by addressing emerging issues discovered while handling code review tasks, and it also shapes your approach and way of conducting reviews.&lt;/p&gt;

&lt;p&gt;With these factors in mind, we can enhance the developer experience for those we work with. It is important to remember that working in a software team is a collective effort. Our code only holds value when it is shipped into production, and our fellow developers play a vital role in helping us achieve that. Therefore, we should strive to reduce burnout factors and embrace healthier practices.&lt;/p&gt;

</description>
      <category>softwaredevelopment</category>
      <category>productivity</category>
      <category>learning</category>
      <category>coding</category>
    </item>
    <item>
      <title>My 2nd time to join our company's hackathon</title>
      <dc:creator>Irvin Gil</dc:creator>
      <pubDate>Sat, 02 Mar 2024 13:43:44 +0000</pubDate>
      <link>https://dev.to/ehrbhein/my-2nd-time-to-join-my-companys-hackathon-4hkn</link>
      <guid>https://dev.to/ehrbhein/my-2nd-time-to-join-my-companys-hackathon-4hkn</guid>
      <description>&lt;p&gt;It's that time of the year again when my current company kicks off our annual hackathon event. We refer to it as "Guild Week" in our department, and this marks my second participation.&lt;/p&gt;

&lt;p&gt;I've been with Synacy for nearly two years now. During my first participation, our team's project emerged as the winner for the People's Choice Awards. Therefore, as I join the event for the second time, I am positive and optimistic for a successful outcome.&lt;/p&gt;

&lt;p&gt;The team rosters and designations were announced by the managers two weeks in advance, providing ample time for the teams to prepare for the weeklong hackathon. I am part of a team comprising three full-stack developers (including myself), one network engineer, and one IT apps developer. While one of our members will be joining remotely, the rest of us will be participating in the face-to-face setup at the KMC co-working space in Cebu. I had to travel from Southern Leyte to Cebu for the event. The company arranged hotel accommodations for those of us who traveled to Cebu, conveniently located near Cebu IT Park, the event venue.&lt;/p&gt;

&lt;p&gt;A week before the hackathon, I initiated conversations to formulate ideas for our project. Each team member was encouraged to share challenges related to work processes or suggest manual tasks that could be enhanced through automation. Queennie, our network engineer, and Harold, our IT apps developer, quickly contributed their ideas. Feeling the need for someone to organize these concepts, I stepped up and proceeded to arrange their submitted ideas on a Notion page, providing a common ground for all our activities.&lt;/p&gt;

&lt;h1&gt;
  
  
  Day 1 - Pitching day
&lt;/h1&gt;

&lt;p&gt;We settled on our team name: "TEAM BANGAN" (Bundle of Amazing Neo-intellectual Gangstas w/ Appealing Niche). The name was intended to be humorous, meaning "weighting scale" in the Cebuano dialect. I suggested it just a week before the event, and we decided to go with it.&lt;/p&gt;

&lt;p&gt;February 19 was scheduled for pitching ideas and for teams to decide which ones they would be developing. Our team was still undecided on the problem we would be solving. So, we had an emergency meeting at 12:30 pm to finalize our decision on what to build and to prepare our presentation for the pitching demo. We ranked each idea using the &lt;a href="https://www.productplan.com/glossary/action-priority-matrix/" rel="noopener noreferrer"&gt;action priority matrix&lt;/a&gt; to identify those that would require the least effort but have a high impact, ideally selecting ideas meeting this criteria for our hackathon project.&lt;/p&gt;

&lt;p&gt;After ranking the ideas, we chose to build the project titled "Automated Zendesk Ticket Reactivation for Scheduled Tasks (AZTiReSchT)." The NOC team from Rise faced an issue where they needed to reactivate tickets scheduled for exact work times. Although they already had a Zendesk automation for this, the problem was that they were restricted to setting the automation to reactivate the ticket only a day ahead. This was suboptimal for them, as they wanted the tickets reactivated 15-30 minutes ahead of the exact scheduled time.&lt;/p&gt;

&lt;p&gt;We adjusted our slides and gained everyone's agreement on what we were going to build. During our pitch in the afternoon, we presented all our gathered ideas and concluded by announcing that we would be building "AZTiReSchT" as our hackathon project.&lt;/p&gt;

&lt;p&gt;After all the teams pitched, our team regrouped to discuss the approach we should take to tackle our problem. At this point, I had zero context on what Zendesk was and its use cases. We consulted with senior developers and managers to determine the path we should take regarding testing and deploying the application.&lt;/p&gt;

&lt;h1&gt;
  
  
  Day 2 - Research
&lt;/h1&gt;

&lt;p&gt;On day 2, the focus was primarily on researching Zendesk and delving deeper into its functionalities. It's a completely new software for me, and I'm still trying to wrap my head around it. I thought it would be beneficial to start using it to get more comfortable. Quennee provided access to a Zendesk account connected to the production line where the network department operates, leading to our first dilemma:&lt;/p&gt;

&lt;h2&gt;
  
  
  How do we create an environment for testing the hackathon project?
&lt;/h2&gt;

&lt;p&gt;There are custom-made fields on the production line, and setting up another environment for the hackathon would require significant effort. We decided to use the Zendesk production line for the hackathon but with caution.&lt;/p&gt;

&lt;p&gt;We set up a group of multiple test tickets and tagged them with a special tag ("guild_week"). The plan is to use only these tickets for performing CRUD operations for our hackathon project. Still, the risk of making a mistake on production is 50/50.&lt;/p&gt;

&lt;h2&gt;
  
  
  But in implementing your application logic, wouldn't that mean having to test the logic multiple times?
&lt;/h2&gt;

&lt;p&gt;Yes, in order to see if our code works, we need to actually test it. On the second day, I also researched an SDK for the project and found the "Zendesk Java Client," a Maven project enabling CRUD operations to Zendesk as if it were regular Java.&lt;/p&gt;

&lt;p&gt;Since we practice unit testing in our day-to-day work, I proposed leveraging unit testing to address this issue. We decided to make API calls to Zendesk only during our final testing. With my teammate, Junsaku, we collaborated with other developers to make unit testing on our application work. This way, we wouldn't have to make API requests to the production Zendesk every time we test our implementation, leading to another crucial question.&lt;/p&gt;

&lt;h2&gt;
  
  
  How would we deploy the application?
&lt;/h2&gt;

&lt;p&gt;We researched and brainstormed different ways to implement and deploy the application, with two ideas standing out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One involves building the project's logic on top of an existing microservice application and using a cron job to trigger the flow at the desired time. This is straightforward as we won't be building it from scratch, just adding new code on top of a stable microservice.&lt;/li&gt;
&lt;li&gt;Another idea is to deploy our logic inside a Lambda on AWS and have another service trigger an event at the desired time. Since we estimated the code to be minimal, we run it as a service whose instance is only spun up when needed and shut down when not. This makes more sense as we are not incorporating Zendesk functionality into another service that encompasses a whole domain. We decided to proceed with the latter.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On this day, we also researched the endpoints we would use for the project. During the later parts of the day, while a learning session was taking place, I exerted effort to figure out how to use the Zendesk API. Eventually, I successfully managed to figure it out and documented the process on Notion so that other team members could read through how to make requests to the Zendesk API.&lt;/p&gt;

&lt;h1&gt;
  
  
  Day 3 - Research continuation
&lt;/h1&gt;

&lt;p&gt;Most of the non-coding work for the project was completed at this point, and we also theoretically established a way to test our application. Now, it's just up to the coding part.&lt;/p&gt;

&lt;p&gt;We discussed the flow and logic for the application and created a flowchart to follow during implementation. Additionally, we made diagrams illustrating how we envisioned the deployment with Lambda and its behavior so that everyone understands what we are building and its components.&lt;/p&gt;

&lt;p&gt;Once again, we decided to divide the work among the developers. Hemant, the senior developer in the group, was tasked with researching and setting up the deployment of the application. Meanwhile, Junsaku and I were assigned to implement the logic for the application and test it, ensuring it performs as intended without disrupting the ongoing tickets on production.&lt;/p&gt;

&lt;p&gt;I delved further into Zendesk, trying out some APIs and double-checking what we needed. I documented my findings on a Notion page, which served as the common point for the hackathon project. Simultaneously, Hemant requested permissions for his AWS sandbox account from the tech leads. As we follow the practice of limiting access to certain services on AWS through IAM, we needed these permissions to access the AWS Lambda service.&lt;/p&gt;

&lt;p&gt;In the afternoon, we didn't make much progress on our hackathon project as there were scheduled games and learning sessions that everyone onsite attended.&lt;/p&gt;

&lt;h1&gt;
  
  
  Day 4 - Implementation
&lt;/h1&gt;

&lt;p&gt;On the 4th day, I walked from the hotel where we were staying to our company office, which is over 2 km away. I collaborated with Junsaku, guiding him on how to work with the Zendesk SDK and clarifying understandings and some questions. I outlined the prerequisites for him and set up a pull request to an existing Lambda project. After laying out the initial code for fetching the desired tickets on Zendesk, I immediately shared the information with him and paired with him on implementing the filtering and logic for the list of fetched Zendesk tickets. Throughout the process, I showed him how to create unit tests for the functions we wrote.&lt;/p&gt;

&lt;p&gt;Unit tests played a significant role for us in this stage since we were dealing with production data. I cannot describe how nervous I was working with production initially. However, as we figured out how to create unit tests, we implemented and tested our code without accessing real production data. We simply mocked the responses and API calls in our tests, allowing us to test our code without the fear of disrupting production.&lt;/p&gt;

&lt;p&gt;Although there were scheduled activities in the afternoon, unfortunately, my body temperature had risen a bit, and I experienced a headache due to lack of sleep. Consequently, I took the rest of the day off to rest.&lt;/p&gt;

&lt;p&gt;In the evening, we had a scheduled team-building activity in Ayala IT Park. After somewhat feeling better, I rushed to join the others at the agreed venue for the team-building activity. I talked with Junsaku about the status of things, mentioning that everything had been implemented but still needed testing for multiple ticket updates. I suggested that we could address it the next day and proceed with deploying the project.&lt;/p&gt;

&lt;h1&gt;
  
  
  Day 5 -  Demo day
&lt;/h1&gt;

&lt;p&gt;It's the last day of the hackathon, and things are not looking well for us.&lt;/p&gt;

&lt;p&gt;Hemant was still encountering issues setting up the Lambda for deployment. Despite the back-and-forths with the tech leads and all the trial and error that took a few hours, they hadn't figured out the necessary permissions for us to proceed.&lt;/p&gt;

&lt;p&gt;I tested the code in the morning and confirmed that it was already working; we just needed to get it deployed. It was challenging for us to reach out to the tech leads because they had meetings scheduled throughout the week, and with Hemant joining online, the conversation became more asynchronous.&lt;/p&gt;

&lt;p&gt;We needed to pivot to another way to demo our project. Ideally, the application should be triggered automatically every 15 minutes, the interval our team had agreed upon in our initial planning. I suggested that we extract the code into a new Spring Boot application and manually start it on a local environment to simulate the application trigger. We just needed to set up the Zendesk test tickets to have their scheduled work time within the desired time range. With that setup, we could fetch the tickets and perform update operations to reactivate them. It was clear at this point that we had missed showcasing the selling point of our project, which is the automation aspect of the process. However, we still had to proceed with the demo since we successfully built the logic needed for the tickets to be reactivated.&lt;/p&gt;

&lt;p&gt;I communicated this information to the rest of the team about the state of things and the reason we were unable to deploy the project on AWS. We were going to rely on Harold and Queenie for the presentation, so we clearly explained the technical challenges that the we, the developers, had encountered.&lt;/p&gt;

&lt;p&gt;We proceeded with the demo, setting up the test tickets on the spot. The test tickets didn't take too long to set up, so it was fine for the audience. We manually ran the application on a local environment, and it performed as we promised. We also explicitly stated to the audience that it was supposed to replace the current automation of the NOC team due to the limitations of the current automation. After the demo, we answered clarifications and questions from the rest of the audience. The tech leads also offered their apologies for not being able to resolve the issue with access to AWS Lambda after the presentation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjt1s7hh4zzjhi3opecic.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjt1s7hh4zzjhi3opecic.png" width="800" height="768"&gt;&lt;/a&gt;&lt;br&gt;Team BANGAN after the presentation and demo of "AZTiReSchT" (Harold, me, Junsaku, and Queenie).
  &lt;/p&gt;

&lt;p&gt;After all the demos were done, the awards were presented. The most-liked project received the People's Choice Award, determined via a vote by all participants of the hackathon. Unfortunately, our project didn't win the award, but every team member gave their all to make the project successful. Appreciation points were awarded to all participants of the hackathon, and after all the dust settled, all participants huddled in for a group photo to commemorate the event.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1jn6edo1uaj6n61unpqb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1jn6edo1uaj6n61unpqb.png" width="800" height="369"&gt;&lt;/a&gt;&lt;br&gt;Group photo at the end of Synacy Guild Week 2024. I'm the one in the black shirt in the bottom row on the left side.
  &lt;/p&gt;

&lt;h1&gt;
  
  
  Takeaways
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Always prepare and never underestimate any situations:&lt;/strong&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I believe one of the areas that can certainly be improved in my second hackathon experience was the level of preparedness of our team. Although it wasn't my first time participating in a hackathon, it was my first time working with the people on my team. Consequently, we didn't communicate much until the week of the hackathon when it was very close. &lt;/li&gt;
&lt;li&gt;Another aspect I underestimated was the challenges we would face during the deployment of the application. In theory, it seemed straightforward, and we were confident that we could finish testing and deployment within an hour if we had the necessary permissions. However, we underestimated the availability of the tech leads, resulting in us being unable to deploy our app on Lambda.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Collaborations are more improved in physical interactions:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I am now convinced that teams working in person and in a face-to-face setting are likely to accomplish tasks faster than asynchronous teams.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Team works best if everyone knows what they need to do and what they can do:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If team members are vocal and communicate well about the necessary tasks, and proactively initiate conversations to get efforts started, then other members are likely to be more proactive and show effort too.&lt;/li&gt;
&lt;li&gt;Initiating conversations about needed tasks also provides members of the group an idea of the roles they're going to play. In our experience, everyone started picking out responsibilities as soon as the required tasks were defined.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Challenging situations bring people out of their comfort zones but also foster learning and growth:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sometimes an unpleasant way to go, but often effective. I took charge as the team member who would organize and keep things aligned so that every member of the team would not be left out. A role in the team I did not expect to find myself in, but still, I am grateful for the opportunity to handle a group, document, and act as a point person for the team.&lt;/li&gt;
&lt;li&gt;This also meant that I did a lot of talking to other people during the duration of the hackathon, something that I don't normally do.&lt;/li&gt;
&lt;li&gt;When our initial plan to deploy our hackathon project on Lambda failed, we quickly extracted our code into a new Spring Boot app that we could use for the demo. This was uncomfortable, given that we did this on the last day of the hackathon, just a few hours before the demo. However, our concept was simple, so we didn't encounter major issues during the pivot.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Asking for help is not a sign of incompetence but rather the willingness to learn:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Many times, we sought advice and help from seniors on other teams regarding testing and developing our project to minimize the risk of disrupting production. Looking back, I'm glad that I asked for help and did not just rely on my judgment because seeking advice from others provided me with various perspectives and approaches to solving problems.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;There's always a learning curve when you're starting to learn something new:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Zendesk was a new concept to me during the hackathon, and I did not get to try it until we got access to the Rise NOC team's production. I thought it would take me just a day to figure things out, but it took me two days to truly understand. This was challenging for us developers because other teams were pitching projects related to our usual tech stack. The anxiety of dealing with production data is no joke, especially since we practice and maintain different environments and tread carefully when dealing with production line items. Accept that there's always a learning curve; you can estimate how long it'll take you to learn something, but you can't be sure.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;The overall hackathon experience was a blast (except for the part where I got sick). I had fun collaborating and working with other developers, and I also got to know more of the new ones joining our department. There is a lot of learning that I gained from the event, and I also got to experience working in a role that is somewhat new to me. I am really grateful for my teammates for being such an awesome bunch. They really don't know how to give up, even if we were a little disheartened when we failed to deploy our project. I really appreciate the amount of effort, brainstorming, and collaboration that they put in to make our project successful. I also hope everyone had fun building and designing solutions for real-world problems that we face in our day-to-day work life. I am truly grateful for the opportunity to work with wonderful people.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F057vo4p9glm9bb70obk6.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F057vo4p9glm9bb70obk6.jpg" width="800" height="320"&gt;&lt;/a&gt;&lt;br&gt;Entire Team Bangan Hackathon Team, from left to right: Me, Junsaku, Hemant, Queenie, and Harold. Hemant joined remotely the whole time, and we decided to photoshop him into this group photo 🤣.
  &lt;/p&gt;

</description>
      <category>socialmedia</category>
    </item>
    <item>
      <title>Restoring data from pg_dump snapshot</title>
      <dc:creator>Irvin Gil</dc:creator>
      <pubDate>Tue, 26 Dec 2023 08:03:24 +0000</pubDate>
      <link>https://dev.to/ehrbhein/restoring-data-from-pgdump-snapshot-3gmh</link>
      <guid>https://dev.to/ehrbhein/restoring-data-from-pgdump-snapshot-3gmh</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: &lt;em&gt;Building on the previous post about capturing "snapshots" of PostgreSQL databases and their benefits for testing and debugging, this post dives into the practical side: how to leverage these snapshots and restore your database to a specific state with ease.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisite
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;For linux OS, we need to add some environment variables on our rc files: &lt;code&gt;bashrc&lt;/code&gt; or &lt;code&gt;zshrc&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PGHOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;postgres_host&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PGPORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;postgres_port&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PGUSER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;postgres_username&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PGPASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;postgres_password&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We'll be dependent on the values of these environment variables to be able to effectively use the next steps.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If your dev environment is based on container technologies like docker, make sure the container with the database is running.&lt;/li&gt;
&lt;li&gt;Since we are restoring the data of an existing database, drop the database on the postgre server if it exists otherwise create the database.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Bash script for restoring snapshot data
&lt;/h1&gt;

&lt;p&gt;Create a &lt;code&gt;.sh&lt;/code&gt; file on the directory where your service's repository is stored and then paste the contents of the script below. &lt;/p&gt;

&lt;p&gt;I'll leave some comments to further explain the details of what the script does so that users can understand it better.&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;p&gt;&lt;span class="c"&gt;#!/usr/bin/bash&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="c"&gt;# HOW TO USE?&lt;/span&gt;&lt;br&gt;
&lt;span class="c"&gt;# 1. this must be used after the pg_dump data has been successfully created.&lt;/span&gt;&lt;br&gt;
&lt;span class="c"&gt;# 2. update the value of the "parent_directory".&lt;/span&gt;&lt;br&gt;
&lt;span class="c"&gt;# 3. also update the value of the "target_database" array.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="c"&gt;# ---&lt;/span&gt;&lt;br&gt;
&lt;span class="c"&gt;# this variables refers to the directory level where the "database_dump" folder is located&lt;/span&gt;&lt;br&gt;
&lt;span class="nv"&gt;parent_directory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"home/development-environments/service-1"&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/&lt;br&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$parent_directory&lt;/span&gt;&lt;span class="s2"&gt;/database_dump"&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="c"&gt;# ---&lt;/span&gt;&lt;br&gt;
&lt;span class="c"&gt;# list your databases that you want to have a restore here.&lt;/span&gt;&lt;br&gt;
&lt;span class="c"&gt;# This variable refers to the databases that you want to restore. Make sure that all the database you wish to restore are all newly created ones.&lt;/span&gt;&lt;br&gt;
&lt;span class="nv"&gt;target_database&lt;/span&gt;&lt;span class="o"&gt;=(&lt;/span&gt;&lt;span class="s2"&gt;"database_1"&lt;/span&gt; &lt;span class="s2"&gt;"database_2"&lt;/span&gt; &lt;span class="s2"&gt;"database_3"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="c"&gt;# ---&lt;/span&gt;&lt;br&gt;
&lt;span class="c"&gt;# iterates throught the databases to be restored. Then prints a message to indicate if the procedure was a success or fail.&lt;/span&gt;&lt;br&gt;
&lt;span class="k"&gt;for &lt;/span&gt;database_name &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;target_database&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;br&gt;
&lt;span class="k"&gt;do&lt;br&gt;
  &lt;/span&gt;psql &lt;span class="nt"&gt;-h&lt;/span&gt; &lt;span class="nv"&gt;$PGHOST&lt;/span&gt; &lt;span class="nt"&gt;-U&lt;/span&gt; &lt;span class="nv"&gt;$PGUSER&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$database_name&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &amp;lt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$database_name&lt;/span&gt;&lt;span class="s2"&gt;.sql"&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; &lt;span class="nt"&gt;-eq&lt;/span&gt; 0 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;br&gt;
   &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;database_name&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; data has been restored successfully."&lt;/span&gt;&lt;br&gt;
  &lt;span class="k"&gt;else&lt;br&gt;
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error: Data restoration attempt for &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;database_name&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; has failed."&lt;/span&gt;&lt;br&gt;
  &lt;span class="k"&gt;fi&lt;br&gt;
done&lt;/span&gt;&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Conclusion&lt;br&gt;
&lt;/h1&gt;

&lt;p&gt;Restoring data from a single .sql database snapshot is a straightforward process. However, when dealing with multiple snapshots, automation becomes essential for efficiency and consistency. To optimize the restoration of multiple snapshots, consider utilizing Bash scripts. These scripts automate the process, significantly reducing manual effort and potential errors.&lt;/p&gt;

&lt;p&gt;When paired with the pg_dump method for creating database snapshots, the restoration procedure via bash scripts create a powerful combination that empowers developers to focus on core tasks while streamlining testing and debugging experiences. &lt;/p&gt;

</description>
      <category>postgres</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
