Wednesday, May 20, 2020

Record type in Java

JDK 14, released in March 2020, introduced records (preview language feature) which provide a compact syntax for declaring classes whose main purpose is to hold data. In records, all low-level, repetitive and error-prone code is like constructors, accessor and utlity methods such as equals(), hashCode(), toString() are automatically derived based on the record’s state description.

What will we build?


Oracle Java Tutorial and Material, Oracle Java Certification, Oracle Java Exam Prep

Record declaration


Record has a name and state description. The state description declares the components of the record and optionaly a body:

record Owner(String name, String address, String city, String telephone) {}
record PetType(String name) {}
record Pet(LocalDate birthDate, PetType type, Owner owner) {}

The representation of a record is derived mechanically and completely from the state description with the following members:

◉ a private final field for each component
◉ a public read accessor method for each component, with the same name and type as the component (e.g. owner.name(), owner.address())
◉ a public constructor
◉ an implementations of equals() and hashCode()
◉ an implementation of toString().

The basic behavior is demonstrated with the below test:

class Java14RecordTests {
    @Test
    void recordAccessors() {
        var owner = new Owner("John Doe", "110 W. Liberty St.", "Madison", "6085551023");
        assertThat(owner.name()).isEqualTo("John Doe");
        assertThat(owner.address()).isEqualTo("110 W. Liberty St.");
        assertThat(owner.city()).isEqualTo("Madison");
        assertThat(owner.telephone()).isEqualTo("6085551023");
    }
    @Test
    void recordEqualsAndHashCode() {
        var pet1 = new Pet(
                LocalDate.of(2019, 1, 1), 
                new PetType("dog"), 
                new Owner("John Doe", null, null, null)
        );
        var pet2 = new Pet(
                LocalDate.of(2019, 1, 1), 
                new PetType("dog"), 
                new Owner("John Doe", null, null, null)
        );
        assertThat(pet1).isEqualTo(pet2);
        assertThat(pet1.hashCode()).isEqualTo(pet2.hashCode());
    }
    @Test
    void recordToString() {
        var pet = new PetType("dog");
        assertThat(pet.toString()).isEqualTo("PetType[name=dog]");
    }
}

Restrictions


Oracle Java Tutorial and Material, Oracle Java Certification, Oracle Java Exam Prep
Record is a restricted form of class and the restrictions are:

◉ Record cannot extend any other class
◉ Any other fields which are declared must be static
◉ The components of a record are implicitly final

Additional behavior


Apart from the above restrictions, record behave like regular class and:

◉ Record may declare instance and static methods, static fields, static initializers:

record Owner(String name, String address, String city, String telephone) {
    /* Static initializer */
    static {
        NONE = "N/A";
    }
    /* Static fields are allowed, both private and public */
    private static String NONE;
    /* Records may have static methods */
    public static Owner anOwner(String name) {
        return new Owner(name, NONE, NONE, NONE);
    }
}

◉ Record may declare constructors and also compact constructors. The compact constructor has access to the record’s components:

record Pet(LocalDate birthDate, PetType type, Owner owner) {
    /* `Compact` constructor */
    public Pet {
        requiresNotNull("birthDate", birthDate);
        requiresNotNull("type", type);
        requiresNotNull("owner", owner);
    }
     
    public Pet(LocalDate birthDate, PetType type) {
        this(birthDate, type, null);
    }
    /* Records may have instance methods */
    private void requiresNotNull(String name, Object obj) {
        if (Objects.isNull(obj)) {
            throw new IllegalArgumentException(name + " can't be null");
        }
    }
}

◉ Record can override all standard methods: equals(), hashCode(), toString()
◉ Record can implement interfaces
◉ Record can be annotated

… and more.

Friday, May 15, 2020

How to convert Array to List in Java

In this post, we will learn, various ways in which we can convert an array to a List.

Oracle Java Cert Exam, Oracle Java Tutorial and Material, Oracle Java Guides, Oracle Java Learning

package com.blogspot.oraclejavacertified;

import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class ArrayToList {

    public static void main(String[] args) {

        //Before Java 8
        System.out.println("Before JAVA 8........................................");

        // 1.
        String[] names = new String[] {"Gaurav", "Sachin", "Yuvraj"};
        List<String> nameList =  Arrays.asList(names);
        System.out.println("using Arrays.asList: " + nameList);

        //2
        List<Integer> list = Arrays.asList(1, 2, 3);
        System.out.println("Inline primitive array to Integer List using Arrays.asList(): "
                + list);

        //Java 8
        System.out.println("JAVA 8 ................................................");
        // 3. primitive array
        int intArray[] = {1, 2, 3};
        List<Integer> integerList1 = Arrays.stream(intArray).boxed()
                                                         .collect(Collectors.toList());
        System.out.println("Primitive int array to Integer List using Array.stream(): "
                + integerList1);

        // 4. primitive array with IntStream
        List<Integer> integerList2 = IntStream.of(intArray).boxed()
                                                          .collect(Collectors.toList());
        System.out.println("Primitive int array to Integer List using IntStream.of(): "
                + integerList2);

        // 5. Object type array to Integer List
        Integer integerArray[] = {1, 2, 3};
        List<Integer> integerList3 = Arrays.stream(integerArray)
                                                           .collect(Collectors.toList());
        System.out.println("Object type array to Integer List using Arrays.stream:  "
                + integerList3);

        // 6. Integer Array to ArrayList
        ArrayList<Integer> arrayList = Arrays.stream(integerArray)
                .collect(Collectors.toCollection(ArrayList::new));
        System.out.println("Integer type array to Integer ArrayList using Arrays.stream:  "
                + arrayList);

        // 7. Integer Array to LinkedList
        LinkedList<Integer> linkedList = Stream.of(integerArray)
                                           .collect(Collectors.toCollection(LinkedList::new));
        System.out.println("Integer type array to Integer LinkedList using Arrays.stream:  "
                + linkedList);

        // 8. Integer Array to Immutable List
        List<Integer> immutableList = Collections.unmodifiableList(Arrays.asList(integerArray));
        System.out.println("Integer type array to Immutable List using Arrays.stream:  "
                + immutableList);

        //9. JAVA 9
        System.out.println("JAVA 9.........................................................");
        String[] playerNames = {"Sachin", "Dhoni", "Yuvraj"};
        List<String> players = List.of(playerNames);
        System.out.println("Array to List using Java 9 List.of() :" + players);

        //10. JAVA 10
        System.out.println("JAVA 10.........................................................");
        List<Integer> integerList = List.copyOf(Arrays.asList(integerArray));
        System.out.println("Array to List using Java 10 List.copyOf() :" + integerList);

        //11. Apache Commons
        System.out.println("Apache Commons...................................................");
        List<Integer> targetList = new ArrayList<>(6);
        CollectionUtils.addAll(targetList, integerArray);
        System.out.println("Array to List using Apache Common CollectionUtils.addAll() :"
                + integerList);

        //12 Google Guava
        System.out.println("Google Guava......................................................");
        Integer[] sourceArray = {1, 2, 3};
        List<Integer> targetList1 = Lists.newArrayList(sourceArray);
        System.out.println("Array to List using Google Guava Lists.newArrayList:"
                + integerList);
    }
}

External Dependency Used :

<dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-collections4</artifactId
      <version>4.4</version>
 </dependency>
 <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-lang3</artifactId>
      <version>3.10</version>
 </dependency>
 <dependency>
      <groupId>com.google.guava</groupId>
      <artifactId>guava</artifactId>
      <version>16.0.1</version>
 </dependency>

Wednesday, May 13, 2020

Java Reflection API

Oracle Java Tutorial and Material, Oracle Java Certification, Oracle Exam Prep

Java Reflection is a process of examining or modifying the run time behavior of a class at run time.

The java.lang.Class class provides many methods that can be used to get metadata, examine and change the run time behavior of a class.

The java.lang and java.lang.reflect packages provide classes for java reflection.

Where it is used

The Reflection API is mainly used in:

◈ IDE (Integrated Development Environment) e.g. Eclipse, MyEclipse, NetBeans etc.
◈ Debugger
◈ Test Tools etc.

java.lang.Class class

The java.lang.Class class performs mainly two tasks:

◈ provides methods to get the metadata of a class at run time.
◈ provides methods to examine and change the run time behavior of a class.

Commonly used methods of Class class:


Method Description 
1) public String getName()  returns the class name
2) public static Class forName(String className)throws ClassNotFoundException  loads the class and returns the reference of Class class. 
3) public Object newInstance()throws InstantiationException,IllegalAccessException  creates new instance. 
4) public boolean isInterface()  checks if it is interface. 
5) public boolean isArray()  checks if it is array. 
6) public boolean isPrimitive()  checks if it is primitive. 
7) public Class getSuperclass()  returns the superclass class reference. 
8) public Field[] getDeclaredFields()throws SecurityException  returns the total number of fields of this class. 
9) public Method[] getDeclaredMethods()throws SecurityException  returns the total number of methods of this class. 
10) public Constructor[] getDeclaredConstructors()throws SecurityException  returns the total number of constructors of this class.
11) public Method getDeclaredMethod(String name,Class[] parameterTypes)throws NoSuchMethodException,SecurityException  returns the method class instance. 

How to get the object of Class class?


There are 3 ways to get the instance of Class class. They are as follows:

◉ forName() method of Class class
◉ getClass() method of Object class
◉ the .class syntax

1) forName() method of Class class


◉ is used to load the class dynamically.
◉ returns the instance of Class class.
◉ It should be used if you know the fully qualified name of class.This cannot be used for primitive types.

Let's see the simple example of forName() method.

class Simple{}  
  
class Test{  
 public static void main(String args[]){  
  Class c=Class.forName("Simple");  
  System.out.println(c.getName());  
 }  
}  

Simple

2) getClass() method of Object class


It returns the instance of Class class. It should be used if you know the type. Moreover, it can be used with primitives.

class Simple{}  
  
class Test{  
  void printName(Object obj){  
  Class c=obj.getClass();    
  System.out.println(c.getName());  
  }  
  public static void main(String args[]){  
   Simple s=new Simple();  
   
   Test t=new Test();  
   t.printName(s);  
 }  
}  
   
Simple

3) The .class syntax


If a type is available but there is no instance then it is possible to obtain a Class by appending ".class" to the name of the type.It can be used for primitive data type also.

class Test{  
  public static void main(String args[]){  
   Class c = boolean.class;   
   System.out.println(c.getName());  
  
   Class c2 = Test.class;   
   System.out.println(c2.getName());  
 }  
}

boolean
Test


Determining the class object


Following methods of Class class is used to determine the class object:

1) public boolean isInterface(): determines if the specified Class object represents an interface type.
2) public boolean isArray(): determines if this Class object represents an array class.
3) public boolean isPrimitive(): determines if the specified Class object represents a primitive type.

Let's see the simple example of reflection api to determine the object type.

class Simple{}  
interface My{}  
  
class Test{  
 public static void main(String args[]){  
  try{  
   Class c=Class.forName("Simple");  
   System.out.println(c.isInterface());  
     
   Class c2=Class.forName("My");  
   System.out.println(c2.isInterface());  
    
  }catch(Exception e){System.out.println(e);}  
  
 }  
}

false
true

Tuesday, May 12, 2020

How to convert a Map to List in Java 8

Oracle Java Tutorial and Material, Oracle Java Certification, Oracle Java Exam Prep, Oracle Java 8

When you convert a Map to List in Java 8 or before, you have three choices, like you can get a list of keys from Map, List of values from Map, or a List of entries from Map, which encapsulates both key and value. The API doesn't provide these methods because Map doesn't guarantee any order and List interface guarantee ordering, i.e. insertion order. Hence, JDK API provides an equivalent method to convert a Map to Set, like keySet() will return a set of keys and entrySet() will return a set of entries. Since Set cannot have duplicates and Map also cannot have duplicate keys, the Set data structure seems to perfect for returning keys and entries.

But, values can be duplicated in Map; hence API provides values() method which returns Collection. Before Java 8, the problem of converting a Map to List is actually a problem of converting Map to Set and then to List, which is also not different in Java 8. Still, because of Streams and lambda expression, it seems you are doing everything in one step.

1. Map to List of keys


Here is a one-liner to convert a Map of Integer and String, where Integer is key, and String is the type of value, to a List of Integer, i.e. list of keys:

idToName.keySet().stream().collect(Collectors.toList());

In this code, we first get the set of keys by calling the keySet() method and them a stream of keys by calling stream() method. After that, you just need to convert the Stream to List, which we have done using Collectors.toList() method, as shown in the earlier example.

Just keep in mind that toList() can return any kind of List implementation, like ArrayList or LinkedList or even Vector, it's up to the implementation. If you want a particular implementation, like ArrayList, you can use another method called toCollection(), which accepts a Supplier to denote the implementation class.

For example, you can convert a Map to ArrayList of keys by using the following snippet:

idToName.keySet()
        .stream()
        .collect(Collectors.toCollection(ArrayList::new));

or, you can use the below code to convert a Map to LinkedList in Java.

idToName.keySet()
        .stream()
        .collect(Collectors.toCollection(LinkedList::new))

Oracle Java Tutorial and Material, Oracle Java Certification, Oracle Java Exam Prep, Oracle Java 8

2. Map to List to Values


Here is the one line of code to create a list of values from Map:

idToName.values()
        .stream()
        .collect(Collectors.toCollection(ArrayList::new))

The only difference is that this list may contain duplicates because values can be repeated in a Map.

3. Map to List of entries


Here is the one line of code to create a list of values from Map:

idToName.entrySet()
        .stream()
        .collect(Collectors.toCollection(ArrayList::new))

This list will contain all the entries from the Map.

4. Map of Entries to List of Objects


Now, you have a situation where you need to create an object by using key and value from Map, e.g. a Pair object which contains both key and values. Though you can easily use Map.Entry if you want both key and value as shown in the previous example, the new object teach you an essential technique of mapping Stream elements to other object using map() method.

idToName.entrySet()
        .stream()
                    .map( e -> Pair::new)
        .collect(Collectors.toCollection(ArrayList::new))

Important points


1) The keySet() method returns a Set of keys; you need this method because stream() is not available in java.util.Map class.

2) The entrySet() method return a Set of Map.Entry object which contains both key and value.

3) The values() method returns a Collection of values because the value can be duplicate as opposed to Set. See the difference between keySet, values, and entrySet to learn more.

4) The toList() method of Collector returns a List without any guarantees on the type, thread-safety, mutability, and serializability. It can return elements of String in an ArrayList or LinkedList or any custom implementation.

5) If you want to accumulate Stream elements into ArrayList, then you must use toCollection() method and pass ArrayList::new. This will then return an ArrayList of keys. You can use this technique to convert Map to any type of List in Java.

That's all about how to convert a Map to a List in Java 8. You have learned how to convert a Map to the ArrayList and LinkedList. You have also learned how to create a List of Keys and List of values, along with a list of entries from Map object. If you want to learn more about essential Java 8 concepts, you can check the following resources.

Monday, May 11, 2020

JDBC Driver

JDBC Driver is a software component that enables java application to interact with the database. There are 4 types of JDBC drivers:

1. JDBC-ODBC bridge driver
2. Native-API driver (partially java driver)
3. Network Protocol driver (fully java driver)
4. Thin driver (fully java driver)

1) JDBC-ODBC bridge driver


The JDBC-ODBC bridge driver uses ODBC driver to connect to the database. The JDBC-ODBC bridge driver converts JDBC method calls into the ODBC function calls. This is now discouraged because of thin driver.

JDBC Driver, Oracle Java Guides, Oracle Java Learning, Oracle Java Tutorial and Materials, Java Exam Prep

Oracle does not support the JDBC-ODBC Bridge from Java 8. Oracle recommends that you use JDBC drivers provided by the vendor of your database instead of the JDBC-ODBC Bridge.

Advantages:

◉ easy to use.
◉ can be easily connected to any database.

Disadvantages:

◉ Performance degraded because JDBC method call is converted into the ODBC function calls.
◉ The ODBC driver needs to be installed on the client machine.

2) Native-API driver


The Native API driver uses the client-side libraries of the database. The driver converts JDBC method calls into native calls of the database API. It is not written entirely in java.

JDBC Driver, Oracle Java Guides, Oracle Java Learning, Oracle Java Tutorial and Materials, Java Exam Prep

Advantage:

◉ performance upgraded than JDBC-ODBC bridge driver.

Disadvantage:

◉ The Native driver needs to be installed on the each client machine.
◉ The Vendor client library needs to be installed on client machine.

3) Network Protocol driver


The Network Protocol driver uses middleware (application server) that converts JDBC calls directly or indirectly into the vendor-specific database protocol. It is fully written in java.

JDBC Driver, Oracle Java Guides, Oracle Java Learning, Oracle Java Tutorial and Materials, Java Exam Prep

Advantage:

◉ No client side library is required because of application server that can perform many tasks like auditing, load balancing, logging etc.

Disadvantages:

◉ Network support is required on client machine.
◉ Requires database-specific coding to be done in the middle tier.
◉ Maintenance of Network Protocol driver becomes costly because it requires database-specific coding to be done in the middle tier.

4) Thin driver


The thin driver converts JDBC calls directly into the vendor-specific database protocol. That is why it is known as thin driver. It is fully written in Java language.

JDBC Driver, Oracle Java Guides, Oracle Java Learning, Oracle Java Tutorial and Materials, Java Exam Prep

Advantage:

◉ Better performance than all other drivers.
◉ No software is required at client side or server side.

Disadvantage:

Drivers depend on the Database.

Friday, May 8, 2020

Java JDBC

Oracle Java Tutorial and and Material, Oracle Java Learning, Oracle Java JDBC, Oracle Java Exam Prep

JDBC stands for Java Database Connectivity. JDBC is a Java API to connect and execute the query with the database. It is a part of JavaSE (Java Standard Edition). JDBC API uses JDBC drivers to connect with the database. There are four types of JDBC drivers:

◉ JDBC-ODBC Bridge Driver,
◉ Native Driver,
◉ Network Protocol Driver, and
◉ Thin Driver

We have discussed the above four drivers in the next chapter.

We can use JDBC API to access tabular data stored in any relational database. By the help of JDBC API, we can save, update, delete and fetch data from the database. It is like Open Database Connectivity (ODBC) provided by Microsoft.

Oracle Java Tutorial and and Material, Oracle Java Learning, Oracle Java JDBC, Oracle Java Exam Prep

The current version of JDBC is 4.3. It is the stable release since 21st September, 2017. It is based on the X/Open SQL Call Level Interface. The java.sql package contains classes and interfaces for JDBC API. A list of popular interfaces of JDBC API are given below:

◉ Driver interface
◉ Connection interface
◉ Statement interface
◉ PreparedStatement interface
◉ CallableStatement interface
◉ ResultSet interface
◉ ResultSetMetaData interface
◉ DatabaseMetaData interface
◉ RowSet interface

A list of popular classes of JDBC API are given below:

◉ DriverManager class
◉ Blob class
◉ Clob class
◉ Types class

Why Should We Use JDBC


Before JDBC, ODBC API was the database API to connect and execute the query with the database. But, ODBC API uses ODBC driver which is written in C language (i.e. platform dependent and unsecured). That is why Java has defined its own API (JDBC API) that uses JDBC drivers (written in Java language).

We can use JDBC API to handle database using Java program and can perform the following activities:

1. Connect to the database
2. Execute queries and update statements to the database
3. Retrieve the result received from the database.