Learn Java in one post (30 minutes) with code examples
In this article, we have covered all important ideas in Java Programming Language and presented each idea along with code examples. You have provided easy to follow implementations of standard Data Structures like Trie and Binary Tree to give you good hold on Implementing ideas.
This is a must read to revise Java in 30 minutes just before an examination or an Interview.
Table of contents:
- Hello World in Java
- Data types in Java
- Variables in Java
- OOP in Java
- Inheritance in Java
- Interface in Java
- Take Input in Java
- Node for Binary Tree in Java
- Binary Tree in Java using above node
- Trie class structure in Java
- Hash Map structure in Java
- Dynamic Array Structure in Java
- Linked List class Structure in Java
- Data Structures in Java Collections (java.util)
- Comparator for custom ordering in Java
- Throw vs Throws
- String vs StringBuffer vs StringBuilder
- Singleton class in Java
- Serializable & transient in Java
- Multiple threads in Java
- Fundamental ideas in Java
Let us get started with mastering Java Programming Language in one go.
Hello World in Java
This is the simpliest code in Java which creates a class named PrintWord and has the main() function which prints a single word that is "opengenus". You must write a simpler structure before writing a complete implementation of a problem.
// This code prints "opengenus".
public class PrintWord {
public static void main(final String[] args) {
System.out.println("opengenus");
}
}
Output:
opengenus
String[] args is an array of command line arguments and these are made final that is the values cannot be changed as this is a good practice and avoid runtime bugs. You can skip this as well and the program will run correctly.
Data types in Java
This code example creates 3 variables of Integer data type (which is a primitive data type in Java). We add the first two variables and store the result in the third variable.
// This code add two variables.
public class PrintWord {
public static void main(final String[] args) {
int A = 10;
int B = 21;
int C; // Default value of C is 0
C = A + B;
System.out.println(C);
}
}
Output:
31
Following are the primitive data types:
Primitive data type | Default value | Size |
---|---|---|
boolean | false | 1 byte |
char | '\u0000' | 2 byte |
byte | 0 | 1 byte |
short | 0 | 2 byte |
int | 0 | 4 byte |
long | 0L | 8 byte |
float | 0.0f | 4 byte |
double | 0.0d | 8 byte |
Note: boolean needs only 1 bit but is assigned 1 byte because 1 byte is the smallest amount of memory that can be allocated.
You can define user-defined data types when we learn how to implement custom class and use them as objects in Java.
Variables in Java
You know how to define and use variables from the previous code examples but there are three types:
- Static Variable: This is a variable that is common to the entire code. You can define head of a Linked List as a static variable as the head is needed to access it and can be used in all methods.
- Local variable: These are variables that are defined within a function and hence, can be used within the function only.
- Instance variable: These are variables that have been defined in main() function.
// This code prints "opengenus".
public class PrintWord {
// Static variable
static float check_variable1 = 1.02;
void function_check() {
// Local variable
double check_variable2 = 2.931271;
}
public static void main(final String[] args) {
// Instance variable
int check_variable3 = 2;
}
}
Note: static keyword is used when we want to keep one common copy across all instances of a class and different functions. Note main() is used with static as there is only one main().
Go through this article to understand scope of variables deeper.
OOP in Java
This section is based on Singly Linked List. We create two classes:
- An internal node
- A Singly Linked List using the above node.
This sample Java code will give you the complete idea of creating custom class, defining member variables, defining a constructor and creating objects of our class in main().
// Singly Linked List implementation in Java
// iq.opengenus.org
// Class for Internal Node
public class Node {
public int item;
public Node next;
}
// Class for Singly Linked List
public class SinglyLinkedList {
// Two private data members
private int size;
private Node head;
// Constructor of Linked List class
public SinglyLinkedList() {
this.size = 0;
this.head = null;
}
// Internal Function to insert Node in SinglyLinkedList
public void insertNode(int item) {
Node node = new Node();
node.item = item;
Node current = this.head;
if (this.head == null) {
this.head = node;
this.head.next = null;
this.size = 1;
System.out.println(this.head.toString());
} else {
while (current.next != null) {
current = current.next;
}
current.next = node;
node.next = null;
this.size += 1;
}
}
}
// Create a main class to use SinglyLinkedList class
public class Test_SinglyLinkedList {
public static void main(String[] args) {
// Create an object of
SinglyLinkedList list = new SinglyLinkedList();
list.insertNode("2");
list.insertNode("9");
}
}
Go through the above example carefully as it is the fundamental code you will need to implement other ideas and data structures like Binary Tree, Trie and others.
To have a good hold on OOP in Java, go through this article.
Inheritance in Java
In this example, we class B inherits class A. The object of class B will have access to member variables and functions in class A depending on access specifiers.
// A is base class
// B is child class
// B inherets A
Class A
{
public void methodA()
{
System.out.println("Base class method");
}
}
// B is inheriting A
Class B extends A
{
public void methodB()
{
System.out.println("Child class method");
}
public static void main(String args[])
{
B obj = new B();
obj.methodA(); //calling super class method
obj.methodB(); //calling local method
}
}
There are different types of Inheritance but not all types are permitted in Java. You can learn about types of Inheritance here.
For example, Multiple Inheritance is not permitted in Java but it can be implemented using Interface. You can learn about this technique here.
Interface in Java
We can inherit only one class but we can inherit multiple interface.
Interface is like a class but it has only function definitions. No function has a real code as Interface only provides the structure that needs to be followed and the actual code is the responsibility of the class using the interface.
This is an example of an Interface:
public interface ContacInfo{
//Abstract method declarations
void addAddress(Address address);// Passing object of type Address
void addEmail(String string);
void addPhoneNo(long phoneNo);
}
Go through this Student class which uses the above interface:
public class Student implements ContactInfo{
int rollNumber;
String name;
int age;
Address address;
String email;
long phoneNo;
public void addAddress(Address address)
{
this.address = address;
}
public void addEmail(String email){
this.email = email;
}
public void addPhoneNo(long phoneNo){
this.phoneNo = phoneNo;
}
}
To learn more about Interface in Java, go through this article.
Take Input in Java
Go through this Java code to understand how to take input using Scanner.
import java.util.Scanner;
public class Input {
public static void main(String[] args) {
// create a scancer object to take user input
Scanner in = new Scanner(System.in);
String userInput;
// nextLine(): complete line till \n
userInput = in.nextLine();
// next(): word till whitespace
userInput = in.next();
// nextInt(), nextDouble(): for numeric data
int data = in.nextInt();
int data = in.nextDouble();
// Check if there is input left
boolean check = in.hasNextInt();
boolean check = in.hasNextLine()
}
}
To get a complete list of Scanner methods, go through this list.
Node for Binary Tree in Java
// Binary Tree Node
// Part of iq.opengenus.org
public class BNode {
private int key;
private String name;
private BNode leftChild;
private BNode rightChild;
/**
* Constructors
* @param key
* @param name
*/
BNode(int key, String name) {
this.key = key;
this.name = name;
}
/**
* Getter
* @return Bnode
*/
public BNode getLeftChild() {
return leftChild;
}
/**
* Setter for the left child node
* @param pLeftChild
*/
public void setLeftChild(BNode pLeftChild) {
leftChild = pLeftChild;
}
/**
* Setter for the righ child node
* @param pRightChild
*/
public void setRightChild(BNode pRightChild) {
rightChild = pRightChild;
}
/**
* Getter
* @return BNode
*/
public BNode getRightChild() { return rightChild; }
/**
* Getter
* @return key
*/
public int getKey() {
return key;
}
/**
* setter
* @param data
*/
public void setKey(int data) {
key = data;
}
/**
* Getter
* @return name
*/
public String getName() {
return name;
}
/**
*
* @return
*/
public String toString() {
StringBuffer b = new StringBuffer();
b.append("[Key="); b.append(key);
if (leftChild == null) {
b.append(";leftChild=null");
} else {
b.append(";leftChild=" + leftChild.getKey());
}
if (rightChild== null) {
b.append(";rightChild=null");
} else {
b.append(";rightChild=" + rightChild.getKey());
}
b.append("]");
return b.toString();
}
}
Binary Tree in Java using above node
// Binary Tree implementation in Java
// Part of iq.opengenus.org
// Go through the comments carefully
// @something are annotations (metadata)
public class BinaryTree {
// BNode defined in previous section
// BNode can be included here alternatively
private BNode root;
private int numOfNodes = 0;
/**
* Constructor
*/
public BinaryTree() {
root = null;
}
/**
* increment the number of items in the tree
*/
public void inc() {
numOfNodes++;
}
/**
* decrement the number of items in the tree
*/
public void dec() {
numOfNodes--;
}
/** getter
*
* @return number of nodes in the tree
*/
public int getNumOfNodes() {
return numOfNodes;
}
public BNode getRoot() {
return root;
}
/**
* Add node traversing the tree until you find the right place for insertion.
* @param key
* @param name
*/
public void addNode(int key, String name) {
// Create a new Node and initialize it
BNode newNode = new BNode(key, name);
// If there is no root this becomes root
if (root == null) {
root = newNode;
inc();
} else {
// Set root as the Node we will start
// with as we traverse the tree
BNode focusNode = root;
// Future parent for our new Node
BNode parent;
while (true) {
// root is the top parent so we start
// there
parent = focusNode;
// Check if the new node should go on
// the left side of the parent node
if (key < focusNode.getKey()) {
// Switch focus to the left child
focusNode = focusNode.getLeftChild();
// If the left child has no children
if (focusNode == null) {
// then place the new node on the left of it
parent.setLeftChild(newNode);
inc();
return; // All Done
}
} else { // If we get here put the node on the right
focusNode = focusNode.getRightChild();
// If the right child has no children
if (focusNode == null) {
// then place the new node on the right of it
parent.setRightChild(newNode);
inc();
return; // All Done
}
}
}
}
}
/**
* Traverse in the inorder. This is the sorted order.
* 1. Go down the left's nodes' children recursively until no children
* 2. Print Node's key
* 3. Go down the right nodes' children recursively until no children
* Recursion is used to go to one node and
* then go to its child nodes and so forth
* @param focusNode, the root node sent to it
*/
public void inOrderTraverseTree(BNode focusNode) {
if (focusNode != null) {
// Traverse the left node's children recursively
inOrderTraverseTree(focusNode.getLeftChild());
// Visit the currently focused on node
System.out.println(focusNode);
// Traverse the right node
inOrderTraverseTree(focusNode.getRightChild());
}
}
/**
* Travere in the preorder
* @param focusNode
*/
public void preorderTraverseTree(BNode focusNode) {
if (focusNode != null) {
System.out.println(focusNode);
preorderTraverseTree(focusNode.getLeftChild());
preorderTraverseTree(focusNode.getRightChild());
}
}
/**
* traverse postorder
* @param focusNode
* @param focusNode
*/
public void postOrderTraverseTree(BNode focusNode) {
if (focusNode != null) {
postOrderTraverseTree(focusNode.getLeftChild());
postOrderTraverseTree(focusNode.getRightChild());
System.out.println(focusNode);
}
}
/**
* Find height
* @param root
* @return
*/
public int findHeight(BNode root) {
if (root == null) {
return -1;
} else
return Math.max(findHeight(root.getLeftChild()), findHeight(root.getRightChild())) + 1;
}
/**
* Find Mininum value in the tree
* @param root
* @return value or -1 if tree is empty
*/
public int findMinValue(BNode root) {
if (root == null) {
return -1;
} else if (root.getLeftChild() == null) {
return root.getKey();
} else {
return findMinValue(root.getLeftChild());
}
}
/**
* Find the Maximum value in the tree
* @param root
* @return
*/
public int findMaxValue(BNode root) {
if (root == null) {
return -1;
} else if (root.getRightChild() == null) {
return root.getKey();
} else {
return findMaxValue(root.getRightChild());
}
}
/**
* Find if the key exists in the tree
* @param key
* @return return Bnode if found otherwise null
*/
public BNode findNode(int key) {
// Start at the top of the tree
BNode focusNode = root;
// check if empty tree
if (root == null) {
return null;
}
// If Node is not found
// keep looking
while ( focusNode.getKey() != key) {
// If we should search to the left
if (key < focusNode.getKey()) {
// Shift the focus Node to the left child
focusNode = focusNode.getLeftChild();
} else {
// Shift the focus Node to the right child
focusNode = focusNode.getRightChild();
}
// node not found
if (focusNode == null)
return null;
}
return focusNode;
}
/**
* Delete a key
* @param key
* @return true if deleted, false otherwise
*/
public boolean remove(int key) {
// Start at the top of the tree
BNode focusNode = root;
BNode parent = root;
// special case if the tree is empty
if (focusNode == null) {
return false;
}
// When searching for a Node this will
// tell us whether to search to the
// right or left
boolean isItALeftChild = true;
// While we haven't found the Node
// keep looking
while (focusNode.getKey() != key) {
parent = focusNode;
// If we should search to the left
if (key < focusNode.getKey()) {
isItALeftChild = true;
// Shift the focus Node to the left child
focusNode = focusNode.getLeftChild();
} else {
// Greater than focus node so go to the right
isItALeftChild = false;
// Shift the focus Node to the right child
focusNode = focusNode.getRightChild();
}
// The node wasn't found
if (focusNode == null)
return false;
}
// If Node doesn't have children delete it
if (focusNode.getLeftChild() == null && focusNode.getRightChild() == null) {
// If root delete it
if (focusNode == root)
root = null;
// If it was marked as a left child
// of the parent delete it in its parent
else if (isItALeftChild)
parent.setLeftChild(null);
// Vice versa for the right child
else
parent.setRightChild(null);
}
// If no right child
else if (focusNode.getRightChild() == null) {
if (focusNode == root)
root = focusNode.getLeftChild();
// If focus Node was on the left of parent
// move the focus Nodes left child up to the
// parent node
else if (isItALeftChild)
parent.setLeftChild(focusNode.getLeftChild());
// Vice versa for the right child
else
parent.setRightChild(focusNode.getLeftChild());
}
// If no left child
else if (focusNode.getLeftChild() == null) {
if (focusNode == root)
root = focusNode.getRightChild();
// If focus Node was on the left of parent
// move the focus Nodes right child up to the
// parent node
else if (isItALeftChild)
parent.setLeftChild(focusNode.getRightChild());
// Vice versa for the left child
else
parent.setRightChild(focusNode.getRightChild());
}
// Two children so I need to find the targeted deleted nodes'
// replacement
else {
BNode replacement = getReplacementNode(focusNode);
// If the focusNode is root replace root
// with the replacement
if (focusNode == root)
root = replacement;
// If the deleted node was a left child
// make the replacement the left child
else if (isItALeftChild)
parent.setLeftChild(replacement);
// Vice versa if it was a right child
else
parent.setRightChild(replacement);
replacement.setLeftChild(focusNode.getLeftChild());
}
dec();
return true;
}
/**
* Find the replacement node. Used in delete function.
* @param replacedNode
* @return BNode or null;
*/
public BNode getReplacementNode(BNode replacedNode) {
BNode replacementParent = replacedNode;
BNode replacement = replacedNode;
BNode focusNode = replacedNode.getRightChild();
// While there are no more left children
while (focusNode != null) {
replacementParent = replacement;
replacement = focusNode;
focusNode = focusNode.getLeftChild();
}
// If the replacement isn't the right child
// move the replacement into the parent's
// leftChild slot and move the replaced nodes
// right child into the replacements rightChild
if (replacement != replacedNode.getRightChild()) {
replacementParent.setLeftChild(replacement.getRightChild());
replacement.setRightChild(replacedNode.getRightChild());
}
return replacement;
}
/**
* Given root of the tree or subtree, find its minimum.
* @param root
* @return
*/
public BNode findMin(BNode root)
{
BNode focusNode = root;
while (focusNode.getLeftChild() != null) {
focusNode = focusNode.getLeftChild();
}
return focusNode;
}
/**
* Recursive version of the deletion.
* @param root
* @param data
* @return the deleted node
*/
public BNode delete(BNode root, int data) {
if (root == null) {
return root;
} else if(data < root.getKey()) {
// traverse recursively the left side
root.setLeftChild(delete(root.getLeftChild(), data));
// travers recursively the right side
} else if (data > root.getKey()) {
root.setRightChild(delete(root.getRightChild(), data));
} else {
// Wohoo... I found you, Get ready to be deleted
// check the three cases
// Case 1: No child, the easy case
if(root.getLeftChild() == null && root.getRightChild() == null) {
root = null;
}
//Case 2: One child
else if(root.getLeftChild() == null) {
BNode temp = root;
root = root.getRightChild();
} else if(root.getRightChild() == null) {
BNode temp = root;
root = root.getLeftChild();
}
// case 3: 2 children
else {
BNode temp = findMin(root.getRightChild());
root.setKey(temp.getKey());
root.setRightChild(delete(root.getRightChild(), temp.getKey()));
}
}
return root;
}
/**
* Check if this tree an a binary tree
* @param root
* @return true or false
*/
boolean isBinarySearchTree(BNode root) {
int rootKey = root.getKey();
if (root == null) {
return true;
} else if (findMinValue(root.getLeftChild()) < rootKey && findMaxValue(root.getRightChild()) > rootKey) {
return true & isBinarySearchTree(root.getLeftChild()) & isBinarySearchTree(root.getRightChild());
} else return false;
}
/**
* Driver for the program
* @param args
*/
public static void main(String[] args) {
BinaryTree bTTree = new BinaryTree();
bTTree.addNode(4, Integer.toString(4));
}
}
Defining the class definition is important for various data structures. Once you have the correct definition, you can easily implement the functions you need.
Trie class structure in Java
Class structure of Trie in Java:
public class Trie {
private class TrieNode {
Map<Character, TrieNode> children;
boolean endOfWord;
public TrieNode() {
children = new HashMap<>();
endOfWord = false;
}
}
private final TrieNode root;
public Trie() {
root = new TrieNode();
}
// Sample insert method
public void insert(String word) {
TrieNode current = root;
for (int i = 0; i < word.length(); i++) {
char ch = word.charAt(i);
TrieNode node = current.children.get(ch);
if (node == null) {
node = new TrieNode();
current.children.put(ch, node);
}
current = node;
}
//mark the current nodes endOfWord as true
current.endOfWord = true;
}
}
Hash Map structure in Java
Class structure of Hash Map in Java:
package java.util;
import java.io.*;
public class HashMap<K,V>
extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable
{
static final int DEFAULT_INITIAL_CAPACITY = 16;
static final int MAXIMUM_CAPACITY = 1 << 30;
static final float DEFAULT_LOAD_FACTOR = 0.75f;
transient Entry[] table;
transient int size;
int threshold;
final float loadFactor;
public HashMap() {
this.loadFactor = DEFAULT_LOAD_FACTOR;
threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);
table = new Entry[DEFAULT_INITIAL_CAPACITY];
init();
}
}
Dynamic Array Structure in Java
Class structure of Dynamic Array in Java:
public class DynamicArray<E> implements Iterable<E>, RandomAccess {
private static final int INITIAL_CAPACITY = 10;
private int size;
private int capacity = INITIAL_CAPACITY;
private Object[] array;
public DynamicArray() {
array = new Object[INITIAL_CAPACITY];
}
}
Linked List class Structure in Java
Class structure of Linked List in Java:
public class LinkedList {
private class Node
{
private Node next;
private Object data;
public Node(Object dat)
{
data = dat;
}
public Object getData()
{
return data;
}
}
private int size;
private Node head;
public LinkedList() {
this.size = 0;
this.head = null;
}
}
Data Structures in Java Collections (java.util)
- HashMap
// Hash Map usage in Java
// Part of iq.opengenus.org
// Inherits AbstractMap; not syncronized; allow null key
// Interface: Map, Cloneable, Serializable
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.Iterator;
public class Test {
public static void main(String[] args) {
// initialize a HashMap
Map<String, Integer> map = new HashMap<String, Integer>();
// To make HashMap thread safe
Map<String, Integer> map = Collections.synchronizedMap(
new HashMap<String, Integer>());
// Add elements using put method
map.put("opengenus", 1);
// Remove using key
map.remove("opengenus");
map.containsKey("opengenus");
map.containsValue("1");
// get with key
map.get("opengenus");
map.size();
// Iterate the map using for-each loop
for (Map.Entry<String, Integer> e : map.entrySet()) {
System.out.println("Key: " + e.getKey() + " Value: " + e.getValue());
}
// Get a set of the entries
Set set = map.entrySet();
// Get an iterator
Iterator i = set.iterator();
// Display elements
while(i.hasNext()) {
Map.Entry me = (Map.Entry)i.next();
System.out.print(me.getKey() + ": ");
System.out.println(me.getValue());
}
}
}
Similar to HashMap
// LinkedHashMap
// Maintains order of iteration
LinkedHashMap<Integer, String> lhmap =
new LinkedHashMap<Integer, String>();
// HashTree
// Does not allow null tree
// only homogeneous keys; supports sorting
TreeMap<Integer, String> tmap =
new TreeMap<Integer, String>();
// Syncronized; slow; legacy; inherits dictionary
Hashtable<Integer,String> hm = new Hashtable<Integer,String>();
- ArrayList
// ArrayList usage in Java
// Part of iq.opengenus.org
// Iterable -> Collection -> List ->
// AbstractList (Interface) -> ArrayList
// No duplicate, maintains order, not synchronized
import java.util.*;
public class Test {
public static void main(String args[]) {
ArrayList<String> list = new ArrayList<String>();
// Add
list.add("opengenus");
// Remove
list.remove("element");
// Get i-th element
list.get(i-1);
//Printing the arraylist object
System.out.println(list);
// Sort
Collections.sort(list);
// Traverse
Iterator itr = list.iterator();
while(itr.hasNext()) {
System.out.println(itr.next());
}
}
}
- LinkedList
// ArrayList usage in Java
// Part of iq.opengenus.org
// Iterable -> Collection -> Queue -> Deque(interface) -> LinkedList
// Iterable -> Collection -> List(interface) -> AbstractSequentialL) -> LL
import java.util.*;
public class Test {
public static void main(String args[]) {
LinkedList<String> ll = new LinkedList<String>();
ll.add("opengenus");
ll.addFirst("open");
ll.addLast("opengenus");
ll.remove("open");
Iterator<String> itr = ll.iterator();
while(itr.hasNext()) {
System.out.println(itr.next());
}
}
}
- Stack
// Stack usage in Java
// Part of iq.opengenus.org
// Iterable -> Collection -> List ---> Vector -> Stack
import java.util.Iterator;
import java.util.Stack;
public class StackIterationExample1
{
public static void main (String[] args)
{
//creating an object of Stack class
Stack<String> stk = new Stack<String>();
//pushing elements into stack
stk.push("opengenus");
stk.pop();
stk.peek();
stk.search("opengenus");
stk.empty();
//iteration over the stack
Iterator iterator = stk.iterator();
while(iterator.hasNext())
{
Object values = iterator.next();
System.out.println(values);
}
}
}
- Stack
// Queue usage in Java
// Part of iq.opengenus.org
// Iterable -> Collection -> List ---> Vector -> Stack
import java.util.Iterator;
import java.util.Queue;
public class Test {
public static void main(String[] args) {
Queue<String> queue=new PriorityQueue<String>();
// add
queue.add("opengenus");
// remove
queue.remove();
// remove; null if empty
queue.poll();
// get
queue.peek();
//Traversing queue elements
for(String str: queue) {
System.out.println(str);
}
}
}
Types:
- PriorityQueue (add Comparable operator)
- BlockingQueue
- LinkedBlockingQueue
- ArrayBlockingQueue
- PriorityBlockingQueue
- DelayQueue
- SynchronousQueue
Comparator for custom ordering in Java
Priority Queue + Comparable Interface:
PriorityQueue<Student> pq = new
PriorityQueue<Student>(5, new StudentComparator());
class Student implements Comparator {
// For a custom class
public int compare(Student a, Student b)
{
return a.id - b.id;
}
}
// -1, 0, 1
class StudentComparator implements Comparator<Student> {
// Overriding compare() of Comparator
public int compare(Student s1, Student s2) {
if (s1.score < s2.score)
return 1;
else if (s1.score > s2.score)
return -1;
return 0;
}
}
Runnable is an interface that is to be implemented by a class whose objects should be executed by a thread.
class Consumer implements Runnable {
private final BlockingQueue queue;
}
- Deque
Implementation is similar to previous examples.
Types include:
- Deque
- ArrayDeque
- ConcurrentLinkedDeque
- LinkedBlockingDeque
- LinkedList
With this, you have the knowledge of different Java Collection data structure available. You can use these in your code quickly and are present in java.util package.
Throw vs Throws
- Throw is used within a function to raise an error
- Throws is used in function definition to suggest it may throw an error
public static void checkNum(int num) {
if (num < 1) {
throw new ArithmeticException("\nNumber is negative, cannot calculate square");
}
public static int divideNum(int m, int n) throws ArithmeticException {
int div = m / n;
return div;
}
String vs StringBuffer vs StringBuilder
This code summarizes the main points:
String str = new String("open");
// str is modified and new object is created
// more memory and time
str = str + "genus";
// StringBuilder: not threadsafe or synchronized
// but does not create a new object
StringBuilder str = new StringBuilder("open");
// StringBuffer: threadsafe and synchronized
// does not create a new object
StringBuffer str = new StringBuffer("Geeks");
s2.append("genus");
Singleton class in Java
Singleton class is a class whose object can be created only once and hence, only one object is used.
// Singleton class in Java
// Part of iq.opengenus.org
public final class ClassSingleton {
private static ClassSingleton INSTANCE;
private String info = "Initial info class";
private ClassSingleton() {
}
public synchronized static ClassSingleton getInstance() {
if(INSTANCE == null) {
INSTANCE = new ClassSingleton();
}
return INSTANCE;
}
}
Serializable & transient in Java
transient keyword is used to avoid converting an object to a stream of bytes during serialization.
public class Student implements Serializable {
String name;
transient int age;
}
To save the object, simply write it to a file:
Student student1 =new Student("OpenGenus");
FileOutputStream f = new FileOutputStream("sample.txt");
ObjectOutputStream out = new ObjectOutputStream(f);
out.writeObject(student1);
out.flush();
out.close();
f.close();
Multiple threads in Java
A class can support threads by extending the Thread class or by implementing the Runnable interface. In both cases, we need to override the run() method which is executed by the threads.
Following is a simple example with Runnable interface:
class Test implements Runnable {
public void run()
{
// add some code
}
}
class Test2 {
public static void main(String[] args)
{
// Number of threads
int n = 8;
for (int i = 0; i < n; i++) {
Thread object = new Thread(new Test());
object.start();
}
// Threads run in parallel
}
}
A test case should check if the code runs correctly using multiple threads.
Thread uses shared address space but different program count and stack memory. Process uses different address space.
Fundamental ideas in Java
To run a code file named "code.java", use the following commands:
javac code.java
java code
Garbage Collection in Java:
- Memory is divided into two major parts: Young (Eden, Survivor 1, Survivor 2) and Old generation
- There are different garbage collection algorithms (like Serial Garbage Collection, Parallel GC, New GC, Concurrent Mark and Sweep) used in Java for different use case. Learn More.
- There are techniques like Mark-copy and Mark-sweep-compact.
- GC is done is 3 phases: Minor, Major and Full.
We can call GC explicitly in code:
// Explicit call of the Garbage Collector
System.gc();
To exit the code, use:
System.exit(1);
Memory management in Java:
- A new variable is allocated space in Eden space.
- memory defrag process is used to avoid issues due to Fragmentation.
- Learn more about Memory model in Java
- class structure (runtime constants and static variables) and code for methods and constructors are stored in Permanent Generation Memory Space.
- Memory pools are created for immutable objects like String pools.
- Runtime constant pool (for run-time constants) is the part of the method area.
- Stack memory is used for execution of a thread.
The reference to an object determines when the object will be removed in Garbage Collection. Types of references in Java:
// Creates a strong reference
Object obj = new Object();
// New Soft Reference to obj object
import java.lang.ref.*
SofReference<Object> softRef = new SoftReference<Object>(obj);
// New Weak Reference to obj object
WeakReference<Object> softRef = new WeakReference<Object>(obj);
// Returns the object reference if it remains in memory,
// otherwise returns null
obj = softRef.get();
// Creating a reference queue
ReferenceQueue<obj> refQueue = new ReferenceQueue<obj>();
// New Phantom Reference to obj object in a queue
PhantomReference<Object> phantomRef = new PhantomReference<Object>(obj, refQueue);
With this, you have a strong idea of implementing any Data Structure in Java along with core design ideas. Best of luck with your Test or Coding Interview.