🚀 Comparable vs Comparator in Java 8 (with Streams Examples) Sorting is one of the most common operations in real-world applications. In Java, we use Comparable and Comparator — and with Java 8 Streams, sorting became even more powerful and readable. Let’s break it down 👇 🔹 1️⃣ Comparable (Natural Ordering) Used when a class defines its own default sorting logic. class Employee implements Comparable<Employee> { private int salary; @Override public int compareTo(Employee other) { return this.salary - other.salary; // natural order } } Usage with Streams: employees.stream() .sorted() .forEach(System.out::println); 👉 Best when sorting logic is fixed and always the same. 🔹 2️⃣ Comparator (Custom Ordering) Used when sorting logic is external or multiple sorting strategies are required. employees.stream() .sorted(Comparator.comparing(Employee::getName)) .forEach(System.out::println); 🔹 3️⃣ Reverse Sorting employees.stream() .sorted(Comparator.comparing(Employee::getSalary).reversed()) .forEach(System.out::println); 🔹 4️⃣ Multiple Field Sorting (Then Comparing) employees.stream() .sorted(Comparator.comparing(Employee::getDepartment) .thenComparing(Employee::getSalary)) .forEach(System.out::println); 🔹 5️⃣ Null Safe Sorting employees.stream() .sorted(Comparator.comparing( Employee::getName, Comparator.nullsLast(String::compareTo) )) .forEach(System.out::println); 🔥 Key Differences ✔ Comparable → Inside the class ✔ Comparator → Outside the class ✔ Comparable → Single natural order ✔ Comparator → Multiple custom sorting logics ✔ Java 8 → Lambda + Method Reference makes Comparator extremely powerful. #Java #Java8 #Streams #Comparator #Comparable #BackendDevelopment #SoftwareEngineering
Java 8 Streams Sorting with Comparable and Comparator
More Relevant Posts
-
Every Java developer has a file in their codebase with a class that does nothing but hold two values — and somehow runs to 40 lines. Records are the fix nobody told you about. 💡 https://lnkd.in/gmpX2F6G
To view or add a comment, sign in
-
🚀 Java Stream API – Writing Cleaner and More Powerful Code Before Java 8, developers mostly used loops to process collections. While loops work well, they can make code longer and harder to read when performing multiple operations. With Stream API, Java introduced a functional programming style that makes data processing cleaner, more readable, and more expressive. Let’s look at a simple example 👇 🔹 Without Stream API List<Integer> numbers = Arrays.asList(1,2,3,4,5,6); for(Integer n : numbers){ if(n % 2 == 0){ System.out.println(n); } } 🔹 With Stream API List<Integer> numbers = Arrays.asList(1,2,3,4,5,6); numbers.stream() .filter(n -> n % 2 == 0) .forEach(System.out::println); Much cleaner and easier to understand. 💡 Key Features of Stream API ✔ Processes collections in a functional style ✔ Reduces boilerplate code ✔ Supports operations like "filter", "map", "sorted", "reduce" ✔ Allows easy parallel processing Example with "map": List<String> names = Arrays.asList("java","spring","hibernate"); names.stream() .map(String::toUpperCase) .forEach(System.out::println); Output: JAVA SPRING HIBERNATE Streams don’t store data, they process data from collections. Understanding Stream API helps developers write more expressive and maintainable Java code. #Java #Java8 #StreamAPI #Programming #SoftwareDevelopment #JavaDeveloper
To view or add a comment, sign in
-
-
Core Java Fundamentals :Key Traits of Metaspace Permanent Generation in Java PermGen (Permanent Generation) was a memory area in the Java Virtual Machine (JVM) used before Java 8 to store class metadata, interned strings, and static variables. It was part of the JVM heap space and had a fixed size, making it difficult to manage memory efficiently. Fixed and Hard-to-Tune Size in PermGen PermGen had a fixed maximum size, which was often too small for applications with many classes. Correct Tuning was Tricky Even though it was configurable using -XX:MaxPermSize, tuning it correctly was difficult. PermGen was not dynamically expanding Unlike Metaspace, on the other hand, dynamically expands using native memory, eliminating manual tuning issues. OutOfMemoryError If class metadata exceeded 256MB, the application would crash with OutOfMemoryError: PermGen space. Key Features of Metaspace Stores Class Metadata It holds information about classes, methods, and their runtime representations (like method bytecode and field details). Unlike PermGen, it does not store Java objects (which reside in the heap). Uses Native Memory Unlike PermGen, which had a fixed maximum size, Metaspace dynamically expands using native memory(outside the heap), reducing Out of memory errors. Automatic Growth & GC Handling The JVM automatically manages Metaspace size based on the application’s needs. Class metadata is garbage collected when classes are no longer needed (such as when an application uses dynamic class loading). Configurable Maximum Size -XX:MaxMetaspaceSize=256m // Limits Metaspace to 256MB -XX:MetaspaceSize=128m // Initial size before expanding ☕ If this helped you — support my work: 👉 Buy Me a Coffee -https://lnkd.in/ebXVUJn2 #JVMInternals #JavaPerformance #MemoryManagement #SpringBoot #Microservices #SystemDesign
To view or add a comment, sign in
-
-
☕ Java Generics – Bounded Type Parameters Explained Generics in Java provide type safety and flexibility. But sometimes, we need to restrict the type of objects that can be passed to a generic method or class. That’s where Bounded Type Parameters come into play. 🔹 What Are Bounded Type Parameters? There may be situations where a method should only accept specific types. For example: A method that works with numbers should only accept instances of Number or its subclasses. To restrict types, we use: <T extends SomeClass> The extends keyword specifies the upper bound of the type parameter. 👉 In generics, extends means: “extends” for classes “implements” for interfaces 🔹 Example – Generic Method to Find Maximum of Three Values public static <T extends Comparable<T>> T maximum(T x, T y, T z) { T max = x; if (y.compareTo(max) > 0) { max = y; } if (z.compareTo(max) > 0) { max = z; } return max; } 📌 Explanation: ✔ <T extends Comparable<T>> ensures only comparable types are allowed ✔ Uses compareTo() method ✔ Returns the largest of three objects 🔹 Sample Output Max of 3, 4 and 5 is 5 Max of 6.6, 8.8 and 7.7 is 8.8 Max of pear, apple and orange is pear This works for: ✔ Integers ✔ Doubles ✔ Strings Because all of them implement the Comparable interface. 💡 Bounded type parameters improve type safety, enforce constraints at compile time, and make generic methods more powerful and reliable. Mastering Generics is essential for writing reusable and scalable Java applications. #Java #Generics #BoundedTypeParameters #JavaProgramming #OOP #FullStackJava #Developers #AshokIT
To view or add a comment, sign in
-
📌Exception Handling in Java ⚠️ ✅Exception Handling is a mechanism to handle unexpected situations that occur while a program is running. When an exception occurs, it disrupts the normal flow of the program. Common examples: • Accessing an invalid index in an array→ ArrayIndexOutOfBoundsException • Dividing a number by zero→ ArithmeticException Java provides thousands of exception classes to handle different runtime problems. 📌 Types of Exceptions in Java 1️⃣ Built-in Exceptions These are predefined exceptions provided by Java. ✅Checked Exceptions -Checked by the compiler at compile time Must be handled using try-catch or declared using throws Examples: IOException SQLException ClassNotFoundException ✅Unchecked Exceptions -Not checked by the compiler at compile time Occur mainly due to programming errors Examples: ArithmeticException NullPointerException ClassCastException 2️⃣ User-Defined (Custom) Exceptions Java also allows developers to create their own exceptions. This is useful when we want to represent specific business logic errors. Basic rules to create a custom exception: 1️⃣ Extend the Exception class 2️⃣ Create a constructor with a message 3️⃣ Throw the exception using throw 4️⃣ Handle it using try-catch 📌 Finally Block ✅The finally block always executes after the try-catch block, whether an exception occurs or not. It is commonly used for cleanup tasks, such as: Closing database connections Closing files Releasing resources 📌 Try-With-Resources ✅Sometimes developers forget to close resources manually. To solve this problem, Java introduced Try-With-Resources. It automatically closes resources once the block finishes execution. This makes resource management safer and cleaner. 📌 Important Keywords ✅throw : Used to explicitly create and throw an exception object. ✅throws: Used in the method signature to indicate that a method may throw an exception. Grateful to my mentor Suresh Bishnoi Sir for explaining Java concepts with such clarity and practical depth . If this post added value, feel free to connect and share it with someone learning Java. #Java #ExceptionHandling #CoreJava #JavaDeveloper #BackendDevelopment #SoftwareEngineering #InterviewPreparation #JavaProgramming #CleanCode
To view or add a comment, sign in
-
-
Day 10 – == vs .equals() in Java ⏳ 1 Minute Java Clarity – Understanding how Java compares Strings This is one of the most confusing topics for beginners in Java ❓ Are these the same? String a = "Java"; String b = "Java"; 👉 a == b → true 👉 a.equals(b) → true Looks same right? But wait ⚠️ 📌 What does == do? It checks if both references point to the same object (memory location). 📌 What does .equals() do? It checks if the values (content) are equal. 💥 Now see this: String a = new String("Java"); String b = new String("Java"); 👉 a == b → false ❌ (different objects in memory) 👉 a.equals(b) → true ✅ (same text content) 💡 Quick Summary ✔ == → compares memory addresses. ✔ .equals() → compares actual values. 🔹 Always use .equals() for Strings unless you specifically need to check if two variables point to the exact same memory slot. 🔹 Next → String Immutability in Java Have you ever spent hours debugging because of a == mistake? #Java #BackendDeveloper #JavaFullStack #LearningInPublic #Programming #JavaProgramming #equals() #SoftwareEngineering #TechCommunity
To view or add a comment, sign in
-
-
How Does "ConcurrentHashMap" Achieve Thread Safety in Java? In multithreaded applications, using a normal "HashMap" can lead to race conditions and inconsistent data. While "Hashtable" provides thread safety, it locks the entire map, which can reduce performance. This is where "ConcurrentHashMap" comes in. It provides high performance and thread safety by allowing multiple threads to read and write simultaneously. 🔹 How it Works 1️⃣ Segment / Bucket Level Locking (Java 7) Instead of locking the entire map, "ConcurrentHashMap" divides the map into segments. Each segment can be locked independently, allowing multiple threads to work on different segments. This significantly improves concurrency. 2️⃣ Fine-Grained Locking (Java 8+) In Java 8, the implementation was improved further. Instead of segments, it uses: ✔ CAS (Compare-And-Swap) operations ✔ Node-level synchronization when needed This allows better performance and scalability. 🔹 Example import java.util.concurrent.ConcurrentHashMap; public class Example { public static void main(String[] args) { ConcurrentHashMap<Integer, String> map = new ConcurrentHashMap<>(); map.put(1, "Java"); map.put(2, "Spring"); map.put(3, "Kafka"); map.forEach((k,v) -> System.out.println(k + " : " + v)); } } Multiple threads can safely read and update the map without blocking the entire structure. 🔹 Key Benefits ✔ Thread-safe operations ✔ Better performance than "Hashtable" ✔ Allows concurrent reads and writes ✔ Highly scalable in multithreaded environments In simple terms: "HashMap" → Not thread safe "Hashtable" → Thread safe but slow "ConcurrentHashMap" → Thread safe and optimized for concurrency. #Java #ConcurrentHashMap #Multithreading #JavaDeveloper #Concurrency #Programming
To view or add a comment, sign in
-
🚀 Java Multithreading – Key Concepts Every Backend Developer Should Know Multithreading is one of the most important concepts in Java backend development. It allows applications to perform multiple tasks concurrently, improving performance and resource utilization. Here are some essential multithreading concepts every developer should understand 👇 🧵 1️⃣ Thread Life Cycle A thread goes through several states during execution: • New – Thread is created but not started • Runnable – Ready to run and waiting for CPU • Running – Thread is actively executing • Blocked / Waiting – Waiting for resources or another thread • Terminated – Execution completed ⚙️ 2️⃣ Thread Methods Commonly used thread methods: • start() – Starts a new thread • run() – Contains the logic executed by the thread • sleep() – Pauses the thread for a specific time • join() – Waits for another thread to finish execution • yield() – Allows other threads to execute • interrupt() – Interrupts a running thread 🧵 3️⃣ Thread Pool A Thread Pool manages a collection of reusable threads. Instead of creating a new thread for every task, tasks are assigned to threads from the pool. Benefits: • Improves performance • Reduces thread creation overhead • Better resource management • Used heavily in backend frameworks and web servers ⚠️ 4️⃣ Deadlock A Deadlock occurs when two or more threads are waiting for each other to release resources, causing the program to stop progressing. Example situation: Thread A holds Resource 1 and waits for Resource 2 Thread B holds Resource 2 and waits for Resource 1 Both threads wait forever. 🔒 5️⃣ Synchronization Synchronization ensures that only one thread accesses a critical section at a time to avoid data inconsistency. Types of Synchronization in Java: • Synchronized Method – Locks the entire method • Synchronized Block – Locks a specific block of code • Static Synchronization – Locks the class level • Explicit Locks – Using ReentrantLock Purpose: • Prevent race conditions • Maintain data consistency • Control concurrent access 💡 Why Multithreading Matters Multithreading is widely used in: • Web servers handling multiple requests • Backend APIs • File processing systems • High-performance applications Mastering multithreading concepts helps developers build scalable and efficient applications. #Java #Multithreading #BackendDevelopment #JavaDeveloper #Concurrency #ThreadPool #SoftwareEngineering
To view or add a comment, sign in
-
-
Discover the differences between Stack and Heap in Java: how memory is allocated, managed, and used for variables, objects, and method calls.
To view or add a comment, sign in
-
📌 Memory Leak vs High Memory Usage in Java — A Practical Explanation One common confusion I see while debugging Java applications is this: High memory usage ≠ memory leak. After working with production JVM systems for several years, I’ve learned the difference usually becomes clear when you observe how memory behaves over time. Here’s a simple way to think about it. 🔹 High Memory Usage High memory usage means the application is using a large portion of the heap, but for legitimate reasons. Examples: Large caches (e.g., product catalogs, pricing data) Batch processing jobs loading many objects High request throughput creating many temporary objects Key characteristics: ✔ Memory increases during workload ✔ Garbage Collector eventually frees unused objects ✔ Heap usage goes up and down in cycles In GC graphs, this usually looks like a sawtooth pattern: memory rises → GC runs → memory drops. This is normal JVM behavior. 🔹 Memory Leak A memory leak happens when objects should be released but remain referenced, so the Garbage Collector cannot reclaim them. Common causes in Java: Static collections growing indefinitely Caches without eviction policies Objects stored in maps or lists that are never cleared ThreadLocal variables not cleaned up Long-lived listeners or callbacks Key characteristics: ❌ Heap usage keeps increasing over time ❌ After GC, memory does not drop significantly ❌ Eventually leads to OutOfMemoryError In monitoring graphs, memory forms a steady upward trend. 🔹 A Practical Rule of Thumb When investigating memory issues, I usually ask: 1️⃣ Does memory drop after GC? 2️⃣ Is the baseline heap slowly increasing over time? 3️⃣ Which objects dominate the heap in a memory dump? These three questions often reveal whether it’s a leak or simply load-driven usage. 📌 One important lesson from production systems: Most “memory leak” alerts actually turn out to be workload spikes, caching behavior, or misconfigured heap sizes. Understanding the difference can save hours of unnecessary debugging. 💬 In your experience, what has caused more trouble in production: actual leaks or misinterpreted memory spikes? #Java #JVM #MemoryManagement #GarbageCollection #BackendEngineering #PerformanceTuning #SoftwareEngineering
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