Saturday, 30 September 2023

Difference Between PermGen (Permanent Generation) and Metaspace in Java

        In this post, we will discuss the differences between PermGen (Permanent Generation) and Metaspace in Java.

Before Java 8, class metadata was stored in the PermGen (Permanent Generation) memory space. If the allocated PermGen space was exhausted, the JVM threw an OutOfMemoryError. By default, the PermGen size was limited, and if required, it could be increased using JVM options such as -XX:MaxPermSize.

Java 8 removed PermGen and introduced Metaspace to address these limitations. Unlike PermGen, Metaspace stores class metadata in native memory rather than in the JVM heap. By default, Metaspace automatically expands as needed (subject to the available native memory), eliminating the need to manually increase its size in most cases. If required, its maximum size can still be limited using the -XX:MaxMetaspaceSize JVM option.

PermGen and Metaspace difference

Thank you for visiting the blog.

Wednesday, 27 September 2023

Difference Between equals() Method and == Operator in Java

     In this post, we will discuss one of the most common Java interview questions: the difference between the equals() method and the == operator. We will also explore practical examples to understand when and how each should be used.

equals and == operator in java

The equals() method compares the contents (or logical equality) of two objects, whereas the == operator compares their object references to determine whether both references point to the same object in memory.

Let's look at a few examples to understand the difference between the equals() method and the == operator.

  • Created two string objects using new operator and applied equals and == operator to check the equality.
public class DemoClass {

     public static void main(String[] args) {

	  String s1 = new String("A");
	  String s2 = new String("A");

	  if (s1.equals(s2)) {
		System.out.println("s1 equals s2 are equal");
	  } else {
		System.out.println("s1 equals s2 are not equal");
	  }

	  if (s1 == s2) {
	       System.out.println("s1 == s2 are equal");
	  } else {
	       System.out.println("s1 == s2 are not equal");
	  }

      }
}

Output:- 
s1 equals s2 are equal
s1 == s2 are not equal

Used new operator to create String objects and those objects will store in heap memory of JVM and will create two different objects in the heap even the contents are same. So == operator result will return false.
  • Created two string objects using literal and applied equals and == operator to check the equality.
public class DemoClass {

     public static void main(String[] args) {

	  String s1 = "A";
	  String s2 = "A";

	  if (s1.equals(s2)) {
		System.out.println("s1 equals s2 are equal");
	  } else {
		System.out.println("s1 equals s2 are not equal");
	  }

	  if (s1 == s2) {
	       System.out.println("s1 == s2 are equal");
	  } else {
	       System.out.println("s1 == s2 are not equal");
	  }

      }
}

Output:-

s1 equals s2 are equal
s1 == s2 are equal

Thank you for visiting blog.

Thursday, 7 September 2023

Sort a List in Ascending and Descending Order Using the Java 8 Stream API

        In one of my previous posts, I covered several Java 8 Stream API coding questions and answers. In this post, we will discuss one of the most commonly asked coding interview questions: how to sort a list in ascending and descending order using the Java 8 Stream API.

1) Sort a List of Strings in Ascending Order Using the Java 8 Stream API

import java.util.Arrays;
import java.util.List;

public class SortExample {

    public static void main(String[] args) {

	 List<String> listOfStrings = Arrays.asList("A", "E", "B", "C");

         listOfStrings.stream().sorted().forEach(s -> System.out.println(s));
    }

}

Output:- A
              B
              C
              E

2) Sort a List of Strings in Descending Order Using the Java 8 Stream API

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

public class SortExample {

     public static void main(String[] args) {

	  List<String> listOfStrings = Arrays.asList("A", "E", "B", "C");

          listOfStrings.stream().sorted(Comparator.reverseOrder())
                                              .forEach(s -> System.out.println(s));
     }

}

Output:-   E
                C
                B
                A

3) Sort a List of Custom Java Objects (Employee Class) in Ascending or Descending Order Using the Java 8 Stream API

Employee.java,
public class Employee {
	
	private Long id;
	private String firstName;
	private String lastName;
	private String address;
      
        //constructor, setter and getter
       // and toString metghod
}

SortExample.java,
package com.main;

import java.util.ArrayList;
import java.util.List;

public class SortExample {

     public static void main(String[] args) {
		
	 Employee e1 = new Employee(1L, "Anil", "Nivargi", "XYZ");
	 Employee e2 = new Employee(2L, "Mahesh", "Nivargi", "XYZ");

	 List<Employee> employeeList = new ArrayList<>();
	 employeeList.add(e1);
	 employeeList.add(e2);
		
	  System.out.println("Sort a list in ascending order using firstName -");
		
	  //sort a list in ascending order using firstName
	  employeeList.stream().sorted((s1,s2) -> 
                        s1.getFirstName().compareTo(s2.getFirstName())).forEach(
                                 s -> System.out.println(s));
		
	  System.out.println("Sort a list in descending order using firstName -");
		
	    //sort a list in descending order using firstName
	  employeeList.stream().sorted((s1,s2) -> 
                        s2.getFirstName().compareTo(s1.getFirstName())).forEach(
                                 s -> System.out.println(s));

     }

}

Output:- 
Sort a list in ascending order using firstName -
Employee [id=1, firstName=Anil, lastName=Nivargi, address=XYZ]
Employee [id=2, firstName=Mahesh, lastName=Nivargi, address=XYZ]
Sort a list in descending order using firstName -
Employee [id=2, firstName=Mahesh, lastName=Nivargi, address=XYZ]
Employee [id=1, firstName=Anil, lastName=Nivargi, address=XYZ]

Thank you reading the blog post.

Reference Posts:-

Friday, 1 September 2023

Difference Between @Resource, @Autowired, and @Inject in Spring

         In this post, we will learn the differences between the @Resource, @Autowired, and @Inject annotations. All three annotations are used for dependency injection in Spring applications. The @Resource and @Inject annotations are part of the Java specification, whereas the @Autowired annotation is provided by the Spring Framework.

@Resource – It's defined in the javax.annotation package and it's part of java.

@Inject – It's defined in the javax.inject package and it's part of Java

@Autowired – It's defined in the package org.springframework.bean.factory and part of Spring framework.

          Internally @Inject and @Autowired annotations use the AutowiredAnnotationBeanPostProcessor to inject the dependencies. But @Resource annotation internally use CommonAnnotationBeanPostProcessor to inject the dependencies. Execution path/step is same for both Inject and Autowired annotations, Resource annotation execution paths also same but order of execution paths are not same.

  • @Inject and @Autowired
         1) Matches by Type
         2) Restricts by Qualifiers
         3) Matches by Name
  • @Resource
         1) Matches by Name
         2) Matched by Type
         3) Restricts by Qualifiers

Let's discuss the execution flow of each annotation with an example.

Notification.java,
public interface Notification {
    // some methods
}

Email.java,
import org.springframework.stereotype.Component;
@Component
public class Email implements Notification {
    // some methods
}

SMS.java,
import org.springframework.stereotype.Component;
@Component
public class SMS implements Notification {
    // some methods
}

Inject the above beans into the caller java class,

@Resource
@Qualifier("invalid")
private Notification email;
 
@Autowired
@Qualifier("invalid")
private Notification email;
 
@Inject
@Qualifier("invalid")
private Notification email;

When we execute the above code, the @Resource annotation works without any errors. However, the @Autowired and @Inject annotations fail and throw an exception, as shown below.

org.springframework.beans.factory.NoSuchBeanDefinitionException:
No matching bean of type [com.prj.basics.notification.Notification]

           The @Resource annotation performs dependency injection by matching the field name. In this example, it finds the bean named email and injects it successfully. However, the @Autowired and @Inject annotations resolve dependencies by type first and then use the qualifier (bean name) if one is specified. Since no bean named invalid exists, both annotations fail and throw an exception.

The following code works correctly for all three annotations without any errors.

@Resource
@Qualifier("email")
private Notification email;
 
@Autowired
@Qualifier("email")
private Notification email;
 
@Inject
@Qualifier("email")
private Notification email;

OR 

@Resource
private Email email;
 
@Autowired
private Email email;
 
@Inject
private Email email;

Thank you for visiting the blog.

Reference posts:-