• Gson in Java – A Complete Guide with Examples

    What is Gson?

    Gson (Google’s JSON library) is a powerful Java library developed by Google to serialize Java objects into JSON format and deserialize JSON back into Java objects. It is simple to use and provides flexibility in handling JSON data.

    ✅ Why Gson?

    • Lightweight and easy to use
    • Supports serialization and deserialization
    • Handles complex objects and generic types
    • No need for XML configuration
    • Integrates well with Java applications

    ⚡How to Add Gson to Your Project?

    If you are using Maven, add the following dependency to your pom.xml:

    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>2.10.1</version>
    </dependency>
    

    For Gradle, add:

    implementation 'com.google.code.gson:gson:2.10.1'
    

    ➤ Basic Example – Serialization and Deserialization

    1️⃣ Java Object to JSON (Serialization)

    import com.google.gson.Gson;
    
    class Student {
        private String name;
        private int age;
        private String course;
    
        public Student(String name, int age, String course) {
            this.name = name;
            this.age = age;
            this.course = course;
        }
    }
    
    public class GsonSerializationExample {
        public static void main(String[] args) {
            Student student = new Student("Ashish", 22, "Computer Science");
            Gson gson = new Gson();
    
            // Convert Java object to JSON
            String json = gson.toJson(student);
    
            System.out.println("Serialized JSON: " + json);
        }
    }
    

    Output:

    {"name":"Ashish","age":22,"course":"Computer Science"}

    2️⃣ JSON to Java Object (Deserialization)

    import com.google.gson.Gson;
    
    public class GsonDeserializationExample {
        public static void main(String[] args) {
            String json = "{\"name\":\"Bhasker\",\"age\":25,\"course\":\"Mathematics\"}";
            Gson gson = new Gson();
    
            // Convert JSON to Java object
            Student student = gson.fromJson(json, Student.class);
    
            System.out.println("Student Name: " + student.name);
            System.out.println("Student Age: " + student.age);
            System.out.println("Student Course: " + student.course);
        }
    }
    

    ✅ Working with Collections

    Example: List of Objects

    import com.google.gson.Gson;
    import com.google.gson.reflect.TypeToken;
    import java.lang.reflect.Type;
    import java.util.List;
    
    public class GsonListExample {
        public static void main(String[] args) {
            String jsonArray = "[{\"name\":\"Alice\",\"age\":22,\"course\":\"CS\"}," +
                                "{\"name\":\"Bob\",\"age\":25,\"course\":\"Math\"}]";
    
            Gson gson = new Gson();
            Type studentListType = new TypeToken<List<Student>>() {}.getType();
    
            List<Student> students = gson.fromJson(jsonArray, studentListType);
    
            for (Student s : students) {
                System.out.println(s.name + " - " + s.course);
            }
        }
    }
    

    ✅ Custom Serialization and Deserialization

    If you want to customize how a class is serialized/deserialized, implement JsonSerializer and JsonDeserializer.

    import com.google.gson.*;
    import java.lang.reflect.Type;
    
    class CustomStudentSerializer implements JsonSerializer<Student> {
        @Override
        public JsonElement serialize(Student student, Type typeOfSrc, JsonSerializationContext context) {
            JsonObject jsonObject = new JsonObject();
            jsonObject.addProperty("studentName", student.name);
            jsonObject.addProperty("studentAge", student.age);
            return jsonObject;
        }
    }
    

    And register it:

    Gson gson = new GsonBuilder()
        .registerTypeAdapter(Student.class, new CustomStudentSerializer())
        .create();
    

    ✅ Advantages of Gson

    • Simple API
    • Good performance
    • No need for annotations unless custom behavior is needed
    • Handles nested objects and generics
    • Handles null values gracefully

    ⚠️ Limitations of Gson

    • No streaming API like Jackson (though it does support streaming but not optimized for large data)
    • Does not support JAXB annotations
    • Custom serialization logic requires additional code

    🎯Conclusion

    Gson is a great library for handling JSON in Java applications. It provides easy-to-use APIs for serialization and deserialization, with flexibility for custom logic when necessary. Perfect for small to medium-sized applications or when you need quick and efficient JSON handling.

  • StringBuffer in Java: Complete Guide with Code Examples

    Introduction

    In Java, handling strings efficiently is crucial, especially when frequent modifications are involved. The StringBuffer class is a powerful alternative to String for such scenarios. Unlike String, which is immutable, StringBuffer allows modification of string content without creating a new object every time, making it ideal for performance-critical applications.

    What is StringBuffer in Java?

    StringBuffer is a thread-safe, mutable sequence of characters provided by Java in the java.lang package. It allows modification of strings (append, insert, delete, reverse, etc.) without creating new objects, which improves memory efficiency and performance.

    Key Characteristics

    • Mutable: The content can be changed.
    • Thread-safe: Methods are synchronized, making it suitable for multi-threaded environments.
    • Efficient for frequent modifications.

    String vs StringBuffer vs StringBuilder

    FeatureStringStringBufferStringBuilder
    MutabilityImmutableMutableMutable
    Thread SafetyNot Thread-safeThread-safeNot Thread-safe
    PerformanceLess efficient in loopsSlower than StringBuilder but thread-safeFast and efficient for single-threaded use cases

    Creating a StringBuffer Object

    StringBuffer sb1 = new StringBuffer(); // Creates an empty buffer with default capacity (16)
    StringBuffer sb2 = new StringBuffer("Hello"); // Creates buffer initialized with "Hello"
    StringBuffer sb3 = new StringBuffer(50); // Creates empty buffer with specified capacity
    

    Common StringBuffer Methods and Examples

    1. append()

    Appends the specified string to this buffer.

    StringBuffer sb = new StringBuffer("Hello");
    sb.append(" World");
    System.out.println(sb); // Output: Hello World
    

    2. insert()

    Inserts the specified string at the specified index.

    StringBuffer sb = new StringBuffer("Hello World");
    sb.insert(5, ",");
    System.out.println(sb); // Output: Hello, World
    

    3. replace()

    Replaces characters from start index to end index with a new string.

    StringBuffer sb = new StringBuffer("Hello World");
    sb.replace(6, 11, "Java");
    System.out.println(sb); // Output: Hello Java
    

    4. delete()

    Deletes characters from start index to end index.

    StringBuffer sb = new StringBuffer("Hello Java");
    sb.delete(5, 10);
    System.out.println(sb); // Output: Hello
    

    5. reverse()

    Reverses the sequence of characters.

    StringBuffer sb = new StringBuffer("Hello");
    sb.reverse();
    System.out.println(sb); // Output: olleH
    

    6. capacity() and ensureCapacity()

    • capacity(): Returns current capacity.
    • ensureCapacity(int minCapacity): Increases capacity if needed.
    StringBuffer sb = new StringBuffer();
    System.out.println(sb.capacity()); // Default is 16
    sb.ensureCapacity(50);
    System.out.println(sb.capacity()); // At least 50
    

    Scenario Examples

    Scenario 1: Building a Large String Efficiently

    StringBuffer sb = new StringBuffer();
    for (int i = 0; i < 1000; i++) {
        sb.append(i).append(", ");
    }
    System.out.println(sb.substring(0, 50) + "...");
    

    Why StringBuffer?
    Using String would create a new object on each iteration, leading to performance overhead.

    Scenario 2: Multi-threaded Environment

    public class StringBufferExample {
        private static StringBuffer buffer = new StringBuffer();
    
        public static void main(String[] args) throws InterruptedException {
            Thread t1 = new Thread(() -> buffer.append("A"));
            Thread t2 = new Thread(() -> buffer.append("B"));
    
            t1.start();
            t2.start();
    
            t1.join();
            t2.join();
    
            System.out.println(buffer.toString()); // Output: AB or BA (depends on thread scheduling)
        }
    }
    

    When to Use StringBuffer vs StringBuilder

    • Use StringBuffer when working in multi-threaded environments where thread safety is needed.
    • Use StringBuilder when thread safety is not required for better performance.

    ✍️Important Points to Remember

    • StringBuffer is synchronized, making it thread-safe.
    • Always prefer StringBuilder for non-concurrent scenarios due to better performance.
    • StringBuffer’s capacity grows automatically but can be managed using ensureCapacity().

    🎯Conclusion

    StringBuffer is a powerful tool in Java for mutable and thread-safe string manipulation. Understanding its methods and appropriate use cases is key to writing efficient Java applications.

  • Complete Guide to Java StringBuilder with Examples & Best Practices

    Introduction

    In Java, StringBuilder is a mutable sequence of characters. Unlike String, which is immutable, StringBuilder allows us to modify the content of the string without creating new objects every time we update it. This makes StringBuilder ideal for scenarios where we need to perform many modifications on strings, such as in loops or intensive string manipulations.

    Why StringBuilder?

    • Performance: Repeated string concatenation using String results in the creation of many temporary objects, leading to memory and CPU overhead.
    • Mutability: StringBuilder offers methods to modify the string directly, improving efficiency.
    • Use Case: It’s especially useful in scenarios like loops, building large strings, and where thread safety is not a concern (use StringBuffer if thread safety is required).

    Key Features of StringBuilder

    • Mutable sequence of characters.
    • Not synchronized (faster than StringBuffer).
    • Provides methods like append(), insert(), delete(), reverse(), and replace().

    How to Create a StringBuilder Object

    StringBuilder sb1 = new StringBuilder(); // Creates an empty StringBuilder
    StringBuilder sb2 = new StringBuilder("Initial text"); // Creates StringBuilder with initial content
    

    Commonly Used Methods of StringBuilder

    1. append()

    Appends the specified string or data to the current sequence.

    StringBuilder sb = new StringBuilder("Hello");
    sb.append(" World");
    System.out.println(sb.toString()); // Output: Hello World
    

    2. insert()

    Inserts the specified string at the given index.

    StringBuilder sb = new StringBuilder("Hello World");
    sb.insert(5, ",");
    System.out.println(sb.toString()); // Output: Hello, World
    

    3. replace()

    Replaces a substring with the specified string.

    StringBuilder sb = new StringBuilder("Hello World");
    sb.replace(6, 11, "Java");
    System.out.println(sb.toString()); // Output: Hello Java
    

    4. delete()

    Deletes a substring between the specified indices.

    StringBuilder sb = new StringBuilder("Hello Java World");
    sb.delete(5, 10);
    System.out.println(sb.toString()); // Output: Hello World
    

    5. reverse()

    Reverses the characters in the sequence.

    StringBuilder sb = new StringBuilder("Hello");
    sb.reverse();
    System.out.println(sb.toString()); // Output: olleH
    

    6. length() and capacity()

    • length() returns the number of characters.
    • capacity() returns the allocated storage size.
    StringBuilder sb = new StringBuilder();
    System.out.println("Length: " + sb.length());    // 0
    System.out.println("Capacity: " + sb.capacity()); // Default capacity, usually 16
    

    Performance Comparison: String vs StringBuilder

    public class PerformanceTest {
        public static void main(String[] args) {
            long startTime = System.currentTimeMillis();
            String str = "";
            for (int i = 0; i < 10000; i++) {
                str += "a";  // Inefficient due to creating new String objects each time
            }
            long endTime = System.currentTimeMillis();
            System.out.println("String concatenation time: " + (endTime - startTime) + " ms");
    
            startTime = System.currentTimeMillis();
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < 10000; i++) {
                sb.append("a");  // Efficient as it modifies the same object
            }
            endTime = System.currentTimeMillis();
            System.out.println("StringBuilder append time: " + (endTime - startTime) + " ms");
        }
    }
    

    Typically, StringBuilder performs much faster.

    When to Use StringBuilder vs StringBuffer vs String

    FeatureStringStringBuilderStringBuffer
    MutabilityImmutableMutableMutable
    Thread-SafeYesNoYes
    PerformanceLow (for frequent modifications)HighModerate
    Use CaseStatic textSingle-threaded modificationsMulti-threaded modifications

    🎯Conclusion

    StringBuilder is a powerful and efficient class for string manipulation in Java, particularly useful in situations where performance matters. Understanding its key methods helps in writing more efficient and cleaner code compared to using the String class for every small string modification.

  • How to Join a List of Strings with Custom Delimiter, Prefix, and Suffix Using Java 8 Streams

    ✅ Problem :

    How do you join a list of strings with a custom delimiter, prefix, and suffix using Java 8 Streams?

    ✅ Example:

    import java.util.Arrays;
    import java.util.List;
    import java.util.stream.Collectors;
    
    public class JoinStringsCustomDelimiter {
        public static void main(String[] args) {
            List<String> words = Arrays.asList("Apple", "Banana", "Grapes", "Blueberry");
    
            // Join strings with custom delimiter, prefix, and suffix
            String result = words.stream()
                .collect(Collectors.joining(", ", "[", "]"));
    
            System.out.println(result);
        }
    }
    

    ✅ Output:

    [Apple, Banana, Grapes, Blueberry]

    ✅ Explanation:

    1. words.stream(): Converts the list of strings into a Stream of String objects.
    2. Collectors.joining(“, “, “[“, “]”):
      • ", " is the delimiter between elements.
      • "[" is the prefix added at the beginning of the result.
      • "]" is the suffix added at the end of the result.
    3. The result is a single string with all words joined by the delimiter and wrapped in brackets.
    4. The output is printed using System.out.println().

  • Find the Sum of the First Two Elements in a List Using Java 8 Streams

    ✅ Problem :

    Using Java 8 Streams, how do you find the sum of the first two numbers in a list?

    ✅ Example:

    import java.util.Arrays;
    import java.util.List;
    
    public class SumOfFirstTwoNumbers {
        public static void main(String[] args) {
            List<Integer> numbers = Arrays.asList(87, 45, 35, 74, 325);
    
            // Find sum of the first two numbers
            int sumOfTwoNumbers = numbers.stream()
                .limit(2)                      // Take only the first two elements
                .mapToInt(Integer::intValue)  // Convert Integer to int
                .sum();                       // Sum the elements
    
            System.out.println("Sum of first two numbers = " + sumOfTwoNumbers);
        }
    }
    

    ✅ Output:

    Sum of first two numbers = 132
    

    (Since 87 + 45 = 132)


    ✅ Explanation:

    1. numbers.stream(): Converts the list of integers into a Stream of Integer objects.
    2. limit(2): Limits the stream to only the first two elements of the list.
    3. mapToInt(Integer::intValue): Converts each Integer object to primitive int for efficient summation.
    4. sum(): Calculates the sum of the remaining elements in the stream.
    5. Finally, the result is printed using System.out.println().
  • Find Words with Exactly ‘K’ Vowels in a Sentence in Java

    ✅ Correct Problem Sentence:

    Using Java 8 Streams, how do you extract all words from a sentence that contain exactly K vowels?

    ✅ Example:

    import java.util.Arrays;
    
    public class WordsWithVowels {
        public static void main(String[] args) {
            String sentence = "Why only half? Because we compare characters from both ends, no need to go full length.";
            int k = 3;  // Number of vowels to match in each word
    
            Arrays.stream(sentence.split("\\s+"))  // Split sentence into words
                .map(word -> word.replaceAll("[^a-zA-Z]", ""))  // Remove punctuation
                .filter(word -> countVowels(word) == k)         // Filter words with exactly k vowels
                .forEach(System.out::println);                 // Print each matching word
        }
    
        public static long countVowels(String word) {
            return word.chars()
                .mapToObj(ch -> (char) ch)
                .filter(ch -> "aeiouAEIOU".indexOf(ch) != -1)
                .count();
        }
    }
    

    ✅ Explanation:

    1. sentence.split(“\s+”): Splits the sentence by spaces into words.
    2. map(word -> word.replaceAll(“[^a-zA-Z]”, “”)): Removes punctuation (like ?, ., ,) from each word so only letters remain.
    3. filter(word -> countVowels(word) == k): Filters words where the number of vowels equals k (in this example, 3).
    4. forEach(System.out::println): Prints each word that satisfies the condition.
    5. The countVowels(String word) method:
      • Converts the word into a stream of characters (word.chars()).
      • Maps each int character code to a Character object.
      • Filters only vowels (case-insensitive).
      • Returns the count of vowels in the word.

    ✅ Sample Output (with k = 3):

    Because
    compare
    characters
    length

  • Sum of Unique Numbers in a List in Java

    Problem :

    How do you calculate the sum of only unique elements from a list using Java 8 Streams?

    ✅ Example:

    import java.util.Arrays;
    import java.util.List;
    
    public class SumOfUniqueNumbers {
        public static void main(String[] args) {
            List<Integer> numbers = Arrays.asList(23, 45, 23, 15, 15, 78, 23, 85, 65);
    
            // Calculate sum of unique numbers
            int uniqueNumbersSum = numbers.stream()
                .distinct()                     // Get only unique elements
                .mapToInt(Integer::intValue)    // Convert Integer to int
                .sum();                         // Sum the unique numbers
    
            System.out.println("Sum of unique numbers: " + uniqueNumbersSum);
        }
    }
    

    ✅ Explanation:

    1. numbers.stream(): Creates a stream from the list of integers.
    2. distinct(): Removes duplicate elements from the stream, keeping only unique values.
    3. mapToInt(Integer::intValue): Converts Integer objects to primitive int for efficient processing.
    4. sum(): Computes the sum of the resulting IntStream.
    5. Finally, the result is printed with System.out.println().

    ✅ Output:

    Sum of unique numbers: 311
    

    Because the unique numbers are:

    23 + 45 + 15 + 78 + 85 + 65 = 311

  • Generate Summary Statistics of a List in Java 8

    Problem:

    Using Java 8 Streams, how do you quickly find minimum, maximum, sum, average, and count of numbers in a list without writing separate loops?

    ✅ Example:

    import java.util.Arrays;
    import java.util.IntSummaryStatistics;
    import java.util.List;
    
    public class SummaryStatisticsExample {
        public static void main(String[] args) {
            List<Integer> numbers = Arrays.asList(5, 3, 9, 1, 7);
    
            // Generate summary statistics
            IntSummaryStatistics stats = numbers.stream()
                .mapToInt(n -> n)  // Convert Integer to int
                .summaryStatistics();
    
            // Print results
            System.out.println("Minimum: " + stats.getMin());
            System.out.println("Maximum: " + stats.getMax());
            System.out.println("Sum: " + stats.getSum());
            System.out.println("Average: " + stats.getAverage());
            System.out.println("Count: " + stats.getCount());
        }
    }
    

    ✅ Explanation:

    1. numbers.stream(): Create a stream of integers from the list.
    2. mapToInt(n -> n): Converts the Stream<Integer> into an IntStream. This is necessary because IntSummaryStatistics works with primitive int.
    3. summaryStatistics(): This terminal operation generates an IntSummaryStatistics object, which contains:
      • Minimum value → getMin()
      • Maximum value → getMax()
      • Sum of all numbers → getSum()
      • Average → getAverage()
      • Count of elements → getCount()
    4. The results are printed using System.out.println.

    ✅ Output:

    Minimum: 1
    Maximum: 9
    Sum: 25
    Average: 5.0
    Count: 5

  • Find the Sum of the First Two Elements in a List Using Java 8 Streams – Quick & Easy Example

    Problem:
    Using Java 8 Streams, how do you find the sum of the first two numbers in a list?

    ✅ Example:

    import java.util.Arrays;
    import java.util.List;
    
    public class SumOfFirstTwoNumbers {
    
        public static void main(String[] args) {
            List<Integer> numbers = Arrays.asList(87, 45, 35, 74, 325);
    
            int sumOfTwoNumbers = numbers.stream()
                    .limit(2)  // Take first two elements
                    .mapToInt(Integer::intValue)  // Convert to int stream
                    .sum();  // Calculate the sum
    
            System.out.println("Sum of first two numbers = " + sumOfTwoNumbers);
        }
    }
    

    ✅ Output:

    Sum of first two numbers = 132

    ✅ Explanation:

    1. The list of numbers: [87, 45, 35, 74, 325]
    2. .stream() creates a stream of elements from the list.
    3. .limit(2) restricts the stream to the first two elements: [87, 45].
    4. .mapToInt(Integer::intValue) converts Integer to primitive int for summing.
    5. .sum() computes the sum of the two numbers:
      87 + 45 = 132.
    6. Finally, print the result: System.out.println("Sum of first two numbers = " + sumOfTwoNumbers);

  • Find the First Repeating Character in a String in Java

    Problem:
    Using Java 8 Streams, how do you find the first repeating character in a given string?

    ✅ Example:

    import java.util.LinkedHashMap;
    import java.util.Map;
    import java.util.stream.Collectors;
    
    public class FindFirstRepeatingCharacter {
    
        public static void main(String[] args) {
            String input = "repeating-characters";
    
            input.chars()
                    .mapToObj(ch -> (char) ch)
                    .collect(Collectors.groupingBy(
                            ch -> ch,
                            LinkedHashMap::new,  // Preserve insertion order
                            Collectors.counting()))
                    .entrySet()
                    .stream()
                    .filter(entry -> entry.getValue() > 1)  // Find characters appearing more than once
                    .map(Map.Entry::getKey)
                    .findFirst()
                    .ifPresent(System.out::println);
        }
    }
    

    ✅ Output:

    e

    ✅ Explanation:

    1. Step 1 – Convert String to Character Stream: input.chars().mapToObj(ch -> (char) ch)
      • Converts the string "repeating-characters" to a stream of characters.
    2. Step 2 – Group by Character Count: .collect(Collectors.groupingBy( ch -> ch, LinkedHashMap::new, Collectors.counting()))
      • Creates a LinkedHashMap<Character, Long> where the key is the character and the value is the count of occurrences.
      • LinkedHashMap preserves the order of first appearance.
    3. Step 3 – Filter Repeating Characters: .filter(entry -> entry.getValue() > 1)
      • Keeps only characters that occur more than once.
    4. Step 4 – Pick First Repeating Character: .findFirst()
      • Finds the first character (in the original order) that repeats.
    5. Step 5 – Print the Character: ifPresent(System.out::println);