🚀 Java Stream 🧠 1. The Fundamental Truth 🔹 Streams operate on objects 🔹 Math operates on primitives So Java needed a bridge… 👉 mapToInt() = The Bridge Stream<Integer> → IntStream (boxes) (real numbers) 📦 Object World (Normal Stream) Inside normal stream: [Integer] [Integer] [Integer] ↓ ↓ ↓ 10 20 30 Every operation: open box → take value → calculate → repack → repeat ⚠️ Slow (boxing & unboxing) ⚡ Primitive World (IntStream) After mapToInt: 10 20 30 No objects No heap allocation Only CPU math 🔥 🌉 Bridge Conversion list.stream() // Stream<Integer> (boxes) .mapToInt(Integer::intValue) // IntStream (numbers) (Lambda: x -> x.intValue(),Method Reference: Integer::intValue) Same meaning ✔ 🔢 Math Operations (Terminal Operations) Operation -> Return Type -> Why sum() -> int -> Always exists count() -> long -> Always exists max() -> OptionalInt -> May not exist min() -> OptionalInt -> May not exist average() -> OptionalDouble -> May not exist 🧠 Rule: int holds data OptionalInt holds possibility of data 📬 Extracting the Value IntStream → max() → OptionalInt → getAsInt() → int 🔹 max() gives Optional 🔹 getAsInt() opens it You may also safely handle: max.orElse(0); max.ifPresent(System.out::println); 🏁 Final Mental Model 👉 Streams = object pipeline 👉 Math operations = primitive pipeline 👉 mapToInt = bridge between them 🔹sum and count always return primitive values 🔹terminal ops (max/min/average) return Optional & safely stores “value may or may not exist” 🔹getAs…() extracts the primitive value from it (assuming it exists), if the value doesn’t exist, getAs…() throws NoSuchElementException. 👍 getAsInt(), getAsDouble(), getAsLong() belong to the Optional primitive classes (OptionalInt, OptionalDouble, OptionalLong). ---> extracts primitive from Optional GitHub Link: https://lnkd.in/gkFvUU32 🔖Frontlines EduTech (FLM) #java #coreJava #optionalPrimitives #BackendDevelopment #Programming #CleanCode #ResourceManagement #Java #Java8 #Streams #FunctionalProgramming #LambdaExpressions #AustraliaJobs #SwitzerlandJobs #NewZealandJobs #USJobs #java #coreJava #optionalPrimitives
Java Streams: Understanding mapToInt() and Optional Primitives
More Relevant Posts
-
The "11th Rule" Trap: Why Java’s Map.of() Might Be Misleading You ❌ Have you ever written perfectly logical, declarative code, only to be hit by a strange Compilation Error? You look at your IDE, and it insists on an "Incompatible Types" issue, even though your classes match perfectly. I recently hit a classic, but treacherous problem, using the Map.of() method. 📋 Dispatch Map Pattern I was implementing a "Type-to-Strategy Map" to replace a messy chain of if-else and instanceof blocks. The idea is clean: a map where the key is the Rule class and the value is the mapping function. Ten rules worked flawlessly. But as soon as I added the eleventh, everything broke. 🤯 A Misleading Hint Instead of a clear "Too many arguments" message, the compiler threw a confusing: "Incompatible types: expected... " I spent 15 minutes re-verifying my code, thinking I had made a mistake in the type system. I was convinced the problem was the type of the new rule, while the actual problem was simply the quantity. The compiler's "confused" hint led me down a rabbit hole, when I should have just been counting my arguments. 💡 Why is there a limit of 10? Why can't Map.of() just use varargs like List.of() to accept any number of elements? Varargs can only handle a single type. Type Mixing: In a Map, we have Keys (K) and Values (V). Java's varargs doesn't have a syntax to say "take arguments where every first is K and every second is V". Safety: Using Object... would lose type safety and risk an odd number of arguments, leading to runtime crashes. Performance: To keep Map.of() lightning-fast and "allocation-free" (avoiding temporary arrays), JDK developers manually overloaded it 11 times (from 0 to 10 pairs). Once you hit 11, you've run out of "pre-built" templates! ✅ The Fix: Map.ofEntries() To bypass the "one-type varargs" limit, Java uses Map.ofEntries(). It wraps each pair into a Map.Entry object. Since the type is now uniform (Entry), varargs works perfectly, allowing for any number of elements. 🛠 Lessons Learned: Source over Docs: When a standard method acts weird, Command(Ctrl for Windows) + Click into the JDK source. Don’t trust the error message 100%: The compiler often "guesses" the closest mismatch, leading you away from the actual fix. The Dispatch Map Pattern: Despite this hiccup, it’s a powerful way to keep your code Open/Closed compliant and maintainable. Have you ever been misled by a cryptic compiler error? Share your stories in the comments! 👇 #java #backend #programming #cleancode #softwaredevelopment #tips #generics #jvm
To view or add a comment, sign in
-
-
Java 26 is released today. Brief look at some of its highlights 1. Performance & JVM Improvements G1 GC: Improve Throughput (JEP 522): This update reduces synchronization between application and garbage collector threads. Improves throughput by 5–15% for write-heavy applications and slightly decreases pause times. Ahead-of-Time (AOT) Object Caching (JEP 516): Building on Project Leyden, this allows the JVM to cache pre-initialized objects in a GC-agnostic format. It significantly accelerates application startup and "warm-up" times across all garbage collectors, including ZGC. G1 Humongous Object Reclamation: G1 now more eagerly reclaims "humongous" objects (those taking up >50% of a region) even if they contain references, which helps reduce heap pressure. 2. Core Library & Networking HTTP/3 Support (JEP 517): The HttpClient API now supports HTTP/3. This allows developers to take advantage of the performance and reliability benefits of QUIC with minimal code changes. PEM Encodings of Cryptographic Objects (JEP 524): Currently in its second preview, this provides a standard API for encoding and decoding cryptographic keys and certificates into the PEM format, including support for encrypted KeyPairs. Vector API (JEP 529): Now in its 11th incubator phase, this API allows developers to write vector computations that the JIT compiler can translate into optimal SIMD instructions, which is crucial for AI and data-heavy applications. 3. Language & Modernization Primitive Types in Patterns (JEP 530): This 4th preview allows primitive types to be used in instanceof and switch pattern matching. It removes previous restrictions, making code more uniform and reducing friction when working with primitives. Prepare to Make Final Mean Final (JEP 500): This is a foundational change to how the JVM handles final fields. It aims to prohibit the modification of final fields via reflection, which currently generates a warning but will eventually lead to an exception. Lazy Constants (JEP 526): In its second preview, this introduces "Stable Values"—constants that are computed lazily and then remain immutable, providing a thread-safe and efficient alternative to existing lazy-initialization patterns. 4. Deprecations & Removals Removal of the Applet API (JEP 504): The long-deprecated Applet API has been fully removed from the JDK, reducing the footprint and cleaning up legacy security risks. https://lnkd.in/gxh9GCUG #java26
To view or add a comment, sign in
-
-
The moment your Java app goes to production, you inherit a problem nobody really explains in college. Who is cleaning up after your code? You create an object to process a request. You create another to cache a response. You create thousands more under the hood just to serve one API call. None of them clean themselves up. The JVM does it. Through something called Garbage Collection. Your app runs fine for 6 hours. Then slows down. Then crawls. Then crashes with OutOfMemoryError. You restart. It is fine again. For 6 hours. That is not a bug in your code. That is a memory leak. And the GC could not save you because you were still holding references to objects you thought you were done with. Here is what is actually happening under the hood: - The JVM splits memory into generations. - Young objects live in Eden. Survivors get promoted. Long-lived objects graduate to Old Gen. When Old Gen fills up, Full GC kicks in and freezes your entire application to clean house. That freeze? That is your latency spike. That repeated freeze? That is your degrading p99. That final freeze where nothing gets collected? That is your OutOfMemoryError. The GC is not magic. It is an algorithm. And like every algorithm, it has tradeoffs. Serial GC is simple but single-threaded. Parallel GC maximises throughput but pauses are long. G1 GC gives you predictable pause times - and it is the default since Java 9 for a reason. Think of it like a municipal garbage truck. Serial GC is one kabaadiwala doing everything alone. Efficient for a small lane, useless for a city. Parallel GC is a whole team of them - faster, but the whole street is blocked while they work. G1 GC is a zoning system. It figures out which areas have the most garbage and cleans those first, so the rest of the city keeps moving. Neither approach is wrong. The choice depends on whether your system needs raw throughput or low latency. And the leaks? Those are on you. Static collections that never evict. Listeners never de-registered. Caches with no TTL. The GC cannot collect what your code is still holding onto. References: 1. Shrayansh Jain : Java Memory Management + GC video : https://lnkd.in/gsn5vCmK 2. Datadog Blog on GC : https://lnkd.in/gPGi9gq8 Full breakdown with diagrams, code examples, and a decision guide in the carousel. Swipe through. ↓
To view or add a comment, sign in
-
🚀 Day 7 — Restarting My Java Journey with Consistency Today’s topic looked simple: Conditional Statements , switch statement. But what I actually learned was how the Java compiler optimizes decision making internally using something called a: ⚙️ Jump Table 🔹 What is a Jump Table? A Jump Table is a compiler optimization technique. Instead of checking conditions one by one: if (x == 0) ... else if (x == 1) ... else if (x == 2) ... The compiler creates a table of memory addresses. Then it: 1️⃣ Calculates an index 2️⃣ Directly jumps to the corresponding case No sequential comparisons. Just direct memory access. That’s why it can run in O(1) time. ⚠ But Jump Tables Are NOT Always Efficient Jump tables work best when case values are dense (continuous). Example: 0, 1, 2, 3 Here, a table makes perfect sense. But what if cases are: 1, 1000, 8000 If a jump table were used here, the JVM would need space for all values between 1 and 8000. That’s massive memory waste ❌ So Java uses two internal bytecode instructions: 1️⃣ table-switch → For Dense Values ✔ Used when values are close together ✔ Creates a jump table (array-like structure) ✔ Direct indexing ✔ Time complexity ≈ O(1) ⚠ May consume more memory 2️⃣ lookup-switch → For Sparse Values ✔ Used when values are far apart ✔ Stores (key → target address) pairs ✔ Keys are stored in sorted order ✔ JVM performs binary search on those keys ✔ Time complexity ≈ O(log n) ✔ Memory efficient This was the biggest insight for me today. lookup-switch is not just key-value storage — it actually uses binary search internally. 🔹 Dense vs Sparse — The Real Engineering Insight Performance of switch depends on: ->Distribution of case values ->Range ->Memory trade-offs ->Compiler optimization strategy It’s not just about writing syntax. It’s about how your data is structured. 🔁 Nested Switch ? Yes, nested switch is possible. But more nesting means: ->Higher complexity ->Lower readability ->Harder maintenance Good engineering is not about what is possible. It’s about what is sustainable. What I Really Learned Today ? Today wasn’t about switch. It was about: ✔ How compilers think ✔ How JVM optimizes execution ✔ Memory vs speed trade-offs ✔ Why understanding internals makes you a stronger backend engineer Surface learning writes code. Deep learning builds engineers. Learning daily with Coder Army and Aditya Tandon Bhaiya and Rohit Negi Bhaiya #Day7 #Java #Consistency #BackendDevelopment #LearningJourney #SoftwareEngineering #CoderArmy
To view or add a comment, sign in
-
-
Abstract Methods vs Interfaces: Java's Secret to Flexible Code Yesterday, we broke down abstract classes as blueprints you can't build directly. Today, let's level up: abstract methods vs interfaces. First, Abstract Methods: The "Do It Your Way" Blueprint Regular methods? They do the work right there. Example of a regular method: public static int add(int A, int B) { int sum = A + B; return sum; // It "does something" immediately } But abstract methods? Nah, they're just a blueprint. You declare them without putting anything inside – no body, no curly braces. Why? Because you want subclasses to "do something with it later," depending on what fits. It looks like this: abstract int add(int A, int B); // No body! Key rule: Abstract methods can only live in abstract classes (or interfaces – more on that soon). So, in our student example: abstract class Student { abstract int add(int A, int B); // Blueprint: "You figure out how to add" } class GSSStudent extends Student { int add(int A, int B) { return A + B; // Now we "do something" } } Why must you implement (instantiate) it in the subclass? Because extending means you're taking the whole package. If you don't, it's like saying, "I want some of you, but not all of you." That won't fly with the compiler – you gotta carry all the baggage! If your abstract class has 10 abstract methods? Subclass must handle ALL 10. No shortcuts. Enter Interfaces (Drum roll) Java devs thought: "What if we want flexibility without forcing everything?" Interfaces! An interface is like a special "contract" that houses abstract methods (all methods are abstract by default). Example: interface MathWizard { int add(int A, int B); int subtract(int A, int B); int divide(int A, int B); } To use it? Don't extend – implement it in your class. And the magic? You must implement those methods there. class GSSStudent implements MathWizard { public int add(int A, int B) { return A + B; // GSS style: straightforward } Pro tip: Since Java 8, interfaces can have default methods (with bodies) for backward compatibility – e.g., `default int multiply(int A, int B) { return A * B; }`. No need to implement those unless you want to override. Why Interfaces > Just Abstract Classes? - Multiple inheritance hack: Java doesn't allow extending multiple classes (to avoid diamond problems), but you can implement MULTIPLE interfaces. Example: `class GSSStudent implements MathWizard, StudyMaster, SportsHero { ... } - Loose coupling supercharged: Interfaces let you swap implementations easily. Code against the interface (e.g., `MathWizard wiz = new GSSStudent();`), and change the class later without breaking everything. Perfect for big teams or scalable apps. Interfaces keep your code flexible, like navigating Lagos traffic – adapt without total breakdown. What did you learn today? Drop it in the comments! #Java #OOP #Abstraction #Interfaces #SoftwareDevelopment
To view or add a comment, sign in
-
Why Java Is Not a Pure Object-Oriented Language A pure object-oriented programming language is one where everything in the program is treated as an object. In such languages, even basic values like numbers, characters, and boolean values are represented as objects. There are no primitive data types. javava is a language that embraces many object-oriented concepts, yet it does not fully qualify as a purely object-oriented language. Here are the key reasons why: 1. Presence of Primitive Data Types Java includes several primitive data types, such as: - int - float - double - char - boolean - long - short - byte These types are not objects, which contradicts the principle that all values in a program should be objects. For example, in the code snippet below, `a` is a primitive value, not an object: ```java int a = 5; System.out.println(a); ``` In contrast, languages like Smalltalk treat even numbers and boolean values as objects. 2. Use of the static Keyword Java permits the declaration of methods and variables using the static keyword. Static members are associated with the class itself rather than with an instance of the class, allowing access without creating an object. This undermines the principle that all operations should occur through objects. For instance: ```java class Test { static int count = 0; static void show() { System.out.println("Hello"); } } ``` In this example, the method `show()` can be called without instantiating an object. 3. Wrapper Classes and Primitive Conversion Java offers wrapper classes such as: - Integer - Float - Double - Character - Boolean These classes enable primitive values to be treated as objects. However, Java still relies on primitive types through mechanisms like autoboxing and unboxing. For example: ```java public class BoxingExample { public static void main(String[] args) { Integer i = new Integer(10); Integer j = new Integer(20); Integer k = new Integer(i.intValue() + j.intValue()); System.out.println("Output: " + k); } } ``` In this case, primitive values #ProgrammingConcepts #SoftwareEngineering #Coding #BackendDevelopment #JavaInterview #TechLearning #ProgrammingEducation #CodeNewbie #DeveloperLife #ComputerScience #ProgrammingTips #JavaConcepts
To view or add a comment, sign in
-
-
Hey everyone! 👋 Day 4 of revising my core Java fundamentals! Today, I tackled a mind-blowing concept that frequently comes up in interviews: How does Java actually store decimal numbers in memory? I ran a simple experiment in my IDE today that completely broke my brain. If you declare float f = 8.125f; and ask Java to print it out to 20 decimal places, it prints exactly 8.125000.... BUT, if you declare float f = 0.7f; and print it, you don't get exactly 0.7. Instead, you get something like 0.699999...!. Why is Java giving us a weird estimated value instead of exactly 0.7? 🤔 To understand this, we have to look at how computers handle memory under the hood. Computers only understand 0s and 1s. When you create a 32-bit float, Java follows the IEEE standard and divides that memory box into three specific parts: 1.Sign Bit (1 bit): Tells the computer if the number is positive or negative. 2.Exponent (8 bits): Helps calculate where the decimal point should be placed. 3.Mantissa (23 bits): Stores the actual fractional data of our number. Here is the ultimate plot twist: When you convert certain decimals (like 0.7) into binary, they don't convert cleanly. Just like 1/3 becomes an infinite 0.3333... in decimal math, converting 0.7 to binary creates an infinite, repeating pattern of 0s and 1s!. Because our "Mantissa" box only has space for exactly 23 bits, the computer is forced to eventually just chop off (truncate) the rest of that infinite pattern. When Java tries to read that chopped-off binary code and convert it back into a decimal for us to see on the screen, a tiny bit of precision is lost. That is why we get 0.699999... instead of exactly 0.7!. 🔥 Pro Developer Tip: Because primitive types like float and double will often give you an "estimated" value, you should NEVER use them for exact calculations where precision is critical (like financial currency). To solve this, Java provides a special non-primitive data type called "BigDecimal", which is designed to give you exact values without this precision loss!. Learning that computers are actually kind of "bad at math" because of strict hardware memory limits was such a cool lightbulb moment today! #Java #SoftwareEngineering #TechFundamentals #StudentDeveloper #CodingJourney #TechCareers #InterviewPrep #FloatingPoint
To view or add a comment, sign in
-
-
🚀 Day 124 of My Java Learning Journey Hi Guys, Today I practiced an important string logical problem — 👉 Finding the occurrence of each character in a String (including spaces) using Java Streams. This type of logic is very common in interviews and improves your understanding of Streams and Collections. ------------------------------------------------------------------------------------------- 💻 Code: -------------> import java.util.Map; import java.util.function.Function; import java.util.stream.Collectors; public class OccurrenceAndNonRepeatingChar { public static void main(String[] args) { String name = "yuvraj singh kushwah"; // Occurrence of all character with spaces Map<Character, Long> charCount = name.chars() .mapToObj(x -> (char) x) .collect(Collectors.groupingBy( Function.identity(), Collectors.counting() )); System.out.println("Occurrence of all characters with spaces: " + charCount); } } ------------------------------------------------------------------------------------------- 🖥 Output: -------------> Occurrence of all characters with spaces: { =2, a=2, g=1, h=2, i=1, j=1, k=1, n=1, r=1, s=2, u=2, v=1, w=1} 🔎 Output Explanation: • Space " " is counted → appears 2 times • Characters like g, i, j, k appear only 1 time • Characters like a, s, u appear 2 times Since we didn’t remove spaces, they are treated like normal characters. ⭐ Important Concept: ✔ chars() → Converts String into IntStream ✔ mapToObj() → Converts int to Character ✔ groupingBy() → Groups identical characters ✔ counting() → Counts frequency This is a clean Java 8+ approach instead of manually using loops and HashMap. 💡 Important Tip: If you don’t want to count spaces, add: .filter(ch -> ch != ' ') before collect(). 🔥 Why This Is Important? ✔ Frequently asked in interviews ✔ Builds strong Stream knowledge ✔ Improves logical thinking ✔ Real-world text processing use case Consistency > Motivation 💪 Day 124 done ✅ What should I practice tomorrow — more Stream problems or interview-based tricky logic? #Java #JavaDeveloper #JavaStreams #CodingPractice #ProblemSolving #InterviewPreparation #DevOps #LearningInPublic #124day #CodeWithYuvi
To view or add a comment, sign in
-
-
What actually happens when we use Runnable vs Thread. While studying Java Multithreading, I explored how the Runnable interface works and some interesting cases. Let me Breakdown to you, I. Creating a Thread using Runnable Instead of extending the Thread class, we can implement the Runnable interface. Steps: 1. Create a class that implements Runnable 2. Override the run() method 3. Pass the Runnable object to a Thread 4. Call start() Example: class MyRunnable implements Runnable { public void run() { System.out.println("Child Thread"); } } class ThreadDemo { public static void main(String[] args) { MyRunnable r = new MyRunnable(); Thread t = new Thread(r); t.start(); } } Once start() is called, a new thread is created and the run() method executes. But things become interesting when explore different cases. Case 1: t.start() A new thread is created. The run() method executes in that new thread while the main thread continues running. Case 2: t.run() No new thread is created. run() behaves like a normal method call, and everything runs in the main thread. Case 3: r.run() Again, no thread is created. This simply executes the method like a normal function. Case 4: r.start() This causes a compile-time error. Why? Because the Runnable interface does not contain the start() method. Only the Thread class has it. Why Runnable is Preferred? Java supports single inheritance. If we extend the Thread class, our class cannot extend any other class. But when we implement Runnable: • We still get multithreading • We can extend another class • The design becomes more flexible That’s why the Runnable approach is recommended in real-world applications. II. Thread Names in Java Every thread has a default name like: main Thread-0 Thread-1 We can get or change the name using: • getName() • setName() Example: Thread.currentThread().getName(); Thread.currentThread().setName("MyMainThread"); III. Getting the Current Thread To know which thread is currently executing: Thread.currentThread() This is very useful while debugging multithreaded programs. #Day5 #Java #Multithreading #BackendDevelopment #SystemDesign #SoftwareEngineering
To view or add a comment, sign in
-
🚀 **Understanding Why We Create Objects in Java | JVM Memory Basics** While learning Java and OOP concepts, one important question arises: **Why do we create objects in Java?** To understand this, we need to look at how the **Java program execution process** works inside the JVM. 1️⃣ Compilation Phase A Java program is first compiled using the **Java Compiler (javac)**, which converts the `.java` file into a `.class` file containing **bytecode**. ``` Main.java → Main.class ``` This `.class` file is stored on the **hard disk**. --- 2️⃣ Class Loading When we run the program using the **Java Virtual Machine**, the **Java ClassLoader** loads the `.class` file into RAM. At this stage, the JVM loads: * Class metadata * Static variables * Static blocks * Method definitions ⚠️ **Important:** Non-static variables are **not created yet**. 3️⃣ Program Execution Starts The JVM searches for the entry point of the program: public static void main(String[] args) Execution begins from the **first line of the `main()` method**. 4️⃣ Static vs Non-Static Members **Static Members** * Loaded when the class is loaded. * Stored in the **method area**. * Accessible without creating an object. Example: ```java static int a = 10; ``` **Non-Static Members** * Created only when an object is created. * Stored in **Heap memory**. Example: ```java int x = 10; ``` --- ### 5️⃣ Why Do We Create Objects? Objects are created for two main reasons: ✔ To allocate memory for **non-static members** ✔ To access **non-static variables and methods** Example: ```java Main obj = new Main(); ``` --- ### 6️⃣ What Happens When We Use the `new` Operator? When the JVM encounters: ```java new Main(); ``` The following steps occur: 1️⃣ Memory is allocated in the **Heap** 2️⃣ Non-static variables are loaded into memory 3️⃣ Variables are initialized (default or assigned values) 4️⃣ Constructor is executed 5️⃣ The memory address of the object is returned The variable `obj` stores the **reference (address)** of the object. --- ### 7️⃣ Example Program ```java public class Main { int x = 10; public static void main(String[] args) { int y = 10; System.out.println(y); Main obj = new Main(); System.out.println(obj.x); } } ``` In this example: * `y` is stored in **Stack memory** * `x` is stored in **Heap memory** * `obj` is a **reference variable** pointing to the object --- ### 8️⃣ Garbage Collection Once the `main()` method finishes execution: * Local variables are removed from the stack * The reference to the object may be lost If no references point to the object anymore, the **Java Garbage Collector** automatically removes it from memory. This process is called **Garbage Collection**. --- #Java #OOP #JVM #JavaMemoryModel #Programming #SoftwareEngineering #BackendDevelopment
To view or add a comment, sign in
Explore content categories
- Career
- Productivity
- Finance
- Soft Skills & Emotional Intelligence
- Project Management
- Education
- Technology
- Leadership
- Ecommerce
- User Experience
- Recruitment & HR
- Customer Experience
- Real Estate
- Marketing
- Sales
- Retail & Merchandising
- Science
- Supply Chain Management
- Future Of Work
- Consulting
- Writing
- Economics
- Artificial Intelligence
- Employee Experience
- Workplace Trends
- Fundraising
- Networking
- Corporate Social Responsibility
- Negotiation
- Communication
- Engineering
- Hospitality & Tourism
- Business Strategy
- Change Management
- Organizational Culture
- Design
- Innovation
- Event Planning
- Training & Development