0% found this document useful (0 votes)
2 views

Java English Medium Book - 2

The document provides an introduction to the basic structure of a Java program, including how to write a simple 'Hello, World!' program and the use of comments for code clarity. It covers Java variables, literals, data types, and operators, emphasizing the importance of syntax and the rules that govern variable declaration and usage. Additionally, it explains the different types of comments in Java and their role in debugging and code collaboration.

Uploaded by

rubiyafaq
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views

Java English Medium Book - 2

The document provides an introduction to the basic structure of a Java program, including how to write a simple 'Hello, World!' program and the use of comments for code clarity. It covers Java variables, literals, data types, and operators, emphasizing the importance of syntax and the rules that govern variable declaration and usage. Additionally, it explains the different types of comments in Java and their role in debugging and code collaboration.

Uploaded by

rubiyafaq
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 222

COMPLETE JAVA

Basic Structure of a Java Program


Java Introduction As we have seen from the last example, a Java
program requires a lot of lines even for a simple
program.
For now, just remember every Java program we write
Your First Java Program will follow this structure.
In the previous tutorial you learned how to install class Main {
Java on your computer. Now, let's write a simple Java public static void main(String[] args) {
program. ...
The following program displays Hello, World! on the }
screen. }
We will write our code in place of ... inside curly
public class Main { braces.
public static void main(String[] args) {
System.out.println("Hello, World!");
Java Comments
In the previous tutorial, you learned to write your
}
first Java program. Now, let's learn about Java
}
comments.
Output
Tip: We are introducing comments early in this
Hello World!
tutorial series because, from now on, we will be using
Note: A Hello World! program includes the basic them to explain our code.
syntax of a programming language and helps
beginners understand the structure before getting Comments are hints that we add to our code, making
started. That's why it is a common practice to it easier to read and understand.
introduce a new language using a Hello Comments are completely ignored by Java compilers.
World! program. For example,
It's okay if you don’t understand how the program class HelloWorld {
works right now. We will learn about it in upcoming public static void main(String[] args) {
tutorials. For now, just write the exact program and // print Hello World to the screen
run it. System.out.println("Hello World");
}
}
Working of Java Program
Congratulations on writing your first Java program. Output
Now, let's see how the program works. Hello World
public class Main { Here, // print Hello World to the screen is a
comment in Java programming. The Java compiler
public static void main(String[] args) { ignores everything after the // symbol.
System.out.println("Hello, World!");
} Note: You can ignore the programming concepts and
} simply focus on the comments. We will revisit these
concepts in later tutorials.
Notice the following line of code:
System.out.println("Hello, World!"); Single-line Comment
In the above code, the System.out.println() In Java, a single-line comment starts and ends in the
statement prints the text Hello, World! to the same line. To write a single-line comment, we can use
screen. the // symbol. For example,

Remember these important things about printf: // declare and initialize two variables
 Everything you want to print should be kept inside int a = 1;
parentheses (). int b = 3;
 The text to be printed is enclosed within double
// print the output
quotes "".
System.out.println("This is output");
 Each System.out.println() statement ends with a
semicolon ;. Here, we have used two single-line comments:
Not following the above rules will result in errors and  // declare and initialize two variables
your code will not run successfully.
 // print the output
The Java compiler ignores everything from // to the  Comments make our code readable for future
end of line. Hence, it is also known as End of reference.
Line comment.  Comments are used for debugging purposes.
 We can use comments for code collaboration as it
Multi-line Comment helps peer developers to understand our code.
When we want to write comments in multiple lines,
we can use the multi-line comment. To write multi- Note: Comments are not and should not be used as a
line comments, we can use the /*....*/ symbol. For substitute to explain poorly written code. Always try
example, to write clean, understandable code, and then use
comments as an addition.
/* This is an example of multi-line comment. In most cases, always use comments to explain 'why'
* The program prints "Hello, World!" to the rather than 'how' and you are good to go.
standard output.
*/

class HelloWorld {
Java Fundamentals
public static void main(String[] args) {
Java Variables and Literals
System.out.println("Hello, World!"); In the previous tutorial you learnt about Java
} comments. Now, let's learn about variables and literals
} in Java.

Output: Java Variables


Hello, World! A variable is a location in memory (storage area) to
Here, we have used the multi-line comment: hold data.
/* This is an example of multi-line comment. To indicate the storage area, each variable should be
* The program prints "Hello, World!" to the given a unique name (identifier). Learn more
standard output. about Java identifiers.
*/
This type of comment is also known as Traditional Create Variables in Java
Comment. In this type of comment, the Java Here's how we create a variable in Java,
compiler ignores everything from /* to */. int speedLimit = 80;
Here, speedLimit is a variable of int data type and we
Prevent Executing Code Using Comments have assigned value 80 to it.
While debugging there might be situations where we The int data type suggests that the variable can only
don't want some part of the code. For example, hold integers.
public class Main { In the example, we have assigned value to the variable
public static void main(String[] args) { during declaration. However, it's not mandatory.
System.out.println("some code"); You can declare variables and assign variables
System.out.println("error code"); separately. For example,
System.out.println("some other code"); int speedLimit;
speedLimit = 80;
}
}
Note: Java is a statically-typed language. It means that
If we get an error while running the program, all variables must be declared before they can be used.
instead of removing the error-prone code, we can
use comments to disable it from being executed; this
can be a valuable debugging tool. Change values of variables
The value of a variable can be changed in the
public class Main { program, hence the name variable. For example,
public static void main(String[] args) { int speedLimit = 80;
System.out.println("some code"); ... .. ...
// System.out.println("error code"); speedLimit = 90;
System.out.println("some other code");
Here, initially, the value of speedLimit is 80. Later,
} we changed it to 90.
} However, we cannot change the data type of a variable
in Java within the same scope.
Why use Comments?
We should use comments for the following reasons: What is the variable scope?
Don't worry about it for now. Just remember that we range = 124;
can't do something like this: System.out.println(range); // prints 124
int speedLimit = 80; }
... .. ... }
float speedLimit;
3. short type
Java literals  The short data type in Java can have values from -
Literals are data used for representing fixed values. 32768 to 32767 (16-bit signed two's complement
They can be used directly in the code. For example, integer).
int a = 1;  If it's certain that the value of a variable will be within
float b = 2.5; -32768 and 32767, then it is used instead of other
char c = 'F'; integer data types ( int , long ).
 Default value: 0
Here, 1 , 2.5 , and 'F' are literals. Example 3: Java short data type
class Main {
Java Data Types (Primitive) public static void main(String[] args) {
Java Data Types
As the name suggests, data types specify the type of short temperature;
data that can be stored inside variables in Java. temperature = -200;
Java is a statically-typed language. This means that all System.out.println(temperature); // prints -200
variables must be declared before they can be used. }
int speed; }
Here, speed is a variable, and the data type of the
variable is int. 4. int type
 The int data type can have values from -231 to 231-
The int data type determines that the speed variable 1 (32-bit signed two's complement integer).
can only contain integers.  If you are using Java 8 or later, you can use an
There are 8 data types predefined in Java, known as unsigned 32-bit integer. This will have a minimum
primitive data types. value of 0 and a maximum value of 232-1.

Note: In addition to primitive data types, there are  Default value: 0
also referenced types (object type).
Example 4: Java int data type
class Main {
8 Primitive Data Types public static void main(String[] args) {
1. boolean type
 The boolean data type has two possible values, int range = -4250000;
System.out.println(range); // print -4250000
either true or false .
}
 Default value: false . }
 They are usually used for true/false conditions.
Example 1: Java boolean data type 5. long type
class Main {  The long data type can have values from -263 to 263-
public static void main(String[] args) { 1 (64-bit signed two's complement integer).
 If you are using Java 8 or later, you can use an
boolean flag = true; unsigned 64-bit integer with a minimum value
System.out.println(flag); // prints true
of 0 and a maximum value of 264-1.
}  Default value: 0
}
Example 5: Java long data type
2. byte type
class LongExample {
 The byte data type can have values from - public static void main(String[] args) {
128 to 127 (8-bit signed two's complement integer).
 If it's certain that the value of a variable will be within long range = -42332200000L;
-128 to 127, then it is used instead of int to save System.out.println(range); // prints -42332200000
memory. }
 Default value: 0 }
Notice, the use of L at the end of -42332200000 . This
Example 2: Java byte data type
represents that it's an integer of the long type.
class Main {
public static void main(String[] args) {

byte range;
6. double type char letter1 = '9';
 The double data type is a double-precision 64-bit System.out.println(letter1); // prints 9
floating-point.
 It should never be used for precise values such as char letter2 = 65;
currency. System.out.println(letter2); // prints A
 Default value: 0.0 (0.0d)
}
Example 6: Java double data type }
class Main {
public static void main(String[] args) { Here, we have assigned 9 as a character (specified by
single quotes) to the letter1 variable. However,
double number = -42.3; the letter2 variable is assigned 65 as an integer
System.out.println(number); // prints -42.3 number (no single quotes).
}
Hence, A is printed to the output. It is because Java
}
treats characters as an integer and the ASCII value
7. float type of A is 65.
 The float data type is a single-precision 32-bit floating-
point. Learn more about single-precision and double-
precision floating-point if you are interested. String type
 It should never be used for precise values such as Java also provides support for character strings
currency. via java.lang.String class. Strings in Java are not
 Default value: 0.0 (0.0f) primitive types. Instead, they are objects. For example,
String myString = "Java Programming";
Example 7: Java float data type Here, myString is an object of the String class.
class Main {
public static void main(String[] args) { Java Operators
Operators are symbols that perform operations on
float number = -42.3f; variables and values. For example, + is an operator
System.out.println(number); // prints -42.3
used for addition, while * is also an operator used for
}
} multiplication.
Operators in Java can be classified into 5 types:
1. Arithmetic Operators
Notice that we have used -42.3f instead of -42.3 in the
2. Assignment Operators
above program. It's because -42.3 is a double literal. 3. Relational Operators
To tell the compiler to treat -42.3 as float rather 4. Logical Operators
than double , you need to use f or F . 5. Unary Operators
6. Bitwise Operators

8. char type
 It's a 16-bit Unicode character. 1. Java Arithmetic Operators
 The minimum value of the char data type Arithmetic operators are used to perform arithmetic
operations on variables and data. For example,
is '\u0000' (0) and the maximum value of the
a+b;
is '\uffff' . Here, the + operator is used to add two
 Default value: '\u0000' variables a and b . Similarly, there are various other
arithmetic operators in Java.
Example 8: Java char data type
class Main { Operator Operation
public static void main(String[] args) {
+ Addition
- Subtraction
char letter = '\u0051';
* Multiplication
System.out.println(letter); // prints Q
} / Division
} % Modulo Operation (Remainder
after division)
Here, the Unicode value of Q is \u0051. Hence, we
Example 1: Arithmetic Operators
get Q as the output. class Main {
Here is another example: public static void main(String[] args) {
class Main {
public static void main(String[] args) { // declare variables
int a = 12, b = 5;
+= a += b; a = a + b;
// addition operator -= a -= b; a = a - b;
System.out.println("a + b = " + (a + b)); *= a *= b; a = a * b;
/= a /= b; a = a / b;
// subtraction operator %= a %= b; a = a % b;
System.out.println("a - b = " + (a - b));
Example 2: Assignment Operators
// multiplication operator class Main {
System.out.println("a * b = " + (a * b)); public static void main(String[] args) {

// division operator // create variables


System.out.println("a / b = " + (a / b)); int a = 4;
int var;
// modulo operator
System.out.println("a % b = " + (a % b)); // assign value using =
} var = a;
} System.out.println("var using =: " + var);

Output // assign value using =+


a + b = 17 var += a;
a-b=7 System.out.println("var using +=: " + var);
a * b = 60
a/b=2 // assign value using =*
a%b=2 var *= a;
System.out.println("var using *=: " + var);
In the above example, we have used + , - , }
and * operators to compute addition, subtraction, and }
multiplication operations.
/ Division Operator Output
Note the operation, a / b in our program. var using =: 4
var using +=: 8
The / operator is the division operator. var using *=: 32
If we use the division operator with two integers, then
the resulting quotient will also be an integer. And, if 3. Java Relational Operators
one of the operands is a floating-point number, we will Relational operators are used to check the relationship
get the result will also be in floating-point. between two operands. For example,
// check if a is less than b
In Java, a < b;
(9 / 2) is 4 Here, < operator is the relational operator. It checks if
(9.0 / 2) is 4.5 a is less than b or not.
(9 / 2.0) is 4.5
(9.0 / 2.0) is 4.5 It returns either true or false.
% Modulo Operator Operator Description Example
The modulo operator % computes the remainder. == Is Equal To 3 == 5 returns
When a = 7 is divided by b = 4 , the remainder is 3. false
!= Not Equal To 3 != 5 returns
Note: The % operator is mainly used with integers. true
> Greater Than 3 > 5 returns
false
2. Java Assignment Operators
< Less Than 3 < 5 returns
Assignment operators are used in Java to assign values
true
to variables. For example,
int age; >= Greater Than or 3 >= 5 returns
age = 5; Equal To false
<= Less Than or 3 <= 5 returns
Equal To true
Here, = is the assignment operator. It assigns the
value on its right to the variable on its left. That is, 5 is Example 3: Relational Operators
assigned to the variable age . class Main {
Let's see some more assignment operators available in public static void main(String[] args) {
Java.
Operator Example Equivalent to // create variables
= a = b; a = b; int a = 7, b = 11;
// ! operator
// value of a and b System.out.println(!(5 == 3)); // true
System.out.println("a is " + a + " and b is " + b); System.out.println(!(5 > 3)); // false
}
// == operator }
System.out.println(a == b); // false
Working of Program
// != operator  (5 > 3) && (8 > 5) returns true because both (5 >
System.out.println(a != b); // true 3) and (8 > 5) are true.
 (5 > 3) && (8 < 5) returns false because the
// > operator expression (8 < 5) is false.
System.out.println(a > b); // false  (5 < 3) || (8 > 5) returns true because the
expression (8 > 5) is true.
// < operator  (5 > 3) || (8 < 5) returns true because the
System.out.println(a < b); // true expression (5 > 3) is true.
 (5 < 3) || (8 < 5) returns false because both (5 <
// >= operator 3) and (8 < 5) are false.
System.out.println(a >= b); // false  !(5 == 3) returns true because 5 == 3 is false.
 !(5 > 3) returns false because 5 > 3 is true.
// <= operator
System.out.println(a <= b); // true
} 5. Java Unary Operators
} Unary operators are used with only one operand. For
example, ++ is a unary operator that increases the
value of a variable by 1. That is, ++5 will return 6.
Note: Relational operators are used in decision Different types of unary operators are:
making and loops.
Operator Meaning
+ Unary plus: not necessary to use since
numbers are positive without using it
- Unary minus: inverts the sign of an
4. Java Logical Operators expression
Logical operators are used to check whether an ++ Increment operator: increments value by
1
expression is true or false . They are used in decision
-- Decrement operator: decrements value
making.
by 1
Operator Example Meaning
! Logical complement operator: inverts
&& (Logical expression1 && true only if both the value of a boolean
AND) expression2 expression1 and
expression2 are
Increment and Decrement Operators
true
Java also provides increment and decrement
|| (Logical expression1 || true if either
OR) expression2 expression1 or operators: ++ and -- respectively. ++ increases the
expression2 is value of the operand by 1, while -- decrease it by 1.
true For example,
! (Logical NOT) !expression true if int num = 5;
expression is // increase num by 1
false and vice ++num;
versa
Here, the value of num gets increased to 6 from its
Example 4: Logical Operators initial value of 5.
class Main {
public static void main(String[] args) {

// && operator
System.out.println((5 > 3) && (8 > 5)); // true Example 5: Increment and Decrement Operators
System.out.println((5 > 3) && (8 < 5)); // false class Main {
public static void main(String[] args) {
// || operator
System.out.println((5 < 3) || (8 > 5)); // true // declare variables
System.out.println((5 > 3) || (8 < 5)); // true int a = 12, b = 12;
System.out.println((5 < 3) || (8 < 5)); // false int result1, result2;
// original value // checks if str is an instance of
System.out.println("Value of a: " + a); // the String class
result = str instanceof String;
// increment operator System.out.println("Is str an object of String? " +
result1 = ++a; result);
System.out.println("After increment: " + result1); }
}
System.out.println("Value of b: " + b);
Output
// decrement operator Is str an object of String? true
result2 = --b; Here, str is an instance of the String class. Hence, the
System.out.println("After decrement: " + result2); instanceof operator returns true.
}
} Java Ternary Operator
The ternary operator (conditional operator) is
Output shorthand for the if-then-else statement. For example,
Value of a: 12 variable = Expression ? expression1 : expression2
After increment: 13
Value of b: 12 Here's how it works.
After decrement: 11  If the Expression is true, expression1 is assigned to
the variable.
In the above program, we have used the ++ and --  If the Expression is false, expression2 is assigned to
operator as prefixes (++a, --b). We can also use these the variable.
operators as postfix (a++, b++). Let's see an example of a ternary operator.
There is a slight difference when these operators are class Java {
used as prefix versus when they are used as a postfix. public static void main(String[] args) {

int februaryDays = 29;


6. Java Bitwise Operators String result;
Bitwise operators in Java are used to perform
operations on individual bits. For example, // ternary operator
Bitwise complement Operation of 35 result = (februaryDays == 28) ? "Not a leap year" :
35 = 00100011 (In Binary) "Leap year";
~ 00100011 System.out.println(result);
________ }
11011100 = 220 (In decimal) }

Here, ~ is a bitwise operator. It inverts the value of Output


each bit (0 to 1 and 1 to 0). Leap year
The various bitwise operators present in Java are:
Operator Description Java Basic Input and Output
~ Bitwise Complement Java Output
<< Left Shift In Java, you can simply use
>> Right Shift System.out.println(); or
>>> Unsigned Right Shift System.out.print(); or
& Bitwise AND System.out.printf();
^ Bitwise exclusive OR
to send output to standard output (screen).
These operators are not generally used in Java. Here,
 System is a class
Other operators  out is a public static field: it accepts output data.
Besides these operators, there are other additional Don't worry if you don't understand it. We will
operators in Java. discuss class, public, and static in later chapters.
Java instanceof Operator Let's take an example to output a line.
The instanceof operator checks whether an object is class AssignmentOperator {
an instanceof a particular class. For example, public static void main(String[] args) {

class Main { System.out.println("Java programming is


public static void main(String[] args) { interesting.");
}
String str = "Programiz"; }
boolean result;
Output:
Java programming is interesting. }
}
Here, we have used the println() method to display
the string. Output:
I am awesome.
Difference between println(), print() and printf() Number = -10.6
 print() - It prints string inside the quotes.
In the above example, notice the line,
 println() - It prints string inside the quotes similar System.out.println("I am " + "awesome.");
like print() method. Then the cursor moves to the
beginning of the next line. Here, we have used the + operator to concatenate
 printf() - It provides string formatting (similar to printf (join) the two strings: "I am " and "awesome.".
in C/C++ programming).
 And also, the line,
Example: print() and println() System.out.println("Number = " + number);
class Output {
public static void main(String[] args) { Here, first the value of variable number is evaluated.
Then, the value is concatenated to the string: "Number
System.out.println("1. println "); = ".
System.out.println("2. println ");
Java Input
System.out.print("1. print "); Java provides different ways to get input from the
System.out.print("2. print"); user. However, in this tutorial, you will learn to get
} input from user using the object of Scanner class.
} In order to use the object of Scanner , we need to
import java.util.Scanner package.
Output:
1. println
import java.util.Scanner;
2. println
1. print 2. Print
Then, we need to create an object of
In the above example, we have shown the working of
the print() and println() methods. the Scanner class. We can use the object to take input
from the user.
// create an object of Scanner
Example: Printing Variables and Literals Scanner input = new Scanner(System.in);

class Variables { // take input from the user


public static void main(String[] args) { int number = input.nextInt();

Double number = -10.6; Example: Get Integer Input From the User
import java.util.Scanner;
System.out.println(5);
System.out.println(number); class Input {
} public static void main(String[] args) {
}
Scanner input = new Scanner(System.in);
When you run the program, the output will be:
5 System.out.print("Enter an integer: ");
-10.6 int number = input.nextInt();
System.out.println("You entered " + number);
Here, you can see that we have not used the quotation
marks. It is because to display integers, variables and // closing the scanner object
so on, we don't use quotation marks. input.close();
}
Example: Print Concatenated Strings }
class PrintVariables {
public static void main(String[] args) { Output:
Enter an integer: 23
Double number = -10.6; You entered 23

System.out.println("I am " + "awesome."); In the above example, we have created an object


System.out.println("Number = " + number); named input of the Scanner class. We then call
the nextInt() method of the Scanner class to get an Don't worry if you don't understand it. We will
integer input from the user. discuss class, public, and static in later chapters.
Similarly, we can Let's take an example to output a line.
use nextLong() , nextFloat() , nextDouble() , class AssignmentOperator {
public static void main(String[] args) {
and next() methods to get long , float , double ,
and string input respectively from the user. System.out.println("Java programming is
interesting.");
}
Note: We have used the close() method to close the }
object. It is recommended to close the scanner object
once the input is taken. Output:
Java programming is interesting.

Here, we have used the println() method to display


Example: Get float, double and String Input the string.
import java.util.Scanner;
Difference between println(), print() and printf()
class Input {  print() - It prints string inside the quotes.
public static void main(String[] args) {
 println() - It prints string inside the quotes similar
Scanner input = new Scanner(System.in); like print() method. Then the cursor moves to the
beginning of the next line.
// Getting float input  printf() - It provides string formatting (similar to printf
System.out.print("Enter float: "); in C/C++ programming).
float myFloat = input.nextFloat(); 
System.out.println("Float entered = " + myFloat); Example: print() and println()
class Output {
// Getting double input public static void main(String[] args) {
System.out.print("Enter double: ");
double myDouble = input.nextDouble(); System.out.println("1. println ");
System.out.println("Double entered = " + System.out.println("2. println ");
myDouble);
System.out.print("1. print ");
// Getting String input System.out.print("2. print");
System.out.print("Enter text: "); }
String myString = input.next(); }
System.out.println("Text entered = " +
myString); Output:
} 1. println
} 2. println
1. print 2. Print
Output:
Enter float: 2.343 In the above example, we have shown the working of
Float entered = 2.343 the print() and println() methods.
Enter double: -23.4
Double entered = -23.4
Enter text: Hey! Example: Printing Variables and Literals
Text entered = Hey! class Variables {
public static void main(String[] args) {
Java Basic Input and Output
Java Output Double number = -10.6;
In Java, you can simply use
System.out.println(); or System.out.println(5);
System.out.println(number);
System.out.print(); or }
}
System.out.printf();
When you run the program, the output will be:
to send output to standard output (screen). 5
Here, -10.6
 System is a class
 out is a public static field: it accepts output data.
Here, you can see that we have not used the quotation }
marks. It is because to display integers, variables and }
so on, we don't use quotation marks.
Output:
Example: Print Concatenated Strings
class PrintVariables { Enter an integer: 23
public static void main(String[] args) { You entered 23

Double number = -10.6; In the above example, we have created an object


named input of the Scanner class. We then call
System.out.println("I am " + "awesome."); the nextInt() method of the Scanner class to get an
System.out.println("Number = " + number);
integer input from the user.
}
Similarly, we can
}
use nextLong() , nextFloat() , nextDouble() ,
Output: and next() methods to get long , float , double ,
I am awesome. and string input respectively from the user.
Number = -10.6

In the above example, notice the line, Note: We have used the close() method to close the
System.out.println("I am " + "awesome."); object. It is recommended to close the scanner object
Here, we have used the + operator to concatenate once the input is taken.
(join) the two strings: "I am " and "awesome.".

And also, the line, Example: Get float, double and String Input
System.out.println("Number = " + number); import java.util.Scanner;
Here, first the value of variable number is evaluated.
Then, the value is concatenated to the string: "Number class Input {
= ". public static void main(String[] args) {
Java Input Scanner input = new Scanner(System.in);
Java provides different ways to get input from the
user. However, in this tutorial, you will learn to get // Getting float input
input from user using the object of Scanner class. System.out.print("Enter float: ");
In order to use the object of Scanner , we need to float myFloat = input.nextFloat();
import java.util.Scanner package. System.out.println("Float entered = " + myFloat);

import java.util.Scanner; // Getting double input


System.out.print("Enter double: ");
double myDouble = input.nextDouble();
Then, we need to create an object of System.out.println("Double entered = " +
myDouble);
the Scanner class. We can use the object to take input
from the user. // Getting String input
// create an object of Scanner System.out.print("Enter text: ");
Scanner input = new Scanner(System.in); String myString = input.next();
System.out.println("Text entered = " +
// take input from the user myString);
int number = input.nextInt(); }
}
Example: Get Integer Input From the User
import java.util.Scanner; Output:
Enter float: 2.343
class Input { Float entered = 2.343
public static void main(String[] args) { Enter double: -23.4
Double entered = -23.4
Scanner input = new Scanner(System.in); Enter text: Hey!
Text entered = Hey!
System.out.print("Enter an integer: "); As mentioned, there are other several ways to get
int number = input.nextInt(); input from the user.
System.out.println("You entered " + number);

// closing the scanner object


input.close();
Java Expressions, Statements and Blocks ++number;
In previous chapters, we have used expressions, Similarly, ++number is an expression
statements, and blocks without much explaining about whereas ++number; is a statement.
them. Now that you know about variables, operators,
and literals, it will be easier to understand these Declaration Statements
concepts. In Java, declaration statements are used for declaring
variables. For example,
Java Expressions Double tax = 9.5;
A Java expression consists The statement above declares a variable tax which is
of variables, operators, literals, and method calls.
initialized to 9.5 .
For example,
int score;
score = 90; Note: There are control flow statements that are used
Here, score = 90 is an expression that returns an int. in decision making and looping in Java. You will learn
Consider another example, about control flow statements in later chapters.

Double a = 2.2, b = 3.4, result;


result = a + b - 3.4; Java Blocks
Here, a + b - 3.4 is an expression. A block is a group of statements (zero or more) that is
enclosed in curly braces { } . For example,
if (number1 == number2)
System.out.println("Number 1 is larger than number class Main {
2");
Here, number1 == number2 is an expression that public static void main(String[] args) {
returns a boolean value. Similarly, "Number 1 is larger
than number 2" is a string expression. String band = "Beatles";
Java Statements
if (band == "Beatles") { // start of block
In Java, each statement is a complete unit of
execution. For example,
int score = 9*5; System.out.print("Hey ");
Here, we have a statement. The complete execution of
this statement involves multiplying System.out.print("Jude!");
integers 9 and 5 and then assigning the result to the
} // end of block
variable score .
In the above statement, we have an expression 9 * 5 . }
In Java, expressions are part of statements. }

Expression statements Output:


We can convert an expression into a statement by Hey Jude!
terminating the expression with a ; . These are known
as expression statements. For example, In the above example, we have a block if {....}.
Here, inside the block we have two statements:
// expression  System.out.print("Hey ");
 System.out.print("Jude!");
number = 10 However, a block may not have any statements.
Consider the following examples,
// statement
number = 10;
In the above example, we have an expression number class Main {
= 10 . Here, by adding a semicolon ( ; ), we have
public static void main(String[] args) {
converted the expression into a statement ( number =
10; ). if (10 > 5) { // start of block
Consider another example,
} // end of block
// expression
}
++number }

// statement
This is a valid Java program. Here, we have a block if int number = 10;
{...} . However, there is no any statement inside this
block. // checks if number is less than 0

if (number < 0) {
class AssignmentOperator {
System.out.println("The number is negative."); }
public static void main(String[] args) { // start of
block System.out.println("Statement outside if block"); }}

} // end of block Output


} Statement outside if block
Here, we have block public static void main() {...} .
In the program, number < 0 is false . Hence, the code
However, similar to the above example, this block
does not have any statement. inside the body of the if statement is skipped.

We can also use Java Strings as the test condition.


Example 2: Java if with String
Java Flow Control
class Main {

public static void main(String[] args) {


Java if...else Statement
In programming, we use the if..else statement to run a // create a string variable
block of code among more than one alternatives.
For example, assigning grades (A, B, C) based on the String language = "Java";
percentage obtained by a student.
 if the percentage is above 90, assign grade A // if statement
 if the percentage is above 75, assign grade B
 if the percentage is above 65, assign grade C if (language == "Java") {

1. Java if (if-then) Statement
System.out.println("Best Programming
The syntax of an if-then statement is:
Language");
if (condition) {
} }}
// statements
}
Here, condition is a boolean expression such as age
Output
>= 18 .
 if condition evaluates to true , the lines of code Best Programming Language
inside if are executed In the above example, we are comparing two strings in
 if condition evaluates to false , the lines of code the if block.
inside if are skipped 2. Java if...else (if-then-else) Statement
Working of if Statement The if statement executes a certain section of code if
the test expression is evaluated to true . However, if
the test expression is evaluated to false , it does
nothing.
In this case, we can use an optional else block.
Statements inside the body of else block are executed
if the test expression is evaluated to false . This is
known as the if-...else statement in Java.
The syntax of the if...else statement is:

Example 1: Java if Statement


if (condition) {
class IfStatement {
// codes in if block}
public static void main(String[] args) {
else { Now, change the value of the number to a negative
integer. Let's say -5 .
// codes in else block}
int number = -5;
Here, the program will do one task (codes inside if
block) if the condition is true and another task (codes If we run the program with the new value of number,
inside else block) if the condition is false. the output will be:
How the if...else statement works? The number is not positive.

Statement outside if...else block

Here, the value of number is -5. So the test expression


evaluates to false. Hence code inside the body of else
is executed.

3. Java if...else...if Statement


In Java, we have an if...else...if ladder, that can be
used to execute one block of code among multiple
Example 3: Java if...else Statement other blocks.

class Main {
if (condition1) {
public static void main(String[] args) {
// codes}
int number = 10;
else if(condition2) {
// checks if number is greater than 0
// codes}
if (number > 0) {
else if (condition3) {
System.out.println("The number is positive."); }
// codes}
// execute this block
else {
// if number is not greater than 0
// codes}
else {
Here, if statements are executed from the top towards
System.out.println("The number is not positive."); the bottom. When the test condition is true , codes
}
inside the body of that if block is executed. And,
System.out.println("Statement outside if...else program control jumps outside the if...else...if ladder.
block"); If all test expressions are false , codes inside the body
of else are executed.
}}
How the if...else...if ladder works?
Output

The number is positive.


Statement outside if...else block

n the above example, we have a variable


named number . Here, the test expression number >
0 checks if number is greater than 0.
Since the value of the number is 10 , the test
expression evaluates to true . Hence code inside the
body of if is executed.
Example 4: Java if...else...if Statement Double n1 = -1.0, n2 = 4.5, n3 = -5.3, largest;

class Main { // checks if n1 is greater than or equal to n2

public static void main(String[] args) { if (n1 >= n2) {

int number = 0; // if...else statement inside the if block

// checks if number is greater than 0 // checks if n1 is greater than or equal to n3

if (number > 0) { if (n1 >= n3) {

System.out.println("The number is positive."); } largest = n1; }

// checks if number is less than 0 else {

else if (number < 0) { largest = n3; }

System.out.println("The number is negative."); } } else {

// if both condition is false // if..else statement inside else block

else { // checks if n2 is greater than or equal to n3

System.out.println("The number is 0."); if (n2 >= n3) {

}}} largest = n2; }

Output else {
The number is 0.
largest = n3;
In the above example, we are checking
whether number is positive, negative, or zero. Here, }}
we have two condition expressions:
 number > 0 - checks if number is greater than 0 System.out.println("Largest Number: " + largest);
 number < 0 - checks if number is less than 0
Here, the value of number is 0 . So both the }}
conditions evaluate to false . Hence the statement
inside the body of else is executed.
Output:
Note: Java provides a special operator called ternary
operator, which is a kind of shorthand notation Largest Number: 4.5
of if...else...if statement. In the above programs, we have assigned the value
of variables ourselves to make this easier.
However, in real-world applications, these values may
come from user input data, log files, form submission,
4. Java Nested if..else Statement
etc.
In Java, it is also possible to use if..else statements
inside an if...else statement. It's called the
nested if...else statement. Java Ternary Operator
Here's a program to find the largest of 3 numbers using In Java, a ternary operator can be used to replace
the nested if...else statement. the if…else statement in certain situations.
Example 5: Nested if...else Statement
Ternary Operator in Java
class Main { A ternary operator evaluates the test condition and
executes a block of code based on the result of the
public static void main(String[] args) { condition.
Its syntax is:
// declaring double type variables condition ? expression1 : expression2;
Here, condition is evaluated and
 if condition is true, expression1 is executed. Here, both programs give the same output. However,
 And, if condition is false, expression2 is executed. the use of the ternary operator makes our code more
readable and clean.
The ternary operator takes 3
operands (condition, expression1, and expression2). Note: You should only use the ternary operator if the
Hence, the name ternary operator. resulting statement is short.
Example: Java Ternary Operator
import java.util.Scanner;
class Main { Nested Ternary Operators
public static void main(String[] args) { It is also possible to use one ternary operator inside
// take input from users another ternary operator. It is called the nested ternary
Scanner input = new Scanner(System.in); operator in Java.
System.out.println("Enter your marks: "); Here's a program to find the largest of 3 numbers using
double marks = input.nextDouble(); the nested ternary operator.
// ternary operator checks if class Main {
// marks is greater than 40 public static void main(String[] args) {
String result = (marks > 40) ? "pass" : "fail"; // create a variable
System.out.println("You " + result + " the exam."); int n1 = 2, n2 = 9, n3 = -11;
input.close(); // nested ternary operator
}} // to find the largest number
Output 1 int largest = (n1 >= n2) ? ((n1 >= n3) ? n1 : n3) :
Enter your marks: ((n2 >= n3) ? n2 : n3);
75 System.out.println("Largest Number: " + largest);
You pass the exam. }}

Suppose the user enters 75. Then, the condition marks Output
> 40 evaluates to true. Hence, the first Largest Number: 9
expression "pass" is assigned to result. In the above example, notice the use of the ternary
operator,
Output 2 (n1 >= n2) ? ((n1 >=n3) ? n1 : n3) : ((n2 >= n3) ? n2 :
Enter your marks: n3);
24 Here,
You fail the exam.  (n1 >= n2) - first test condition that checks if n1 is
Now, suppose the user enters 24. Then, the greater than n2
 (n1 >= n3) - second test condition that is executed if
condition marks > 40 evaluates to false. Hence, the
the first condition is true
second expression "fail" is assigned to result.  (n2 >= n3) - third test condition that is executed if the
first condition is false
When to use the Ternary Operator?
In Java, the ternary operator can be used to replace
certain types of if...else statements. For example, Note: It is not recommended to use nested ternary
You can replace this code operators. This is because it makes our code more
class Main { complex.
public static void main(String[] args) {
// create a variable
int number = 24;
Java for Loop
if(number > 0) { In computer programming, loops are used to repeat a
block of code. For example, if you want to show a
System.out.println("Positive Number"); }
else { message 100 times, then rather than typing the same
System.out.println("Negative Number"); }}} code 100 times, you can use a loop.
With In Java, there are three types of loops.
class Main {  for loop
public static void main(String[] args) {  while loop
// create a variable  do...while loop
int number = 24; This tutorial focuses on the for loop. You will learn
String result = (number > 0) ? "Positive Number" : about the other types of loops in the upcoming
"Negative Number"; tutorials.
System.out.println(result); }}
Java for Loop
Output Java for loop is used to run a block of code for a
Positive Number certain number of times. The syntax of for loop is:
for (initialExpression; testExpression;
updateExpression) {
// body of the loop } 4
Here, 5
1. The initialExpression initializes and/or Here is how the program works.
declares variables and executes only once. Iteration Variable Condition: i Action
2. The condition is evaluated. If the condition is true, 1st i=1 true 1 is printed. i is
the body of the for loop is executed. n=5 increased to 2.
3. The updateExpression updates the value 2nd i=2 true 2 is printed. i is
n=5 increased to 3.
of initialExpression.
3rd i=3 true 3 is printed. i is
4. The condition is evaluated again. The process n=5 increased to 4.
continues until the condition is false. 4th i=4 true 4 is printed. i is
n=5 increased to 5.
Example 1: Display a Text Five Times 5th i=5 true 5 is printed. i is
// Program to print a text 5 times n=5 increased to 6.
class Main { 6th i=6 false The loop is
public static void main(String[] args) { n=5 terminated.
int n = 5;
// for loop Example 3: Display Sum of n Natural Numbers
for (int i = 1; i <= n; ++i) { // Program to find the sum of natural numbers from 1
System.out.println("Java is fun"); }}} to 1000.
Output class Main {
Java is fun public static void main(String[] args) {
Java is fun int sum = 0;
Java is fun int n = 1000;
Java is fun // for loop
Java is fun for (int i = 1; i <= n; ++i) {
Here is how this program works. // body inside for loop
Iteration Variable Condition: i Action sum += i; // sum = sum + i
1st i=1 true Java is fun }
n=5 is printed. i System.out.println("Sum = " + sum); }}
is increased
to 2. Output:
2nd i=2 true Java is fun Sum = 500500
n=5 is printed. i
is increased Here, the value of sum is 0 initially. Then, the for loop
to 3.
is iterated from i = 1 to 1000. In each iteration, i is
3rd i=3 true Java is fun
n=5 is printed. i added to sum and its value is increased by 1.
is increased When i becomes 1001, the test condition
to 4. is false and sum will be equal to 0 + 1 + 2 + .... +
4th i=4 true Java is fun 1000.
n=5 is printed. i The above program to add the sum of natural numbers
is increased can also be written as
to 5. // Program to find the sum of natural numbers from 1
5th i=5 true Java is fun to 1000.
n=5 is printed. i
is increased class Main {
to 6. public static void main(String[] args) {
6th i=6 false The loop is
n=5 terminated. int sum = 0;
int n = 1000;
Example 2: Display numbers from 1 to 5
// Program to print numbers from 1 to 5 // for loop
class Main { for (int i = n; i >= 1; --i) {
public static void main(String[] args) { // body inside for loop
int n = 5; sum += i; // sum = sum + i
// for loop }
for (int i = 1; i <= n; ++i) {
System.out.println(i); }}} System.out.println("Sum = " + sum);
Output }
1 }
2 The output of this program is the same as the Example
3 3.
 item - each item of array/collection is assigned to this
Java for-each Loop variable
The Java for loop has an alternative syntax that makes  dataType - the data type of the array/collection
it easy to iterate through arrays and collections. For 
example, Example 1: Print Array Elements
// print array elements // print array elements

class Main { class Main {


public static void main(String[] args) { public static void main(String[] args) {

// create an array // create an array


int[] numbers = {3, 7, 5, -5}; int[] numbers = {3, 9, 5, -5};

// iterating through the array // for each loop


for (int number: numbers) { for (int number: numbers) {
System.out.println(number); System.out.println(number);
} }}}
}
} Output
Output 3
3 9
7 5
5 -5
-5
Here, we have used the for-each loop to print each Here, we have used the for-each loop to print each
element of the numbers array one by one. element of the numbers array one by one.
In the first iteration of the loop, number will  In the first iteration, item will be 3.
be 3, number will be 7 in second iteration and so on.  In the second iteration, item will be 9.
 In the third iteration, item will be 5.
Java Infinite for Loop  In the fourth iteration, item will be -5.
If we set the test expression in such a way that it never
evaluates to false, the for loop will run forever. This is Example 2: Sum of Array Elements
called infinite for loop. For example, // Calculate the sum of all elements of an array
// Infinite for Loop
class Main {
class Infinite { public static void main(String[] args) {
public static void main(String[] args) {
// an array of numbers
int sum = 0; int[] numbers = {3, 4, 5, -5, 0, 12};
int sum = 0;
for (int i = 1; i <= 10; --i) {
System.out.println("Hello"); // iterating through each element of the array
} for (int number: numbers) {
} sum += number;
} }
Here, the test expression ,i <= 10, is
never false and Hello is printed repeatedly until the System.out.println("Sum = " + sum);
memory runs out. }
}
Java for-each Loop Output:
In Java, the for-each loop is used to iterate through Sum = 19
elements of arrays and collections (like ArrayList). It is
also known as the enhanced for loop. In the above program, the execution of the for
each loop looks as:
for-each Loop Syntax Iteration Variables
The syntax of the Java for-each loop is: 1 number = 3 sum = 0 + 3 = 3
for(dataType item : array) { 2 number = 4 sum = 3 + 4 = 7
... 3 number = 5 sum = 7 + 5 = 12
} 4 number = -5 sum = 12 + (-5) = 7
Here, 5 number = 0 sum = 7 + 0 = 7
 array - an array or a collection 6 number = 12 sum = 7 + 12 = 19
As we can see, we have added each element of Java while loop
the numbers array to the sum variable in each Java while loop is used to run a specific code until a
iteration of the loop. certain condition is met. The syntax of the while loop
is:
for loop Vs for-each loop while (testExpression) {
Let's see how a for-each loop is different from a // body of loop
regular Java for loop. }
1. Using for loop Here,
class Main { 1. A while loop evaluates the textExpression inside the
public static void main(String[] args) { parenthesis ().
2. If the textExpression evaluates to true, the code
char[] vowels = {'a', 'e', 'i', 'o', 'u'};
inside the while loop is executed.
// iterating through an array using a for loop 3. The textExpression is evaluated again.
for (int i = 0; i < vowels.length; ++ i) { 4. This process continues until
System.out.println(vowels[i]); the textExpression is false.
} 5. When the textExpression evaluates to false, the loop
} stops.
}
Output:
a Flowchart of while loop
e
i
o
u
2. Using for-each Loop
class Main {
public static void main(String[] args) {

char[] vowels = {'a', 'e', 'i', 'o', 'u'};

// iterating through an array using the for-each loop


for (char item: vowels) {
System.out.println(item);
}
}
}
Output:
a
e
i
o
u Flowchart of Java while loop
Here, the output of both programs is the same.
However, the for-each loop is easier to write and Example 1: Display Numbers from 1 to 5
understand. // Program to display numbers from 1 to 5
This is why the for-each loop is preferred over
the for loop when working with arrays and collections. class Main {
public static void main(String[] args) {
Java while and do...while Loop
In computer programming, loops are used to repeat a // declare variables
block of code. For example, if you want to show a int i = 1, n = 5;
message 100 times, then you can use a loop. It's just a // while loop from 1 to 5
simple example; you can achieve much more with while(i <= n) {
loops. System.out.println(i);
In the previous tutorial, you learned about Java for i++; }}}
loop. Here, you are going to learn
about while and do...while loops. Output
1
2
3
4
5
Here is how this program works.
Iteration Variable Condition: i Action Java do...while loop
1st i=1 true 1 is printed. i is The do...while loop is similar to while loop. However,
n=5 increased to 2. the body of do...while loop is executed once before the
2nd i=2 true 2 is printed. i is test expression is checked. For example,
n=5 increased to 3. do {
3rd i=3 true 3 is printed. i is // body of loop
n=5 increased to 4. } while(textExpression);
4th i=4 true 4 is printed. i is
n=5 increased to 5. Here,
5th i=5 true 5 is printed. i is 1.The body of the loop is executed at first. Then
n=5 increased to 6. the textExpression is evaluated.
6th i=6 false The loop is 2.If the textExpression evaluates to true, the body of the
n=5 terminated loop inside the do statement is executed again.
3.The textExpression is evaluated once again.
Example 2: Sum of Positive Numbers Only 4.If the textExpression evaluates to true, the body of the
loop inside the do statement is executed again.
// Java program to find the sum of positive numbers 5. This process continues until
import java.util.Scanner; the textExpression evaluates to false. Then the loop
stops.
class Main { Flowchart of do...while loop
public static void main(String[] args) {
int sum = 0;

// create an object of Scanner class


Scanner input = new Scanner(System.in);

// take integer input from the user


System.out.println("Enter a number");
int number = input.nextInt();

// while loop continues


// until entered number is positive
while (number >= 0) {
// add only positive numbers
sum += number;

System.out.println("Enter a number");
number = input.nextInt(); Flowchart of Java do while loop
}
System.out.println("Sum = " + sum); Let's see the working of do...while loop.
input.close();
Example 3: Display Numbers from 1 to 5
}
// Java Program to display numbers from 1 to 5
}
import java.util.Scanner;
Output
Enter a number // Program to find the sum of natural numbers from 1
25 to 100.
Enter a number
9 class Main {
Enter a number public static void main(String[] args) {
5
Enter a number int i = 1, n = 5;
-3
Sum = 39 // do...while loop from 1 to 5
In the above program, we have used the Scanner do {
class to take input from the user. Here, nextInt() takes System.out.println(i);
integer input from the user. i++;
The while loop continues until the user enters a } while(i <= n);
negative number. During each iteration, the number }
entered by the user is added to the sum variable. }
When the user enters a negative number, the loop Output
terminates. Finally, the total sum is displayed. 1
2 Sum = 39
3 Here, the user enters a positive number, that number is
4 added to the sum variable. And this process continues
5 until the number is negative. When the number is
Here is how this program works. negative, the loop terminates and displays the sum
Iteration Variable Condition: i without adding the negative number.
Action Output 2
i=1n=5 not 1 is printed. Enter a number
checked i is -8
increased to Sum is 0
2. Here, the user enters a negative number. The test
1st i=2n=5 true 2 is condition will be false but the code inside of the loop
printed. i is executes once.
increased to
3. Infinite while loop
2nd i=3n=5 true 3 is printed. If the condition of a loop is always true, the loop runs
i is for infinite times (until the memory is full). For
increased to example,
4. // infinite while loop
3rd i=4n=5 true 4 is printed. while(true){
i is // body of loop
increased to }
5.
4th i=5n=5 true 5 is printed. Here is an example of an infinite do...while loop.
i is
// infinite do...while loop
increased to int count = 1;
6.
do {
// body of loop
Example 4: Sum of Positive Numbers } while(count == 1)
// Java program to find the sum of positive numbers In the above programs, the textExpression is
import java.util.Scanner;
always true. Hence, the loop body will run for infinite
times.
class Main {
public static void main(String[] args) {
for and while loops
int sum = 0; The for loop is used when the number of iterations is
int number = 0; known. For example,
for (int i = 1; i <=5; ++i) {
// create an object of Scanner class // body of loop
Scanner input = new Scanner(System.in); }
And while and do...while loops are generally used
// do...while loop continues when the number of iterations is unknown. For
// until entered number is positive example,
do { while (condition) {
// add only positive numbers // body of loop
sum += number; }
System.out.println("Enter a number");
number = input.nextInt(); Java break Statement
} while(number >= 0); While working with loops, it is sometimes desirable to
skip some statements inside the loop or terminate the
System.out.println("Sum = " + sum); loop immediately without checking the test
input.close(); expression.
} In such cases, break and continue statements are
} used. You will learn about the Java continue
Output 1 statement in the next tutorial.
Enter a number
25 The break statement in Java terminates the loop
Enter a number
immediately, and the control of the program moves to
9
the next statement following the loop.
Enter a number
It is almost always used with decision-making
5
statements (Java if...else Statement).
Enter a number
Here is the syntax of the break statement in Java:
-3
break;
How break statement works? while (true) {
System.out.print("Enter a number: ");

// takes double input from user


number = input.nextDouble();

// if number is negative the loop terminates


if (number < 0.0) {
break;
}

sum += number;
}
Working of Java break Statement System.out.println("Sum = " + sum);
}
Example 1: Java break statement }
class Test {
public static void main(String[] args) { Output:
Enter a number: 3.2
// for loop Enter a number: 5
for (int i = 1; i <= 10; ++i) { Enter a number: 2.3
Enter a number: 0
// if the value of i is 5 the loop terminates Enter a number: -4.5
if (i == 5) { Sum = 10.5
break; In the above program, the test expression of
} the while loop is always true. Here, notice the line,
System.out.println(i); if (number < 0.0) {
} break;
} }
} This means when the user input negative numbers, the
while loop is terminated.
Output:
1 Java break and Nested Loop
2 In the case of nested loops, the break statement
3 terminates the innermost loop.
4
In the above program, we are using the for loop to
print the value of i in each iteration.

if (i == 5) {
break;
}
This means when the value of i is equal to 5, the loop
terminates. Hence we get the output with values less
than 5 only.

Example 2: Java break statement


The program below calculates the sum of numbers
entered by the user until user enters a negative
number. Working of break Statement with Nested Loops
To take input from the user, we have used
the Scanner object. Here, the break statement terminates the
innermost while loop, and control jumps to the outer
import java.util.Scanner; loop.

class UserInputSum { Labeled break Statement


public static void main(String[] args) { Till now, we have used the unlabeled break statement.
It terminates the innermost loop and switch statement.
Double number, sum = 0.0; However, there is another form of break statement in
Java known as the labeled break.
// create an object of Scanner We can use the labeled break statement to terminate
Scanner input = new Scanner(System.in); the outermost loop as well.
}
}

Output:
i = 1; j = 1
i = 1; j = 2
i = 2; j = 1
In the above example, the labeled break statement is
used to terminate the loop labeled as first. That is,
first:
for(int i = 1; i < 5; i++) {...}
Here, if we change the statement break first; to break
second; the program will behave differently. In this
case, for loop labeled as second will be terminated.
For example,
class LabeledBreak {
Working of the labeled break statement in Java public static void main(String[] args) {
As you can see in the above image, we have used
the label identifier to specify the outer loop. Now, // the for loop is labeled as first
notice how the break statement is used (break label;). first:
Here, the break statement is terminating the labeled for( int i = 1; i < 5; i++) {
statement (i.e. outer loop). Then, the control of the
program jumps to the statement after the labeled // the for loop is labeled as second
statement. second:
Here's another example: for(int j = 1; j < 3; j ++ ) {
while (testExpression) {
// codes System.out.println("i = " + i + "; j = " +j);
second:
while (testExpression) { // the break statement terminates the loop
// codes labeled as second
while(testExpression) { if ( i == 2)
// codes break second;
break second; }
} }
} }
// control jumps here }
}
In the above example, when the statement break Output:
second; is executed, the while loop labeled i = 1; j = 1
as second is terminated. And, the control of the i = 1; j = 2
i = 2; j = 1
program moves to the statement after the
i = 3; j = 1
second while loop. i = 3; j = 2
i = 4; j = 1
Example 3: labeled break Statement i = 4; j = 2
class LabeledBreak {
public static void main(String[] args) {
Java continue Statement
// the for loop is labeled as first While working with loops, sometimes you might want
first: to skip some statements or terminate the loop. In such
for( int i = 1; i < 5; i++) { cases, break and continue statements are used.

// the for loop is labeled as second Here, we will learn about the continue statement.
second:
for(int j = 1; j < 3; j ++ ) { Java continue
System.out.println("i = " + i + "; j = " +j); The continue statement skips the current iteration of a
loop (for, while, do...while, etc).
// the break statement breaks the first for After the continue statement, the program moves to
loop
the end of the loop. And, test expression is evaluated
if ( i == 2)
(update statement is evaluated in case of the for loop).
break first; Here's the syntax of the continue statement.
} continue;
}
Note: The continue statement is almost always used in class Main {
decision-making statements (if...else Statement). public static void main(String[] args) {

Double number, sum = 0.0;


Working of Java continue statement // create an object of Scanner
Scanner input = new Scanner(System.in);

for (int i = 1; i < 6; ++i) {


System.out.print("Enter number " + i + " : ");
// takes input from the user
number = input.nextDouble();

// if number is negative
// continue statement is executed
if (number <= 0.0) {
continue;
}

sum += number;
}
System.out.println("Sum = " + sum);
input.close();
}
}
Working of Java continue Statement Output:
Enter number 1: 2.2
Example 1: Java continue statement Enter number 2: 5.6
class Main { Enter number 3: 0
public static void main(String[] args) { Enter number 4: -2.4
Enter number 5: -3
// for loop Sum = 7.8
for (int i = 1; i <= 10; ++i) {
In the above example, we have used the for loop to
// if value of i is between 4 and 9 print the sum of 5 positive numbers. Notice the line,
// continue is executed if (number < 0.0) {
if (i > 4 && i < 9) { continue;
continue; }
} Here, when the user enters a negative number,
System.out.println(i); the continue statement is executed. This skips the
} current iteration of the loop and takes the program
} control to the update expression of the loop.
}
Output:
1 Note: To take input from the user, we have used
2 the Scanner object.
3
4
9 Java continue with Nested Loop
10 In the case of nested loops in Java,
In the above program, we are using the for loop to the continue statement skips the current iteration of
print the value of i in each iteration. the innermost loop.
Notice the statement,
if (i > 4 && i < 9) {
continue;
}
Here, the continue statement is executed when the
value of i becomes more than 4 and less than 9.
It then skips the print statement for those values.
Hence, the output skips the values 5, 6, 7, and 8.

Example 2: Compute the sum of 5 positive numbers


import java.util.Scanner;
continue:
}
Here, when the value of j is 2, the value of j is
increased and the continue statement is executed.
This skips the iteration of the inner loop. Hence, the
text Inner Loop: 2 is skipped from the output.

Labeled continue Statement


Till now, we have used the
unlabeled continue statement. However, there is
another form of continue statement in Java known
as labeled continue.
It includes the label of the loop along with
the continue keyword. For example,
continue label;
Here, the continue statement skips the current
iteration of the loop specified by label.

Working of Java continue statement with Nested


Loops

Example 3: continue with Nested Loop


class Main {
public static void main(String[] args) {

int i = 1, j = 1;

// outer loop
while (i <= 3) {

System.out.println("Outer Loop: " + i);

// inner loop Working of the Java labeled continue Statement


while(j <= 3) { We can see that the label identifier specifies the outer
loop. Notice the use of the continue inside the inner
if(j == 2) { loop.
j++; Here, the continue statement is skipping the current
continue; iteration of the labeled statement (i.e. outer loop).
} Then, the program control goes to the next iteration of
the labeled statement.
System.out.println("Inner Loop: " + j);
j++; Example 4: labeled continue Statement
} class Main {
i++; public static void main(String[] args) {
}
} // outer loop is labeled as first
} first:
for (int i = 1; i < 6; ++i) {
Output
Outer Loop: 1 // inner loop
Inner Loop: 1 for (int j = 1; j < 5; ++j) {
Inner Loop: 3 if (i == 3 || j == 2)
Outer Loop: 2
Outer Loop: 3 // skips the current iteration of outer loop
continue first;
In the above example, we have used the nested while System.out.println("i = " + i + "; j = " + j);
loop. Note that we have used the continue statement }
inside the inner loop. }
if(j == 2) { }
j++; }
Output: Example: Java switch Statement
i = 1; j = 1 // Java Program to check the size
i = 2; j = 1 // using the switch...case statement
i = 4; j = 1
i = 5; j = 1 class Main {
public static void main(String[] args) {
In the above example, the labeled continue statement
is used to skip the current iteration of the loop labeled int number = 44;
as first. String size;
if (i==3 || j==2)
continue first; // switch statement to check size
switch (number) {
Here, we can see the outermost for loop is labeled
case 29:
as first,
size = "Small";
first: break;
for (int i = 1; i < 6; ++i) {..}
case 42:
Hence, the iteration of the outer for loop is skipped if size = "Medium";
the value of i is 3 or the value of j is 2. break;

Note: The use of labeled continue is often discouraged // match the value of week
as it makes your code hard to understand. If you are in case 44:
a situation where you have to use labeled continue, size = "Large";
break;
refactor your code and try to solve it in a different way
to make it more readable. case 48:
size = "Extra Large";
Java switch Statement break;
The switch statement allows us to execute a block of
code among many alternatives. default:
Syntax: size = "Unknown";
switch (expression) { break;

case value1: }
// code System.out.println("Size: " + size);
break; }
}
case value2:
// code Output:
break; Size: Large
In the above example, we have used
... the switch statement to find the size. Here, we have a
... variable number. The variable is compared with the
value of each case statement.
default: Since the value matches with 44, the code of case 44 is
// default statements executed.
} size = "Large";
How does the switch-case statement work? break;
The expression is evaluated once and compared with
the values of each case. Here, the size variable is assigned with the
 If expression matches with value1, the code of case value Large.
value1 are executed. Similarly, the code of case
value2 is executed if expression matches with value2
 If there is no match, the code of the default case is
executed

Note: The working of the switch-case statement is


similar to the Java if...else...if ladder. However, the
syntax of the switch statement is cleaner and much
easier to read and write.
System.out.println("Case 2");
Flowchart of switch Statement
case 3:
System.out.println("Case 3");

default:
System.out.println("Default case");
}
}
}

Output
Case 2
Case 3
Default case
In the above example, expression matches with case
2. Here, we haven't used the break statement after
each case.
Hence, all the cases after case 2 are also executed.
This is why the break statement is needed to terminate
the switch-case statement after the matching case.

default Case in Java switch-case


The switch statement also includes an optional
default case. It is executed when the expression
doesn't match any of the cases. For example,
class Main {
public static void main(String[] args) {

int expression = 9;

switch(expression) {

case 2:
System.out.println("Small Size");
break;

Flow chart of the Java switch statement case 3:


System.out.println("Large Size");
break Statement in Java switch...case break;
Notice that we have been using break in each case
block. // default case
... default:
case 29: System.out.println("Unknown Size");
size = "Small"; }
break; }
... }
The break statement is used to terminate the switch- Output
case statement. If break is not used, all the cases after Unknown Size
the matching case are also executed. For example,
class Main { In the above example, we have created a switch-
public static void main(String[] args) { case statement. Here, the value of expression doesn't
match with any of the cases.
int expression = 2; Hence, the code inside the default case is executed.
default:
// switch statement to check size System.out.println("Unknown Size);
switch (expression) {
case 1: Note: The Java switch statement only works with:
System.out.println("Case 1"); Primitive data types: byte, short, char, and int
Enumerated types
// matching case String Class
case 2: Wrapper Classes: Character, Byte, Short, and Integer.
age[1] = 4;
Java Arrays age[2] = 5;
..

Java Arrays
An array is a collection of similar types of data.
For example, if we want to store the names of 100
Java
people then we can create an array of the string type
Arrays initialization
that can store 100 names.
String[] array = new String[100]; Note:
Here, the above array cannot store more than 100  Array indices always start from 0. That is, the first
element of an array is at index 0.
names. The number of values in a Java array is always
fixed.  If the size of an array is n, then the last element of the
array will be at index n-1.
How to declare an array in Java?
In Java, here is how we can declare an array. How to Access Elements of an Array in Java?
dataType[] arrayName; AD
 dataType - it can be primitive data We can access the element of an array using the index
types like int, char, double, byte, etc. or Java objects number. Here is the syntax for accessing elements of
an array,
 arrayName - it is an identifier
// access array elements
For example, array[index]
double[] data;
Let's see an example of accessing array elements using
Here, data is an array that can hold values of index numbers.
type double. Example: Access Array Elements
But, how many elements can array this hold? class Main {
Good question! To define the number of elements that public static void main(String[] args) {
an array can hold, we have to allocate memory for the
array in Java. For example, // create an array
// declare an array int[] age = {12, 4, 5, 2, 5};
double[] data;
// access each array elements
// allocate memory System.out.println("Accessing Elements of Array:");
data = new double[10]; System.out.println("First Element: " + age[0]);
System.out.println("Second Element: " + age[1]);
Here, the array can store 10 elements. We can also say System.out.println("Third Element: " + age[2]);
that the size or length of the array is 10. System.out.println("Fourth Element: " + age[3]);
In Java, we can declare and allocate the memory of an System.out.println("Fifth Element: " + age[4]);
array in one single statement. For example, }
double[] data = new double[10]; }

How to Initialize Arrays in Java? Output


In Java, we can initialize arrays during declaration. Accessing Elements of Array:
For example, First Element: 12
//declare and initialize and array Second Element: 4
int[] age = {12, 4, 5, 2, 5}; Third Element: 5
Fourth Element: 2
Here, we have created an array named age and Fifth Element: 5
initialized it with the values inside the curly brackets. In the above example, notice that we are using the
Note that we have not provided the size of the array. index number to access each element of the array.
In this case, the Java compiler automatically specifies We can use loops to access all the elements of the
the size by counting the number of elements in the array at once.
array (i.e. 5).
In the Java array, each memory location is associated Looping Through Array Elements
with a number. The number is known as an array In Java, we can also loop through each element of the
index. We can also initialize arrays in Java, using the array. For example,
index number. For example, Example: Using For Loop
// declare an array class Main {
int[] age = new int[5]; public static void main(String[] args) {

// initialize array // create an array


age[0] = 12; int[] age = {12, 4, 5};
int arrayLength = numbers.length;
// loop through the array
// using for loop // calculate the average
System.out.println("Using for Loop:"); // convert the average from int to double
for(int i = 0; i < age.length; i++) { average = ((double)sum / (double)arrayLength);
System.out.println(age[i]);
} System.out.println("Sum = " + sum);
} System.out.println("Average = " + average);
} }
}
Output
Using for Loop: Output:
12 Sum = 36
4 Average = 3.6
5
In the above example, we have created an array of
In the above example, we are using the for Loop in named numbers. We have used the for...each loop to
Java to iterate through each element of the array. access each element of the array.
Notice the expression inside the loop, Inside the loop, we are calculating the sum of each
age.length element. Notice the line,
int arrayLength = number.length;
Here, we are using the length property of the array to
get the size of the array. Here, we are using the length attribute of the array to
We can also use the for-each loop to iterate through calculate the size of the array. We then calculate the
the elements of an array. For example, average using:
Example: Using the for-each Loop average = ((double)sum / (double)arrayLength);
class Main {
public static void main(String[] args) { As you can see, we are converting the int value
into double. This is called type casting in Java.
// create an array
int[] age = {12, 4, 5}; Multidimensional Arrays
Arrays we have mentioned till now are called one-
// loop through the array dimensional arrays. However, we can declare
// using for loop multidimensional arrays in Java.
System.out.println("Using for-each Loop:"); A multidimensional array is an array of arrays. That
for(int a : age) { is, each element of a multidimensional array is an
System.out.println(a); array itself. For example,
} double[][] matrix = {{1.2, 4.3, 4.0},
} {4.1, -1.1}
} };
Output Here, we have created a multidimensional array
Using for-each Loop: named matrix. It is a 2-dimensional array.
12
4
5
Java Multidimensional Arrays
Example: Compute Sum and Average of Array
A multidimensional array is an array of arrays. Each
Elements
element of a multidimensional array is an array itself.
class Main {
For example,
public static void main(String[] args) {
int[][] a = new int[3][4];
Here, we have created a multidimensional array
int[] numbers = {2, -9, 0, 5, 12, -25, 22, 9, 8, 12};
int sum = 0; named a. It is a 2-dimensional array, that can hold a
Double average; maximum of 12 elements,

// access all elements using for each loop


// add each element in sum
for (int number: numbers) {
sum += number;
}

// get the total number of elements


// calculate the length of each row
System.out.println("Length of row 1: " +
a[0].length);
System.out.println("Length of row 2: " +
a[1].length);
System.out.println("Length of row 3: " +
a[2].length);
}
}

Output:
Length of row 1: 3
Length of row 2: 4
2-dimensional Array Length of row 3: 1
Remember, Java uses zero-based indexing, that is,
indexing of arrays in Java starts with 0 and not 1. In the above example, we are creating a
Let's take another example of the multidimensional multidimensional array named a. Since each
array. This time we will be creating a 3-dimensional component of a multidimensional array is also an
array. For example, array (a[0], a[1] and a[2] are also arrays).
String[][][] data = new String[3][4][2]; Here, we are using the length attribute to calculate the
length of each row.
Here, data is a 3d array that can hold a maximum of
24 (3*4*2) elements of type String. Example: Print all elements of 2d array Using Loop
class MultidimensionalArray {
How to initialize a 2d array in Java? public static void main(String[] args) {
Here is how we can initialize a 2-dimensional array in
Java. int[][] a = {
int[][] a = { {1, -2, 3},
{1, 2, 3}, {-4, -5, 6, 9},
{4, 5, 6, 9}, {7},
{7}, };
};
for (int i = 0; i < a.length; ++i) {
As we can see, each element of the multidimensional for(int j = 0; j < a[i].length; ++j) {
array is an array itself. And also, unlike C/C++, each System.out.println(a[i][j]);
row of the multidimensional array in Java can be of }
different lengths. }
}
}

Output:
1
-2
3
-4
-5
6
9
7

We can also use the for...each loop to access elements


Initialization of 2-dimensional Array of the multidimensional array. For example,
Example: 2-dimensional Array class MultidimensionalArray {
class MultidimensionalArray { public static void main(String[] args) {
public static void main(String[] args) {
// create a 2d array
// create a 2d array int[][] a = {
int[][] a = { {1, -2, 3},
{1, 2, 3}, {-4, -5, 6, 9},
{4, 5, 6, 9}, {7},
{7}, };
};
// first for...each loop access the individual array
// inside the 2d array // for..each loop to iterate through elements of
for (int[] innerArray: a) { 3d array
// second for...each loop access each element for (int[][] array2D: test) {
inside the row for (int[] array1D: array2D) {
for(int data: innerArray) { for(int item: array1D) {
System.out.println(data); System.out.println(item);
} }
} }
} }
} }
}
Output:
1 Output:
-2 1
3 -2
-4 3
-5 2
6 3
9 4
7 -4
-5
In the above example, we are have created a 2d array 6
named a. We then used for loop and for...each loop 9
to access each element of the array. 1
2
How to initialize a 3d array in Java? 3
Let's see how we can use a 3d array in Java. We can
initialize a 3d array similar to the 2d array. For
example, Java Copy Arrays
// test is a 3d array In Java, we can copy one array into another. There are
int[][][] test = { several techniques you can use to copy arrays in Java.
{
{1, -2, 3}, 1. Copying Arrays Using Assignment Operator
{2, 3, 4} Let's take an example,
}, class Main {
{ public static void main(String[] args) {
{-4, -5, 6, 9},
{1}, int [] numbers = {1, 2, 3, 4, 5, 6};
{2, 3} int [] positiveNumbers = numbers; // copying
} arrays
};
for (int number: positiveNumbers) {
Basically, a 3d array is an array of 2d arrays. The rows System.out.print(number + ", ");
of a 3d array can also vary in length just like in a 2d }
array. }
}
Example: 3-dimensional Array
class ThreeArray { ;Output:
public static void main(String[] args) { 1, 2, 3, 4, 5, 6

// create a 3d array In the above example, we have used the assignment


int[][][] test = { operator (=) to copy an array named numbers to
{
another array named positiveNumbers.
{1, -2, 3},
This technique is the easiest one and it works as well.
{2, 3, 4}
However, there is a problem with this technique. If we
},
change elements of one array, corresponding elements
{
of the other arrays also change. For example,
{-4, -5, 6, 9},
class Main {
{1},
public static void main(String[] args) {
{2, 3}
}
int [] numbers = {1, 2, 3, 4, 5, 6};
};
int [] positiveNumbers = numbers; // copying
arrays
// change value of first array 3. Copying Arrays Using arraycopy() method
numbers[0] = -1; In Java, the System class contains a method
named arraycopy() to copy arrays. This method is a
// printing the second array better approach to copy arrays than the above two.
for (int number: positiveNumbers) { The arraycopy() method allows you to copy a
System.out.print(number + ", "); specified portion of the source array to the destination
} array. For example,
} arraycopy(Object src, int srcPos,Object dest, int
} destPos, int length)
Output: Here,
-1, 2, 3, 4, 5, 6  src - source array you want to copy
Here, we can see that we have changed one value of  srcPos - starting position (index) in the source array
the numbers array. When we print  dest - destination array where elements will be copied
the positiveNumbers array, we can see that the same from the source
value is also changed.  destPos - starting position (index) in the destination
It's because both arrays refer to the same array object. array
This is because of the shallow copy.  length - number of elements to copy
Now, to make new array objects while copying the Let's take an example:
arrays, we need deep copy rather than a shallow copy. // To use Arrays.toString() method
import java.util.Arrays;
2. Using Looping Construct to Copy Arrays
Let's take an example: class Main {
import java.util.Arrays; public static void main(String[] args) {
int[] n1 = {2, 3, 12, 4, 12, -2};
class Main {
public static void main(String[] args) { int[] n3 = new int[5];

int [] source = {1, 2, 3, 4, 5, 6}; // Creating n2 array of having length of n1 array


int [] destination = new int[6]; int[] n2 = new int[n1.length];

// iterate and copy elements from source to // copying entire n1 array to n2


destination System.arraycopy(n1, 0, n2, 0, n1.length);
for (int i = 0; i < source.length; ++i) { System.out.println("n2 = " +
destination[i] = source[i]; Arrays.toString(n2));
}
// copying elements from index 2 on n1 array
// converting array to string // copying element to index 1 of n3 array
System.out.println(Arrays.toString(destination)); // 2 elements will be copied
} System.arraycopy(n1, 2, n3, 1, 2);
} System.out.println("n3 = " +
Arrays.toString(n3));
Output: }
[1, 2, 3, 4, 5, 6] }

In the above example, we have used the for loop to Output:


iterate through each element of the source array. In n2 = [2, 3, 12, 4, 12, -2]
each iteration, we are copying elements from n3 = [0, 12, 4, 0, 0]
the source array to the destination array.
Here, the source and destination array refer to In the above example, we have used
different objects (deep copy). Hence, if elements of one the arraycopy() method,
array are changed, corresponding elements of another  System.arraycopy(n1, 0, n2, 0, n1.length) - entire
array is unchanged. elements from the n1 array are copied to n2 array
Notice the statement,  System.arraycopy(n1, 2, n3, 1, 2) - 2 elements of
System.out.println(Arrays.toString(destination)); the n1 array starting from index 2 are copied to the
index starting from 1 of the n3 array
Here, the toString() method is used to convert an array
into a string. As you can see, the default initial value of elements of
an int type array is 0.
for (int j = 0; j < destination[i].length; ++j) {
4. Copying Arrays Using copyOfRange() method destination[i][j] = source[i][j];
We can also use the copyOfRange() method defined }
in Java Arrays class to copy arrays. For example, }
// To use toString() and copyOfRange() method
import java.util.Arrays; // displaying destination array

class ArraysCopy { System.out.println(Arrays.deepToString(destination));


public static void main(String[] args) {
}
int[] source = {2, 3, 12, 4, 12, -2}; }

// copying entire source array to destination Output:


int[] destination1 = Arrays.copyOfRange(source, [[1, 2, 3, 4], [5, 6], [0, 2, 42, -4, 5]]
0, source.length);
System.out.println("destination1 = " + In the above program, notice the line,
Arrays.toString(destination1)); System.out.println(Arrays.deepToString(destination);

// copying from index 2 to 5 (5 is not included) Here, the deepToString() method is used to provide a
int[] destination2 = Arrays.copyOfRange(source, better representation of the 2-dimensional array.
2, 5);
System.out.println("destination2 = " + Copying 2d Arrays using arraycopy()
Arrays.toString(destination2)); To make the above code more simpler, we can replace
} the inner loop with System.arraycopy() as in the case
} of a single-dimensional array. For example,
import java.util.Arrays;
Output
destination1 = [2, 3, 12, 4, 12, -2] class Main {
destination2 = [12, 4, 12] public static void main(String[] args) {
In the above example, notice the line, int[][] source = {
int[] destination1 = Arrays.copyOfRange(source, 0, {1, 2, 3, 4},
source.length); {5, 6},
{0, 2, 42, -4, 5}
Here, we can see that we are creating };
the destination1 array and copying the source array to
it at the same time. We are not creating int[][] destination = new int[source.length][];
the destination1 array before calling
the copyOfRange() method. for (int i = 0; i < source.length; ++i) {

5. Copying 2d Arrays Using Loop // allocating space for each row of destination
Similar to the single-dimensional array, we can also array
copy the 2-dimensional array using the for loop. For destination[i] = new int[source[i].length];
example, System.arraycopy(source[i], 0, destination[i],
import java.util.Arrays; 0, destination[i].length);
}
class Main {
public static void main(String[] args) { // displaying destination array

int[][] source = { System.out.println(Arrays.deepToString(destination));


{1, 2, 3, 4}, }
{5, 6}, }
{0, 2, 42, -4, 5}
}; Output:
[[1, 2, 3, 4], [5, 6], [0, 2, 42, -4, 5]]
int[][] destination = new int[source.length][];
Here, we can see that we get the same output by
for (int i = 0; i < destination.length; ++i) { replacing the inner for loop with
the arraycopy() method.
// allocating space for each row of destination
array
destination[i] = new int[source[i].length];
Java OOP(I)
Java Objects
An object is called an instance of a class. For example,
suppose Bicycle is a class
Java Class and Objects
then MountainBicycle, SportsBicycle, TouringBicycl
Java is an object-oriented programming language. The
core concept of the object-oriented approach is to e, etc can be considered as objects of the class.
break complex problems into smaller objects. Creating an Object in Java
An object is any entity that has a state and behavior. Here is how we can create an object of a class.
For example, a bicycle is an object. It has className object = new className();
 States: idle, first gear, etc
// for Bicycle class
 Behaviors: braking, accelerating, etc.
Before we learn about objects, let's first know about Bicycle sportsBicycle = new Bicycle();
classes in Java.
Bicycle touringBicycle = new Bicycle();
Java Class
A class is a blueprint for the object. Before we create We have used the new keyword along with the
an object, we first need to define the class. constructor of the class to create an object.
We can think of the class as a sketch (prototype) of a Constructors are similar to methods and have the
house. It contains all the details about the floors, same name as the class. For example, Bicycle() is the
doors, windows, etc. Based on these descriptions we constructor of the Bicycle class.
build the house. House is the object.
Since many houses can be made from the same Here, sportsBicycle and touringBicycle are the names
description, we can create many objects from a class. of objects. We can use them to access fields and
methods of the class.
Create a class in Java As you can see, we have created two objects of the
We can create a class in Java using the class keyword. class. We can create multiple objects of a single class
For example, in Java.
class ClassName {
// fields
// methods Note: Fields and methods of a class are also called
} members of the class.

Here, fields (variables) and methods represent


the state and behavior of the object respectively. Access Members of a Class
 fields are used to store data We can use the name of objects along with
 methods are used to perform some operations the . operator to access members of a class. For
For our bicycle object, we can create the class as example,
class Bicycle { class Bicycle {

// state or field // field of class


private int gear = 5; int gear = 5;

// behavior or method // method of class


public void braking() { void braking() {
System.out.println("Working of Braking"); ...
} }
} }

In the above example, we have created a class // create object


named Bicycle. It contains a field named gear and a Bicycle sportsBicycle = new Bicycle();
method named braking().
Here, Bicycle is a prototype. Now, we can create any // access field and method
sportsBicycle.gear;
number of bicycles using the prototype. And, all the
sportsBicycle.braking();
bicycles will share the fields and methods of the
prototype.
In the above example, we have created a class
named Bicycle. It includes a field named gear and a
Note: We have used keywords private and public. method named braking(). Notice the statement,
These are known as access modifiers. Bicycle sportsBicycle = new Bicycle();
Here, we have created an object  halogen.turnOff() - It sets the isOn variable
of Bicycle named sportsBicycle. We then use the to false and prints the output.
object to access the field and method of the class. The variable isOn defined inside the class is also
 sportsBicycle.gear - access the field gear called an instance variable. It is because when we
 sportsBicycle.braking() - access the method braking() create an object of the class, it is called an instance of
We have mentioned the word method quite a few the class. And, each instance will have its own copy of
times. You will learn about Java methods in detail in the variable.
the next chapter. That is, led and halogen objects will have their own
Now that we understand what is class and object. Let's copy of the isOn variable.
see a fully working example.
Example: Create objects inside the same class
Example: Java Class and Objects Note that in the previous example, we have created
class Lamp { objects inside another class and accessed the members
from that class.
// stores the value for light However, we can also create objects inside the same
// true if light is on class.
// false if light is off class Lamp {
boolean isOn;
// stores the value for light
// method to turn on the light // true if light is on
void turnOn() { // false if light is off
isOn = true; boolean isOn;
System.out.println("Light on? " + isOn);
// method to turn on the light
} void turnOn() {
isOn = true;
// method to turnoff the light System.out.println("Light on? " + isOn);
void turnOff() {
isOn = false; }
System.out.println("Light on? " + isOn);
} public static void main(String[] args) {
}
// create an object of Lamp
public class Main { Lamp led = new Lamp();
public static void main(String[] args) {
// access method using object
// create objects led and halogen led.turnOn();
Lamp led = new Lamp(); }
Lamp halogen = new Lamp(); }
// turn on the light by Output
// calling method turnOn() Light on? True
led.turnOn();
Here, we are creating the object inside
// turn off the light by the main() method of the same class.
// calling method turnOff()
halogen.turnOff();
} Java Methods
} A method is a block of code that performs a specific
task.
Output: Suppose you need to create a program to create a
Light on? true circle and color it. You can create two methods to
Light on? False solve this problem:
 a method to draw the circle
In the above program, we have created a class  a method to color the circle
named Lamp. It contains a variable: isOn and two Dividing a complex problem into smaller chunks
makes your program easy to understand and reusable.
methods: turnOn() and turnOff().
In Java, there are two types of methods:
Inside the Main class, we have created two  User-defined Methods: We can create our own
objects: led and halogen of the Lamp class. We then method based on our requirements.
used the objects to call the methods of the class.  Standard Library Methods: These are built-in
 led.turnOn() - It sets the isOn variable to true and methods in Java that are available to use.
prints the output. Let's first learn about user-defined methods.
Declaring a Java Method
The syntax to declare a method is:
returnType methodName() {
// method body
}

Here,
 returnType - It specifies what type of value a method
returns For example if a method has an int return type
then it returns an integer value.
Working of Java Method Call
If the method does not return a value, its return type
is void. Example 1: Java Methods
 methodName - It is an identifier that is used to refer to class Main {
the particular method in a program.
 method body - It includes the programming // create a method
statements that are used to perform some tasks. The public int addNumbers(int a, int b) {
method body is enclosed inside the curly braces { }. int sum = a + b;
// return value
For example,
return sum;
int addNumbers() {
}
// code
}
public static void main(String[] args) {
In the above example, the name of the method
int num1 = 25;
is adddNumbers(). And, the return type is int. We
int num2 = 15;
will learn more about return types later in this tutorial.
This is the simple syntax of declaring a method. // create an object of Main
However, the complete syntax of declaring a method Main obj = new Main();
is // calling method
modifier static returnType nameOfMethod int result = obj.addNumbers(num1, num2);
(parameter1, parameter2, ...) { System.out.println("Sum is: " + result);
// method body }
} }
Here, Output
 modifier - It defines access types whether the method Sum is: 40
is public, private, and so on.
 static - If we use the static keyword, it can be accessed In the above example, we have created a method
without creating objects. named addNumbers(). The method takes two
parameters a and b. Notice the line,
For example, the sqrt() method of standard Math
int result = obj.addNumbers(num1, num2);
class is static. Hence, we can directly
call Math.sqrt() without creating an instance Here, we have called the method by passing two
of Math class. arguments num1 and num2. Since the method is
 parameter1/parameter2 - These are values passed to a returning some value, we have stored the value in
method. We can pass any number of arguments to a the result variable.
method.

Calling a Method in Java Note: The method is not static. Hence, we are calling
In the above example, we have declared a method the method using the object of the class.
named addNumbers(). Now, to use the method, we
need to call it.
Here's is how we can call the addNumbers() method. Java Method Return Type
// calls the method A Java method may or may not return a value to the
addNumbers(); function call. We use the return statement to return
any value. For example,
int addNumbers() {
...
return sum;
}
Here, we are returning the variable sum. Since the // code
return type of the function is int. The sum variable }
should be of int type. Otherwise, it will generate an
// method with no parameter
error.
int addNumbers(){
Example 2: Method Return Type
// code
class Main {
}
// create a method
If a method is created with parameters, we need to
public static int square(int num) {
pass the corresponding values while calling the
method. For example,
// return statement
// calling the method with two parameters
return num * num;
addNumbers(25, 15);
}
// calling the method with no parameters
public static void main(String[] args) {
addNumbers()
int result;
Example 3: Method Parameters
// call the method
class Main {
// store returned value to result
result = square(10);
// method with no parameter
public void display1() {
System.out.println("Squared value of 10 is: " +
System.out.println("Method without parameter");
result);
}
}
}
// method with single parameter
public void display2(int a) {
Output:
System.out.println("Method with a single
Squared value of 10 is: 100
parameter: " + a);
}
In the above program, we have created a method
named square(). The method takes a number as its public static void main(String[] args) {
parameter and returns the square of the number.
Here, we have mentioned the return type of the // create an object of Main
method as int. Hence, the method should always Main obj = new Main();
return an integer value.
// calling method with no parameter
obj.display1();

// calling method with the single parameter


obj.display2(24);
}
}

Output
Method without parameter
Method with a single parameter: 24
Representation of the Java method returning a value Here, the parameter of the method is int. Hence, if we
Note: If the method does not return any value, we use
the void keyword as the return type of the method. For pass any other data type instead of int, the compiler
example, will throw an error. It is because Java is a strongly
public void square(int a) { typed language.
int square = a * a; Note: The argument 24 passed to
System.out.println("Square is: " + square); the display2() method during the method call is called
} the actual argument.
The parameter a accepted by the method definition is
known as a formal argument. We need to specify the
Method Parameters in Java type of formal arguments. And, the type of actual
A method parameter is a value accepted by the arguments and formal arguments should always
method. As mentioned earlier, a method can also have match.
any number of parameters. For example,
// method with two parameters
int addNumbers(int a, int b) {
2. Methods make code more readable and easier to
Standard Library Methods debug. Here, the getSquare() method keeps the code
The standard library methods are built-in methods in to compute the square in a block. Hence, makes it
Java that are readily available for use. These standard more readable.
libraries come along with the Java Class Library (JCL)
in a Java archive (*.jar) file with JVM and JRE. Java Method Overloading
For example,
In Java, two or more methods may have the same
 print() is a method of java.io.PrintSteam. name if they differ in parameters (different number of
The print("...") method prints the string inside parameters, different types of parameters, or both).
quotation marks. These methods are called overloaded methods and this
 sqrt() is a method of Math class. It returns the square feature is called method overloading. For example:
root of a number. void func() { ... }
Here's a working example: void func(int a) { ... }
Example 4: Java Standard Library Method float func(double a) { ... }
public class Main { float func(int a, float b) { ... }
public static void main(String[] args) {
Here, the func() method is overloaded. These methods
// using the sqrt() method have the same name but accept different arguments.
System.out.print("Square root of 4 is: " +
Math.sqrt(4));
} Note: The return types of the above methods are not
} the same. It is because method overloading is not
associated with return types. Overloaded methods
Output:
may have the same or different return types, but they
Square root of 4 is: 2.0
must differ in parameters.

What are the advantages of using methods?


Why method overloading?
1. The main advantage is code reusability. We can
Suppose, you have to perform the addition of given
write a method once, and use it multiple times. We do
numbers but there can be any number of arguments
not have to rewrite the entire code each time. Think of
(let’s say either 2 or 3 arguments for simplicity).
it as, "write once, reuse multiple times".
In order to accomplish the task, you can create two
Example 5: Java Method for Code Reusability
public class Main { methods sum2num(int, int) and sum3num(int, int,
int) for two and three parameters respectively.
// method defined However, other programmers, as well as you in the
private static int getSquare(int x){ future may get confused as the behavior of both
return x * x; methods are the same but they differ by name.
} The better way to accomplish this task is by
overloading methods. And, depending upon the
public static void main(String[] args) { argument passed, one of the overloaded methods is
for (int i = 1; i <= 5; i++) { called. This helps to increase the readability of the
program.
// method call
int result = getSquare(i); How to perform method overloading in Java?
System.out.println("Square of " + i + " is: " + Here are different ways to perform method
result); overloading:
} 1. Overloading by changing the number of
} parameters
} class MethodOverloading {
private static void display(int a){
Output: System.out.println("Arguments: " + a);
Square of 1 is: 1 }
Square of 2 is: 4
Square of 3 is: 9 private static void display(int a, int b){
Square of 4 is: 16 System.out.println("Arguments: " + a + " and " +
Square of 5 is: 25 b);
}
In the above program, we have created the method
named getSquare() to calculate the square of a public static void main(String[] args) {
number. Here, the method is used to calculate the display(1);
square of numbers less than 6. display(1, 4);
Hence, the same method is used again and again. }
} Note: In Java, you can also overload constructors in a
similar way like methods.
Output:
Arguments: 1 Recommended Reading: Java Constructor
Arguments: 1 and 4 Overloading

2. Method Overloading by changing the data type of Important Points


parameters Two or more methods can have the same name inside
class MethodOverloading { the same class if they accept different arguments. This
feature is known as method overloading.
// this method accepts int Method overloading is achieved by either:
private static void display(int a){ changing the number of arguments.
System.out.println("Got Integer data."); or changing the data type of arguments.
} It is not method overloading if we only change the
return type of methods. There must be differences in
// this method accepts String object the number of parameters.
private static void display(String a){
System.out.println("Got String object.");
} Java Constructors
A constructor in Java is similar to a method that is
public static void main(String[] args) { invoked when an object of the class is created.
display(1); Unlike Java methods, a constructor has the same
display("Hello"); name as that of the class and does not have any return
} type. For example,
} class Test {
Test() {
Output: // constructor body
Got Integer data. }
Got String object. }
Here, both overloaded methods accept one argument.
Here, Test() is a constructor. It has the same name as
However, one accepts the argument of
that of the class and doesn't have a return type.
type int whereas other accepts String object.
Example: Java Constructor
Let’s look at a real-world example: class Main {
class HelperService { private String name;
private String formatNumber(int value) { // constructor
return String.format("%d", value); Main() {
} System.out.println("Constructor Called:");
name = "Programiz";
private String formatNumber(double value) { }
return String.format("%.3f", value);
} public static void main(String[] args) {
private String formatNumber(String value) { // constructor is invoked while
return String.format("%.2f", // creating an object of the Main class
Double.parseDouble(value)); Main obj = new Main();
} System.out.println("The name is " + obj.name);
}
public static void main(String[] args) { }
HelperService hs = new HelperService();
System.out.println(hs.formatNumber(500)); Output:
System.out.println(hs.formatNumber(89.9934)); Constructor Called:
System.out.println(hs.formatNumber("550")); The name is Programiz
}
} In the above example, we have created a constructor
named Main().
When you run the program, the output will be:
500 Inside the constructor, we are initializing the value of
89.993 the name variable.
550.00 Notice the statement creating an object of
the Main class.
Main obj = new Main();
Example: Java Public no-arg Constructors
Here, when the object is created, class Company {
the Main() constructor is called. And the value of String name;
the name variable is initialized.
Hence, the program prints the value of // public constructor
the name variables as Programiz. public Company() {
name = "Programiz";
}
Types of Constructor
}
In Java, constructors can be divided into three types:
1. No-Arg Constructor
class Main {
2. Parameterized Constructor
public static void main(String[] args) {
3. Default Constructor
// object is created in another class
1. Java No-Arg Constructors
Company obj = new Company();
Similar to methods, a Java constructor may or may
System.out.println("Company name = " +
not have any parameters (arguments).
obj.name);
If a constructor does not accept any parameters, it is
}
known as a no-argument constructor. For example,
}
private Constructor() {
// body of the constructor
Output
}
Company name = Programiz
Example: Java Private No-arg Constructor
2. Java Parameterized Constructor
class Main {
A Java constructor can also accept one or more
parameters. Such constructors are known as
int i;
parameterized constructors (constructors with
parameters).
// constructor with no parameter
Example: Parameterized Constructor
private Main() {
class Main {
i = 5;
System.out.println("Constructor is called");
String languages;
}
// constructor accepting single value
public static void main(String[] args) {
Main(String lang) {
languages = lang;
// calling the constructor without any parameter
System.out.println(languages + " Programming
Main obj = new Main();
Language");
System.out.println("Value of i: " + obj.i);
}
}
}
public static void main(String[] args) {
Output:
// call constructor by passing a single value
Constructor is called
Main obj1 = new Main("Java");
Value of i: 5
Main obj2 = new Main("Python");
Main obj3 = new Main("C");
In the above example, we have created a
}
constructor Main(). }
Here, the constructor does not accept any parameters.
Hence, it is known as a no-arg constructor. Output
Notice that we have declared the constructor as Java Programming Language
private. Python Programming Language
Once a constructor is declared private, it cannot be C Programming Language
accessed from outside the class.
So, creating objects from outside the class is prohibited In the above example, we have created a constructor
using the private constructor. named Main().
Here, we are creating the object inside the same class. Here, the constructor takes a single parameter. Notice
Hence, the program is able to access the constructor. the expression:
Main obj1 = new Main("Java");
However, if we want to create objects outside the
class, then we need to declare the constructor Here, we are passing the single value to the
as public. constructor.
Based on the argument passed, the language variable System.out.println("Default Value:");
is initialized inside the constructor. System.out.println("a = " + obj.a);
System.out.println("b = " + obj.b);
3. Java Default Constructor }
If we do not create any constructor, the Java compiler }
automatically creates a no-arg constructor during the
execution of the program. Output
This constructor is called the default constructor. Default Value:
Example: Default Constructor a=0
class Main { b = false

int a; Important Notes on Java Constructors


boolean b;  Constructors are invoked implicitly when you
instantiate objects.
public static void main(String[] args) {  The two rules for creating a constructor are:
1. The name of the constructor should be the same as
// calls default constructor the class.
Main obj = new Main(); 2. A Java constructor must not have a return type.
 If a class doesn't have a constructor, the Java compiler
System.out.println("Default Value:"); automatically creates a default constructor during
System.out.println("a = " + obj.a); run-time. The default constructor initializes instance
System.out.println("b = " + obj.b); variables with default values. For example,
} the int variable will be initialized to 0
}  Constructor types:
No-Arg Constructor - a constructor that does not
Output accept any arguments
Default Value: Parameterized constructor - a constructor that accepts
a=0 arguments
b = false Default Constructor - a constructor that is
automatically created by the Java compiler if it is not
Here, we haven't created any constructors. explicitly defined.
Hence, the Java compiler automatically creates the  A constructor cannot be abstract or static or final.
default constructor.  A constructor can be overloaded but can not be
The default constructor initializes any uninitialized overridden.
instance variables with default values. 
Type Default Value Constructors Overloading in Java
boolean false Similar to Java method overloading, we can also
byte 0 create two or more constructors with different
short 0 parameters. This is called constructor overloading.
int 0 Example: Java Constructor Overloading
long 0L class Main {
char \u0000
float 0.0f String language;
double 0.0d
object Reference null // constructor with no parameter
Main() {
In the above program, the variables a and b are this.language = "Java";
initialized with default value 0 and false respectively. }
The above program is equivalent to:
class Main { // constructor with a single parameter
Main(String language) {
int a; this.language = language;
boolean b; }

Main() { public void getName() {


a = 0; System.out.println("Programming Language: " +
b = false; this.language);
} }

public static void main(String[] args) { public static void main(String[] args) {
// call the constructor
Main obj = new Main(); // call constructor with no parameter
Main obj1 = new Main();
Static Methods
// call constructor with a single parameter Static methods are also called class methods. It is
Main obj2 = new Main("Python"); because a static method belongs to the class rather
than the object of a class.
obj1.getName(); And we can invoke static methods directly using the
obj2.getName(); class name. For example,
} class Test {
} // static method inside the Test class
public static void method() {...}
Output }
Programming Language: Java
Programming Language: Python class Main {
// invoking the static method
In the above example, we have two Test.method();
constructors: Main() and Main(String language). }
Here, both the constructors initialize the value of the Here, we can see that the static method can be
variable language with different values. accessed directly from other classes using the class
Based on the parameter passed during object creation, name.
different constructors are called, and different values In every Java program, we have declared
are assigned. the main method static. It is because to run the
It is also possible to call one constructor from another program the JVM should be able to invoke the main
constructor. method during the initial phase where no objects exist
in the memory.
Note: We have used this keyword to specify the Example 1: Java static and non-static Methods
variable of the class. class StaticTest {

Java Static Keyword // non-static method


int multiply(int a, int b){
What is a static keyword in Java?
return a * b;
In Java, if we want to access class members, we must
}
first create an instance of the class. But there will be
situations where we want to access class members
// static method
without creating any variables.
static int add(int a, int b){
In those situations, we can use the static keyword in
return a + b;
Java. If we want to access class members without
}
creating an instance of the class, we need to declare
}
the class members static.
The Math class in Java has almost all of its members
public class Main {
static. So, we can access its members without creating
instances of the Math class. For example,
public static void main( String[] args ) {
public class Main {
public static void main( String[] args ) {
// create an instance of the StaticTest class
StaticTest st = new StaticTest();
// accessing the methods of the Math class
System.out.println("Absolute value of -12 = " +
// call the nonstatic method
Math.abs(-12));
System.out.println(" 2 * 2 = " + st.multiply(2,2));
System.out.println("Value of PI = " + Math.PI);
System.out.println("Value of E = " + Math.E);
// call the static method
System.out.println("2^2 = " + Math.pow(2,2));
System.out.println(" 2 + 3 = " +
}
StaticTest.add(2,3));
}
}
}
Output:
Absolute value of -12 = 12
Output:
Value of PI = 3.141592653589793
2*2=4
Value of E = 2.718281828459045
2+3=5
2^2 = 4.0
In the above program, we have declared a non-static
In the above example, we have not created any
method named multiply() and a static method
instances of the Math class. But we are able to access
named add() inside the class StaticTest.
its methods: abs() and pow() and variables: PI and E.
Inside the Main class, we can see that we are calling
It is possible because the methods and variables of
the non-static method using the object of the class
the Math class are static.
(st.multiply(2, 2)). However, we are calling the static
method by using the class name (StaticTest.add(2, 3)).
Static Variables (obj.min + 1). However, we are calling the static
In Java, when we create objects of a class, then every variable by using the class name (Test.max + 1).
object will have its own copy of all the variables of the Note: Static variables are rarely used in Java. Instead,
class. For example, the static constants are used. These static constants are
class Test { defined by static final keyword and represented in
// regular variable uppercase. This is why some people prefer to use
int age; uppercase for static variables as well.
}
Access static Variables and Methods within the
class Main { Class
// create instances of Test We are accessing the static variable from another
Test test1 = new Test(); class. Hence, we have used the class name to access it.
Test test2 = new Test(); However, if we want to access the static member from
} inside the class, it can be accessed directly. For
Here, both the objects test1 and test2 will have example,
separate copies of the variable age. And, they are public class Main {
different from each other.
However, if we declare a variable static, all objects of // static variable
the class share the same static variable. It is because static int age;
like static methods, static variables are also associated // static method
with the class. And, we don't need to create objects of static void display() {
the class to access the static variables. For example, System.out.println("Static Method");
class Test { }
// static variable public static void main(String[] args) {
static int age;
} // access the static variable
class Main { age = 30;
// access the static variable System.out.println("Age is " + age);
Test.age = 20;
} // access the static method
Here, we can see that we are accessing the static display();
variable from the other class using the class name. }
Example 2: Java static and non-static Variables }
class Test { Output:
Age is 30
// static variable Static Method
static int max = 10; Here, we are able to access the static variable and
method directly without using the class name. It is
// non-static variable because static variables and methods are by default
int min = 5; public. And, since we are accessing from the same
} class, we don't have to specify the class name.

public class Main { Static Blocks


public static void main(String[] args) { In Java, static blocks are used to initialize the static
Test obj = new Test(); variables. For example,
class Test {
// access the non-static variable // static variable
System.out.println("min + 1 = " + (obj.min + 1)); static int age;

// access the static variable // static block


System.out.println("max + 1 = " + (Test.max + static {
1)); age = 23;
} }
} }
Here we can see that we have used a static block with
Output: the syntax:
min + 1 = 6 static {
max + 1 = 11 // variable initialization
In the above program, we have declared a non-static }
variable named min and a static variable The static block is executed only once when the class
named max inside the class Test. is loaded in memory. The class is loaded if either the
Inside the Main class, we can see that we are calling object of the class is requested in code or the static
the non-static variable using the object of the class members are requested in code.
A class can have multiple static blocks and each static
block is executed in the same sequence in which they // non-static nested class
have been written in a program. class InnerClass {...}
}
Example 3: Use of static block in java
class Main { Java Strings
In Java, a string is a sequence of characters. For
// static variables example, "hello" is a string containing a sequence of
static int a = 23;
characters 'h', 'e', 'l', 'l', and 'o'.
static int b;
static int max; We use double quotes to represent a string in Java.
For example,
// static blocks // create a string
static { String type = "Java programming";
System.out.println("First Static block.");
b = a * 4; Here, we have created a string variable named type.
} The variable is initialized with the string Java
static { Programming.
System.out.println("Second Static block.");
max = 30; Example: Create a String in Java
} class Main {
public static void main(String[] args) {
// static method
static void display() { // create strings
String first = "Java";
System.out.println("a = " + a); String second = "Python";
System.out.println("b = " + b); String third = "JavaScript";
System.out.println("max = " + max);
} // print strings
System.out.println(first); // print Java
public static void main(String args[]) { System.out.println(second); // print Python
// calling the static method System.out.println(third); // print JavaScript
display(); }
} }
}
In the above example, we have created three strings
Output: named first, second, and third.
First Static block. Here, we are directly creating strings like primitive
Second Static block. types.
a = 23 However, there is another way of creating Java strings
b = 92 (using the new keyword).
max = 30
We will learn about that later in this tutorial.
In the above program. as soon as the Main class is
Note: Strings in Java are not primitive types
loaded,
(like int, char, etc). Instead, all strings are objects of a
The value of a is set to 23.
The first static block is executed. Hence, the predefined class named String.
string First Static block is printed and the value of b is And all string variables are instances of
set to a * 4. the String class.
The second static block is executed. Hence, the
string Second Static block is printed and the value Java String Operations
of max is set to 30. Java provides various string methods to perform
And finally, the print statements inside the different operations on strings. We will look into some
method display() are executed. of the commonly used string operations.

Nested Static Class 1. Get the Length of a String


In Java, we can declare a class inside another class. To find the length of a string, we use
Such classes are known as nested classes. Nested the length() method. For example,
classes are of 2 types: class Main {
Static Nested Classes public static void main(String[] args) {
Non-static Nested Classes
For example, // create a string
class OuterClass { String greet = "Hello! World";
// static nested class System.out.println("String: " + greet);
static class NestedClass {...}
String second = "java programming";
// get the length of greet String third = "python programming";
int length = greet.length();
// compare first and second strings
System.out.println("Length: " + length); boolean result1 = first.equals(second);
}
} System.out.println("Strings first and second are
equal: " + result1);
Output
String: Hello! World // compare first and third strings
Length: 12 boolean result2 = first.equals(third);

In the above example, the length() method calculates System.out.println("Strings first and third are equal:
the total number of characters in the string and returns " + result2);
it. }
}

2. Join Two Java Strings Output


We can join two strings in Java using Strings first and second are equal: true
the concat() method. For example, Strings first and third are equal: false
class Main {
public static void main(String[] args) { In the above example, we have created 3 strings
named first, second, and third.
// create first string Here, we are using the equal() method to check if one
String first = "Java "; string is equal to another.
System.out.println("First String: " + first); The equals() method checks the content of strings
while comparing them.
// create second
String second = "Programming"; Note: We can also compare two strings using
System.out.println("Second String: " + second); the == operator in Java. However, this approach is
different than the equals() method.
// join two strings
String joinedString = first.concat(second);
Escape Character in Java Strings
System.out.println("Joined String: " + joinedString); The escape character is used to escape some of the
} characters present inside a string.
} Suppose we need to include double quotes inside a
string.
Output // include double quote
First String: Java String example = "This is the "String" class";
Second String: Programming
Joined String: Java Programming Since strings are represented by double quotes, the
compiler will treat "This is the " as the string. Hence,
In the above example, we have created two strings
the above code will cause an error.
named first and second. Notice the statement,
To solve this issue, we use the escape character \ in
String joinedString = first.concat(second);
Java. For example,
// use the escape character
Here, the concat() method joins the second string to
String example = "This is the \"String\" class.";
the first string and assigns it to
the joinedString variable. Now escape characters tell the compiler to
We can also join two strings using the + operator in escape double quotes and read the whole text.
Java.
Java Strings are Immutable
In Java, strings are immutable. This means once we
3. Compare Two Strings create a string, we cannot change that string.
In Java, we can make comparisons between two To understand it more thoroughly, consider an
strings using the equals() method. For example, example:
class Main { // create a string
public static void main(String[] args) { String example = "Hello! ";

// create 3 strings
String first = "java programming";
Here, we have created a string variable Here, we are directly providing the value of the string
named example. The variable holds the string "Hello! (Java). Hence, the compiler first checks the string pool
". to see if the string already exists.
Now, suppose we want to change the string.  If the string already exists, the new string is not
// add another string "World" created. Instead, the new reference, example points to
// to the previous tring example the already existing string (Java).
example = example.concat(" World");  If the string doesn't exist, a new string (Java) is
created.
Here, we are using the concat() method to add 2. While creating strings using the new keyword,
another string "World" to the previous string. String example = new String("Java");
It looks like we are able to change the value of the
previous string. However, this is not true. Here, the value of the string is not directly provided.
Let's see what has happened here: Hence, a new "Java" string is created even
1. JVM takes the first string "Hello! " though "Java" is already present inside the memory
2. creates a new string by adding "World" to the first pool.
string
3. assigns the new string "Hello! World" to Methods of Java String
the example variable Besides those mentioned above, there are
various string methods present in Java. Here are some
4. The first string "Hello! " remains unchanged
of those methods:
Creating Strings Using the New Keyword
Methods Description
So far, we have created strings like primitive types in
contains() Checks whether the string
Java.
contains a substring.
Since strings in Java are objects, we can create strings
substring() Returns the substring of the
using the new keyword as well. For example,
string.
// create a string using the new keyword
join() Joins the given strings using
String name = new String("Java String");
the delimiter.
replace() Replaces the specified old
In the above example, we have created a
character with the specified
string name using the new keyword. new character.
Here, when we create a string object, replaceAll() Replaces all substrings
the String() constructor is invoked. matching the regex pattern.
replaceFirst() Replaces the first matching
Note: The String class provides various other substring.
constructors to create strings. charAt() Returns the character present
in the specified location.
getBytes() Converts the string to an array
Example: Create Java Strings Using the New of bytes.
Keyword indexOf() Returns the position of the
class Main { specified character in the
public static void main(String[] args) { string.
compareTo() Compares two strings in the
// create a string using new dictionary order.
String name = new String("Java String"); compareToIgn Compares two strings, ignoring
oreCase() case differences.
trim() Removes any leading and
System.out.println(name); // print Java String trailing whitespaces.
} format() Returns a formatted string.
} split() Breaks the string into an array
of strings.
Create String Using Literals vs. New Keyword toLowerCase() Converts the string to
Now that we know how strings are created lowercase.
using string literals and the new keyword, let's see toUpperCase() Converts the string to
what is the major difference between them. uppercase.
In Java, the JVM maintains a string pool to store all valueOf() Returns the string
of its strings inside the memory. The string pool helps representation of the specified
in reusing the strings. argument.
1. While creating strings using string literals, toCharArray() Converts the string to a char
String example = "Java"; array.
matches() Checks whether the string
matches the given regex.
startsWith() Checks if the string begins with void message(){
the given string. System.out.println("This is a message");
endsWith() Checks if the string ends with }
the given string. }
isEmpty() Checks whether a string is
empty or not. Here, the Logger class has the default access modifier.
intern() Returns the canonical And the class is visible to all the classes that belong to
representation of the string. the defaultPackage package. However, if we try to use
contentEquals() Checks whether the string is the Logger class in another class outside of
equal to charSequence. defaultPackage, we will get a compilation error.
hashCode() Returns a hash code for the
string. Private Access Modifier
subSequence() Returns a subsequence from When variables and methods are declared private,
the string. they cannot be accessed outside of the class. For
example,
class Data {
Java Access Modifiers // private variable
What are Access Modifiers? private String name;
In Java, access modifiers are used to set the }
accessibility (visibility)
of classes, interfaces, variables, methods, constructors, public class Main {
data members, and the setter methods. For example, public static void main(String[] main){
class Animal {
public void method1() {...} // create an object of Data
Data d = new Data();
private void method2() {...}
} // access private variable and field from another
class
In the above example, we have declared 2 methods: d.name = "Programiz";
method1() and method2(). Here, }
 method1 is public - This means it can be accessed by }
other classes.
 method2 is private - This means it can not be In the above example, we have declared a private
accessed by other classes. variable named name. When we run the program, we
Note the keyword public and private. These are will get the following error:
access modifiers in Java. They are also known as Main.java:18: error: name has private access in Data
visibility modifiers. d.name = "Programiz";
^

Note: You cannot set the access modifier of getters The error is generated because we are trying to access
methods. the private variable of the Data class from
the Main class.
Types of Access Modifier You might be wondering what if we need to access
Before you learn about types of access modifiers, make those private variables. In this case, we can use the
sure you know about Java Packages. getters and setters method. For example,
There are four access modifiers keywords in Java and class Data {
they are: private String name;
Modifier Description
Default declarations are visible only within // getter method
the package (package private) public String getName() {
Private declarations are visible within the return this.name;
class only }
Protected declarations are visible within the // setter method
package or all subclasses public void setName(String name) {
Public declarations are visible everywhere this.name= name;
}
Default Access Modifier }
If we do not explicitly specify any access modifier for public class Main {
classes, methods, variables, etc, then by default the public static void main(String[] main){
default access modifier is considered. For example, Data d = new Data();
package defaultPackage;
class Logger { // access the private variable using the getter and
setter
d.setName("Programiz"); Note: We cannot declare classes or
System.out.println(d.getName()); interfaces protected in Java.
}
}
Public Access Modifier
Output: When methods, variables, classes, and so on are
The name is Programiz declared public, then we can access them from
anywhere. The public access modifier has no scope
In the above example, we have a private variable restriction. For example,
named name. In order to access the variable from the // Animal.java file
outer class, we have used // public class
methods: getName() and setName(). These methods public class Animal {
are called getter and setter in Java. // public variable
Here, we have used the setter method (setName()) to public int legCount;
assign value to the variable and the getter method
(getName()) to access the variable. // public method
public void display() {
We have used this keyword inside the setName() to
System.out.println("I am an animal.");
refer to the variable of the class.
System.out.println("I have " + legCount + "
legs.");
}
Note: We cannot declare classes and interfaces private
}
in Java. However, the nested classes can be declared
private. // Main.java
public class Main {
public static void main( String[] args ) {
Protected Access Modifier // accessing the public class
When methods and data members are Animal animal = new Animal();
declared protected, we can access them within the
same package as well as from subclasses. For example, // accessing the public variable
class Animal { animal.legCount = 4;
// protected method // accessing the public method
protected void display() { animal.display();
System.out.println("I am an animal"); }
} }
}
Output:
class Dog extends Animal { I am an animal.
public static void main(String[] args) { I have 4 legs.

// create an object of Dog class Here,


Dog dog = new Dog();  The public class Animal is accessed from
// access protected method the Main class.
dog.display();
 The public variable legCount is accessed from
}
} the Main class.
 The public method display() is accessed from
Output: the Main class.
I am an animal

In the above example, we have a protected method


named display() inside the Animal class.
The Animal class is inherited by the Dog class

We then created an object dog of the Dog class.


Using the object we tried to access the protected
method of the parent class.
Since protected methods can be accessed from the
child classes, we are able to access the method
of Animal class from the Dog class.
Access Modifiers Summarized in one figure // parameter
MyClass(int age){
age = age;
}
}

In the above program, the instance variable and the


parameter have the same name: age. Here, the Java
compiler is confused due to name ambiguity.
In such a situation, we use this keyword. For example,
First, let's see an example without using this keyword:
class Main {

int age;
Main(int age){
age = age;
}

Accessibility of all Access Modifiers in Java public static void main(String[] args) {
Main obj = new Main(8);
System.out.println("obj.age = " + obj.age);
Java this Keyword }
In Java, this keyword is used to refer to the current }
object inside a method or a constructor. For example,
class Main { Output:
int instVar; obj.age = 0
Main(int instVar){
In the above example, we have passed 8 as a value to
this.instVar = instVar;
System.out.println("this reference = " + this); the constructor. However, we are getting 0 as an
} output. This is because the Java compiler gets
confused because of the ambiguity in names between
public static void main(String[] args) { instance the variable and the parameter.
Main obj = new Main(8); Now, let's rewrite the above code using this keyword.
System.out.println("object reference = " + obj); class Main {
}
} int age;
Main(int age){
Output: this.age = age;
this reference = Main@23fc625e }
object reference = Main@23fc625e
public static void main(String[] args) {
In the above example, we created an object Main obj = new Main(8);
named obj of the class Main. We then print the System.out.println("obj.age = " + obj.age);
reference to the object obj and this keyword of the }
}
class.
Here, we can see that the reference of
Output:
both obj and this is the same. It means this is nothing
obj.age = 8
but the reference to the current object.
Now, we are getting the expected output. It is because
Use of this Keyword
when the constructor is called, this inside the
There are various situations where this keyword is
constructor is replaced by the object obj that has
commonly used.
1. Using this for Ambiguity Variable Names called the constructor. Hence the age variable is
In Java, it is not allowed to declare two or assigned value 8.
more variables having the same name inside a scope Also, if the name of the parameter and instance
(class scope or method scope). However, instance variable is different, the compiler automatically
variables and parameters may have the same name. appends this keyword. For example, the code:
For example, class Main {
class MyClass { int age;
// instance variable
int age; Main(int i) {
age = i; private Complex(int i){
} // invokes the constructor with 2 parameters
} this(i, i);
}
is equivalent to:
class Main { // constructor with no parameter
int age; private Complex(){
// invokes the constructor with single parameter
Main(int i) { this(0);
this.age = i; }
}
} @Override
public String toString(){
2. this with Getters and Setters return this.a + " + " + this.b + "i";
Another common use of this keyword is in setters and }
getters methods of a class. For example:
class Main { public static void main( String[] args ) {
String name;
// creating object of Complex class
// setter method // calls the constructor with 2 parameters
void setName( String name ) { Complex c1 = new Complex(2, 3);
this.name = name;
} // calls the constructor with a single parameter
Complex c2 = new Complex(3);
// getter method
String getName(){ // calls the constructor with no parameters
return this.name; Complex c3 = new Complex();
}
// print objects
public static void main( String[] args ) { System.out.println(c1);
Main obj = new Main(); System.out.println(c2);
System.out.println(c3);
// calling the setter and the getter method }
obj.setName("Toshiba"); }
System.out.println("obj.name: "+obj.getName());
} Output:
} 2 + 3i
3 + 3i
Output: 0 + 0i
obj.name: Toshiba
Here, we have used this keyword: In the above example, we have used this keyword,
 to assign value inside the setter method  to call the constructor Complex(int i, int j) from the
 to access value inside the getter method constructor Complex(int i)
  to call the constructor Complex(int i) from the
3. Using this in Constructor Overloading constructor Complex()
While working with constructor overloading, we Notice the line,
might have to invoke one constructor from another System.out.println(c1);
constructor. In such a case, we cannot call the
constructor explicitly. Instead, we have to
Here, when we print the object c1, the object is
use this keyword.
converted into a string. In this process, the toString() is
Here, we use a different form of this keyword. That
called. Since we override the toString() method inside
is, this(). Let's take an example,
our class, we get the output according to that method.
class Complex {
One of the huge advantages of this() is to reduce the
private int a, b; amount of duplicate code. However, we should be
always careful while using this().
// constructor with 2 parameters This is because calling constructor from another
private Complex( int i, int j ){ constructor adds overhead and it is a slow process.
this.a = i; Another huge advantage of using this() is to reduce
this.b = j; the amount of duplicate code.
}

// constructor with single parameter


Note: Invoking one constructor from another Java final keyword
constructor is called explicit constructor invocation. In Java, the final keyword is used to denote constants.
It can be used with variables, methods, and classes.
Once any entity (variable, method or class) is
Passing this as an Argument declared final, it can be assigned only once. That is,
We can use this keyword to pass the current object as  the final variable cannot be reinitialized with another
an argument to a method. For example, value
class ThisExample {  the final method cannot be overridden
// declare variables  the final class cannot be extended
int x;
int y; 1. Java final Variable
In Java, we cannot change the value of a final
ThisExample(int x, int y) { variable. For example,
// assign values of variables inside constructor class Main {
this.x = x; public static void main(String[] args) {
this.y = y;
// create a final variable
// value of x and y before calling add() final int AGE = 32;
System.out.println("Before passing this to
addTwo() method:"); // try to change the final variable
System.out.println("x = " + this.x + ", y = " + AGE = 45;
this.y); System.out.println("Age: " + AGE);
}
// call the add() method passing this as argument }
add(this);
In the above program, we have created a final variable
// value of x and y after calling add()
named age. And we have tried to change the value of
System.out.println("After passing this to
the final variable.
addTwo() method:");
When we run the program, we will get a compilation
System.out.println("x = " + this.x + ", y = " +
error with the following message.
this.y);
cannot assign a value to final variable AGE
}
AGE = 45;
^
void add(ThisExample o){
Note: It is recommended to use uppercase to declare
o.x += 2;
o.y += 2; final variables in Java.
}
}
2. Java final Method
class Main { Before you learn about final methods and final classes,
public static void main( String[] args ) { make sure you know about the Java Inheritance.
ThisExample obj = new ThisExample(1, -2); In Java, the final method cannot be overridden by the
} child class. For example,
} class FinalDemo {
// create a final method
Output: public final void display() {
Before passing this to addTwo() method: System.out.println("This is a final method.");
x = 1, y = -2 }
After passing this to addTwo() method: }
x = 3, y = 0
class Main extends FinalDemo {
In the above example, inside the // try to override final method
constructor ThisExample(), notice the line, public final void display() {
add(this); System.out.println("The final method is
overridden.");
}
Here, we are calling the add() method by passing this
as an argument. Since this keyword contains the
public static void main(String[] args) {
reference to the object obj of the class, we can change Main obj = new Main();
the value of x and y inside the add() method. obj.display();
}
}
In the above example, we have created a final method
named display() inside the FinalDemo class. Here, Working of Java Recursion
the Main class inherits the FinalDemo class. In the above example, we have called
We have tried to override the final method in the recurse() method from inside the main method
the Main class. When we run the program, we will get (normal method call). And, inside the recurse()
a compilation error with the following message. method, we are again calling the same recurse
display() in Main cannot override display() in method. This is a recursive call.
FinalDemo In order to stop the recursive call, we need to provide
public final void display() { some conditions inside the method. Otherwise, the
^ method will be called infinitely.
overridden method is final Hence, we use the if...else statement (or similar
approach) to terminate the recursive call inside the
3. Java final Class method.
In Java, the final class cannot be inherited by another
class. For example, Example: Factorial of a Number Using Recursion
// create a final class class Factorial {
final class FinalClass {
public void display() { static int factorial( int n ) {
System.out.println("This is a final method."); if (n != 0) // termination condition
} return n * factorial(n-1); // recursive call
} else
return 1;}
// try to extend the final class public static void main(String[] args) {
class Main extends FinalClass { int number = 4, result;
public void display() { result = factorial(number);
System.out.println("The final method is System.out.println(number + " factorial = " +
overridden."); result);
} }}

public static void main(String[] args) { Output:


Main obj = new Main(); 4 factorial = 24
obj.display();
} In the above example, we have a method
} named factorial(). The factorial() is called from
the main() method with the number variable passed
In the above example, we have created a final class as an argument.
named FinalClass. Here, we have tried to inherit the Here, notice the statement,
final class by the Main class. return n * factorial(n-1);
When we run the program, we will get a compilation
error with the following message. The factorial() method is calling itself. Initially, the
cannot inherit from final FinalClass value of n is 4 inside factorial(). During the next
class Main extends FinalClass { recursive call, 3 is passed to the factorial() method.
^ This process continues until n is equal to 0.
When n is equal to 0, the if statement returns false
Java Recursion hence 1 is returned. Finally, the accumulated result is
In Java, a method that calls itself is known as a passed to the main() method.
recursive method. And, this process is known as
recursion. Working of Factorial Program
A physical world example would be to place two The image below will give you a better idea of how the
parallel mirrors facing each other. Any object in factorial program is executed using recursion.
between them would be reflected recursively.

How Recursion works?


Here, if objectName is an instance of className,
the operator returns true. Otherwise, it returns false.

Example: Java instanceof


class Main {

public static void main(String[] args) {

// create a variable of string type


String name = "Programiz";

// checks if name is instance of String


boolean result1 = name instanceof String;
System.out.println("name is an instance of String: "
+ result1);

// create an object of Main


Main obj = new Main();

// checks if obj is an instance of Main


boolean result2 = obj instanceof Main;
System.out.println("obj is an instance of Main: " +
result2);
}
}

Output
name is an instance of String: true
obj is an instance of Main: true

In the above example, we have created a


variable name of the String type and an object obj of
the Main class.
Here, we have used the instanceof operator to check
whether name and obj are instances of
the String and Main class respectively. And, the
operator returns true in both cases.

Note: In Java, String is a class rather than a primitive


data type.

Advantages and Disadvantages of Recursion Java instanceof during Inheritance


When a recursive call is made, new storage locations
for variables are allocated on the stack. As, each We can use the instanceof operator to check if objects
recursive call returns, the old variables and parameters of the subclass is also an instance of the superclass.
are removed from the stack. Hence, recursion For example,
generally uses more memory and is generally slow. // Java Program to check if an object of the subclass
On the other hand, a recursive solution is much // is also an instance of the superclass
simpler and takes less time to write, debug and
maintain. // superclass
class Animal {
}
Java instanceof Operator
// subclass
The instanceof operator in Java is used to check
class Dog extends Animal {
whether an object is an instance of a particular class or }
not.
Its syntax is class Main {
objectName instanceOf className; public static void main(String[] args) {
// create an object of the subclass Note: In Java, all the classes are inherited from
Dog d1 = new Dog(); the Object class. So, instances of all the classes are
also an instance of the Object class.
// checks if d1 is an instance of the subclass In the previous example, if we check,
System.out.println(d1 instanceof Dog); // d1 instanceof Object
prints true
The result will be true.
// checks if d1 is an instance of the superclass
System.out.println(d1 instanceof Animal); //
prints true
} Java OOP(II)
}

In the above example, we have created a


subclass Dog that inherits from the
Java Inheritance
Inheritance is one of the key features of OOP that
superclass Animal. We have created an object d1 of
allows us to create a new class from an existing class.
the Dog class. The new class that is created is known
Inside the print statement, notice the expression, as subclass (child or derived class) and the existing
d1 instanceof Animal class from where the child class is derived is known
as superclass (parent or base class).
Here, we are using the instanceof operator to check The extends keyword is used to perform inheritance in
whether d1 is also an instance of the Java. For example,
superclass Animal. class Animal {
// methods and fields
Java instanceof in Interface }
The instanceof operator is also used to check whether
an object of a class is also an instance of the interface // use of extends keyword
implemented by the class. For example, // to perform inheritance
// Java program to check if an object of a class is also class Dog extends Animal {
// an instance of the interface implemented by the
class // methods and fields of Animal
// methods and fields of Dog
interface Animal { }
}
In the above example, the Dog class is created by
class Dog implements Animal { inheriting the methods and fields from
} the Animal class.
Here, Dog is the subclass and Animal is the
class Main { superclass.
public static void main(String[] args) {
Example 1: Java Inheritance
// create an object of the Dog class class Animal {
Dog d1 = new Dog();
// field and method of the parent class
// checks if the object of Dog String name;
// is also an instance of Animal public void eat() {
System.out.println(d1 instanceof Animal); // System.out.println("I can eat");
returns true }
} }
}
// inherit from Animal
In the above example, the Dog class implements class Dog extends Animal {
the Animal interface. Inside the print statement,
notice the expression, // new method in subclass
d1 instanceof Animal public void display() {
System.out.println("My name is " + name);
Here, d1 is an instance of Dog class. }
The instanceof operator checks if d1 is also an }
instance of the interface Animal.
class Main {
public static void main(String[] args) {
// create an object of the subclass In this case, the method in the subclass overrides the
Dog labrador = new Dog(); method in the superclass. This concept is known as
method overriding in Java.
// access field of superclass Example 2: Method overriding in Java Inheritance
labrador.name = "Rohu"; class Animal {
labrador.display();
// method in the superclass
// call method of superclass public void eat() {
// using object of subclass System.out.println("I can eat");
labrador.eat(); }
}
}
} // Dog inherits Animal
class Dog extends Animal {
Output
My name is Rohu // overriding the eat() method
I can eat @Override
public void eat() {
In the above example, we have derived a System.out.println("I eat dog food");
subclass Dog from superclass Animal. Notice the }
statements,
labrador.name = "Rohu"; // new method in subclass
labrador.eat(); public void bark() {
System.out.println("I can bark");
Here, labrador is an object of Dog. }
However, name and eat() are the members of }
the Animal class.
class Main {
Since Dog inherits the field and method public static void main(String[] args) {
from Animal, we are able to access the field and
method using the object of the Dog. // create an object of the subclass
Dog labrador = new Dog();

// call the eat() method


labrador.eat();
labrador.bark();
}
}

Output
I eat dog food
I can bark

In the above example, the eat() method is present in


Java Inheritance Implementation both the superclass Animal and the subclass Dog.
Here, we have created an object labrador of Dog.
is-a relationship
Now when we call eat() using the object labrador, the
In Java, inheritance is an is-a relationship. That is, we
use inheritance only if there exists an is-a relationship method inside Dog is called. This is because the
between two classes. For example, method inside the derived class overrides the method
 Car is a Vehicle inside the base class.
 Orange is a Fruit This is called method overriding.
 Surgeon is a Doctor
 Dog is an Animal
Here, Car can inherit from Vehicle, Orange can Note: We have used the @Override annotation to tell
inherit from Fruit, and so on. the compiler that we are overriding a method.
However, the annotation is not mandatory.
Method Overriding in Java Inheritance
In Example 1, we see the object of the subclass can
access the method of the superclass. super Keyword in Java Inheritance
Previously we saw that the same method in the
However, if the same method is present in both the subclass overrides the method in superclass.
superclass and subclass, what will happen?
In such a situation, the super keyword is used to call
the method of the parent class from the method of the protected Members in Inheritance
child class. In Java, if a class includes protected fields and
methods, then these fields and methods are accessible
Example 3: super Keyword in Inheritance from the subclass of the class.
class Animal {
Example 4: protected Members in Inheritance
// method in the superclass class Animal {
public void eat() { protected String name;
System.out.println("I can eat");
} protected void display() {
} System.out.println("I am an animal.");
}
// Dog inherits Animal }
class Dog extends Animal {
class Dog extends Animal {
// overriding the eat() method
@Override public void getInfo() {
public void eat() { System.out.println("My name is " + name);
}
// call method of superclass }
super.eat();
System.out.println("I eat dog food"); class Main {
} public static void main(String[] args) {

// new method in subclass // create an object of the subclass


public void bark() { Dog labrador = new Dog();
System.out.println("I can bark");
} // access protected field and method
} // using the object of subclass
labrador.name = "Rocky";
class Main { labrador.display();
public static void main(String[] args) {
labrador.getInfo();
// create an object of the subclass }
Dog labrador = new Dog(); }

// call the eat() method Output


labrador.eat(); I am an animal.
labrador.bark(); My name is Rocky
}
} In the above example, we have created a class named
Animal. The class includes a protected
Output field: name and a method: display().
I can eat We have inherited the Dog class inherits Animal.
I eat dog food Notice the statement,
I can bark labrador.name = "Rocky";
labrador.display();
In the above example, the eat() method is present in
both the base class Animal and the derived class Dog. Here, we are able to access the protected field and
Notice the statement, method of the superclass using the labrador object of
super.eat(); the subclass.

Here, the super keyword is used to call Why use inheritance?


the eat() method present in the superclass.  The most important use of inheritance in Java is code
We can also use the super keyword to call reusability. The code that is present in the parent class
the constructor of the superclass from the constructor can be directly used by the child class.
of the subclass.  Method overriding is also known as runtime
polymorphism. Hence, we can achieve Polymorphism
in Java with the help of inheritance.

Types of inheritance
There are five types of inheritance.
1. Single Inheritance 4. Multiple Inheritance
In single inheritance, a single subclass extends from a In multiple inheritance, a single subclass extends from
single superclass. For example, multiple superclasses. For example,

Java Single Inheritance


Java Multiple Inheritance
2. Multilevel Inheritance
In multilevel inheritance, a subclass extends from a
Note: Java doesn't support multiple inheritance.
superclass and then the same subclass acts as a
superclass for another class. For example, However, we can achieve multiple inheritance using
interfaces.

5. Hybrid Inheritance
Hybrid inheritance is a combination of two or more
types of inheritance. For example,

Java Multilevel Inheritance


Java Hybrid Inheritance
3. Hierarchical Inheritance
In hierarchical inheritance, multiple subclasses extend Here, we have combined hierarchical and multiple
from a single superclass. For example, inheritance to form a hybrid inheritance.

Java Method Overriding


In the last tutorial, we learned about inheritance.
Inheritance is an OOP property that allows us to
derive a new class (subclass) from an existing class
(superclass). The subclass inherits the attributes and
methods of the superclass.
Now, if the same method is defined in both the
superclass and the subclass, then the method of the
subclass class overrides the method of the superclass.
This is known as method overriding.
Java Hierarchical Inheritance

Example 1: Method Overriding super Keyword in Java Overriding
class Animal { A common question that arises while performing
public void displayInfo() { overriding in Java is:
System.out.println("I am an animal."); Can we access the method of the superclass after
} overriding?
} Well, the answer is Yes. To access the method of the
superclass from the subclass, we use
class Dog extends Animal { the super keyword.
@Override Example 2: Use of super Keyword
public void displayInfo() { class Animal {
System.out.println("I am a dog."); public void displayInfo() {
} System.out.println("I am an animal.");
} }
}
class Main {
public static void main(String[] args) { class Dog extends Animal {
Dog d1 = new Dog(); public void displayInfo() {
d1.displayInfo(); super.displayInfo();
} System.out.println("I am a dog.");
} }
}
Output:
I am a dog. class Main {
public static void main(String[] args) {
In the above program, the displayInfo() method is Dog d1 = new Dog();
present in both the Animal superclass and d1.displayInfo();
the Dog subclass. }
When we call displayInfo() using the d1 object (object }
of the subclass), the method inside the subclass Dog is
Output:
called. The displayInfo() method of the subclass I am an animal.
overrides the same method of the superclass. I am a dog.

In the above example, the subclass Dog overrides the


method displayInfo() of the superclass Animal.
When we call the method displayInfo() using
the d1 object of the Dog subclass, the method inside
the Dog subclass is called; the method inside the
superclass is not called.
Inside displayInfo() of the Dog subclass, we have
used super.displayInfo() to call displayInfo() of the
superclass.
Notice the use of the @Override annotation in our
example. In Java, annotations are the metadata that It is important to note that constructors in Java are not
we used to provide information to the compiler. Here, inherited. Hence, there is no such thing as constructor
the @Override annotation specifies the compiler that overriding in Java.
the method after this annotation overrides the method However, we can call the constructor of the superclass
of the superclass. from its subclasses. For that, we use super().
It is not mandatory to use @Override. However,
when we use this, the method should follow all the Access Specifiers in Method Overriding
rules of overriding. Otherwise, the compiler will The same method declared in the superclass and its
generate an error. subclasses can have different access specifiers.
However, there is a restriction.
Java Overriding Rules We can only use those access specifiers in subclasses
 Both the superclass and the subclass must have the that provide larger access than the access specifier of
same method name, the same return type and the the superclass. For example,
same parameter list. Suppose, a method myClass() in the superclass is
 We cannot override the method declared declared protected. Then, the same
as final and static. method myClass() in the subclass can be
 We should always override abstract methods of the either public or protected, but not private.
superclass (will be discussed in later tutorials).
overrides the method in the superclass. This is
Example 3: Access Specifier in Overriding called method overriding.
class Animal { Example 1: Method overriding
protected void displayInfo() { class Animal {
System.out.println("I am an animal.");
} // overridden method
} public void display(){
System.out.println("I am an animal");
class Dog extends Animal { }
public void displayInfo() { }
System.out.println("I am a dog.");
} class Dog extends Animal {
}
// overriding method
class Main { @Override
public static void main(String[] args) { public void display(){
Dog d1 = new Dog(); System.out.println("I am a dog");
d1.displayInfo(); }
}
} public void printMessage(){
display();
Output: }
I am a dog. }

In the above example, the subclass Dog overrides the class Main {
method displayInfo() of the superclass Animal. public static void main(String[] args) {
Dog dog1 = new Dog();
Whenever we call displayInfo() using the d1 (object
dog1.printMessage();
of the subclass), the method inside the subclass is
}
called.
}
Notice that, the displayInfo() is declared protected in
the Animal superclass. The same method has Output
the public access specifier in the Dog subclass. This is I am a dog
possible because the public provides larger access than
the protected. In this example, by making an
object dog1 of Dog class, we can call its
Overriding Abstract Methods method printMessage() which then executes
In Java, abstract classes are created to be the the display() statement.
superclass of other classes. And, if a class contains an Since display() is defined in both the classes, the
abstract method, it is mandatory to override it. method of subclass Dog overrides the method of
We will learn more about abstract classes and
superclass Animal. Hence, the display() of the
overriding of abstract methods in later tutorials.
subclass is called.
Java super
The super keyword in Java is used in subclasses to
access superclass members
(attributes, constructors and methods).

Uses of super keyword


1. To call methods of the superclass that is overridden in
the subclass.
2. To access attributes (fields) of the superclass if both
superclass and subclass have attributes with the same
name.
3. To explicitly call superclass no-arg (default) or
parameterized constructor from the subclass
constructor.
Let's understand each of these uses.
What if the overridden method of the superclass has
1. Access Overridden Methods of the superclass to be called?
If methods with the same name are defined in both
superclass and subclass, the method in the subclass
We use super.display() if the overridden Example 3: Access superclass attribute
method display() of superclass Animal needs to be class Animal {
called. protected String type="animal";
Example 2: super to Call Superclass Method }
class Animal {
class Dog extends Animal {
// overridden method public String type="mammal";
public void display(){
System.out.println("I am an animal"); public void printType() {
} System.out.println("I am a " + type);
} System.out.println("I am an " + super.type);
}
class Dog extends Animal { }

// overriding method class Main {


@Override public static void main(String[] args) {
public void display(){ Dog dog1 = new Dog();
System.out.println("I am a dog"); dog1.printType();
} }
}
public void printMessage(){
Output:
// this calls overriding method I am a mammal
display(); I am an animal

// this calls overridden method In this example, we have defined the same instance
super.display(); field type in both the superclass Animal and the
} subclass Dog.
} We then created an object dog1 of the Dog class.
Then, the printType() method is called using this
class Main { object.
public static void main(String[] args) { Inside the printType() function,
Dog dog1 = new Dog();
dog1.printMessage();  type refers to the attribute of the subclass Dog.
}  super.type refers to the attribute of the superclass
} Animal.
Hence, System.out.println("I am a " + type); prints I
Output am a mammal. And, System.out.println("I am an " +
I am a dog super.type); prints I am an animal.
I am an animal
3. Use of super() to access superclass constructor
Here, how the above program works. As we know, when an object of a class is created, its
default constructor is automatically called.
To explicitly call the superclass constructor from the
subclass constructor, we use super(). It's a special form
of the super keyword.
super() can be used only inside the subclass
constructor and must be the first statement.

Example 4: Use of super()


class Animal {

// default or no-arg constructor of class Animal


Animal() {
System.out.println("I am an animal");
}
}
2. Access Attributes of the Superclass
The superclass and subclass can have attributes with class Dog extends Animal {
the same name. We use the super keyword to access
// default or no-arg constructor of class Dog
the attribute of the superclass.
Dog() {
// calling default constructor of the superclass Example 5: Call Parameterized Constructor Using
super(); super()
class Animal {
System.out.println("I am a dog");
} // default or no-arg constructor
} Animal() {
System.out.println("I am an animal");
class Main { }
public static void main(String[] args) {
Dog dog1 = new Dog(); // parameterized constructor
} Animal(String type) {
} System.out.println("Type: "+type);
}
Output }
I am an animal
I am a dog class Dog extends Animal {

Here, when an object dog1 of Dog class is created, it // default constructor


automatically calls the default or no-arg constructor of Dog() {
that class.
Inside the subclass constructor, the super() statement // calling parameterized constructor of the
calls the constructor of the superclass and executes the superclass
statements inside it. Hence, we get the output I am an super("Animal");
animal.
System.out.println("I am a dog");
}
}

class Main {
public static void main(String[] args) {
Dog dog1 = new Dog();
}
}

Output
Type: Animal
I am a dog

The compiler can automatically call the no-arg


constructor. However, it cannot call parameterized
constructors.
If a parameterized constructor has to be called, we
need to explicitly define it in the subclass constructor.
The flow of the program then returns back to the
subclass constructor and executes the remaining
statements. Thus, I am a dog will be printed.
However, using super() is not compulsory. Even
if super() is not used in the subclass constructor, the
compiler implicitly calls the default constructor of the
superclass.

So, why use redundant code if the compiler


automatically invokes super()?
It is required if the parameterized constructor (a
constructor that takes arguments) of the superclass
has to be called from the subclass constructor.
The parameterized super() must always be the first
statement in the body of the constructor of the
subclass, otherwise, we get a compilation error.

Note that in the above example, we explicitly called


the parameterized constructor super("Animal"). The
compiler does not call the default constructor of the System.out.println("This is Java Programming");
superclass in this case. }
}

Java Abstract Class and Abstract Methods class Main extends Language {
Java Abstract Class public static void main(String[] args) {
The abstract class in Java cannot be instantiated (we
cannot create objects of abstract classes). We use // create an object of Main
the abstract keyword to declare an abstract class. For Main obj = new Main();
example,
// create an abstract class // access method of abstract class
abstract class Language { // using object of Main class
// fields and methods obj.display();
} }
... }

// try to create an object Language Output


// throws an error This is Java programming
Language obj = new Language();
In the above example, we have created an abstract
An abstract class can have both the regular methods class named Language. The class contains a regular
and abstract methods. For example,
method display().
abstract class Language {
We have created the Main class that inherits the
// abstract method abstract class. Notice the statement,
abstract void method1(); obj.display();

// regular method Here, obj is the object of the child class Main. We are
void method2() { calling the method of the abstract class using the
System.out.println("This is regular method"); object obj.
}
} Implementing Abstract Methods
If the abstract class includes any abstract method, then
all the child classes inherited from the abstract
Java Abstract Method superclass must provide the implementation of the
A method that doesn't have its body is known as an abstract method. For example,
abstract method. We use the same abstract keyword abstract class Animal {
to create abstract methods. For example, abstract void makeSound();
abstract void display();
public void eat() {
Here, display() is an abstract method. The body System.out.println("I can eat.");
}
of display() is replaced by ;.
}
If a class contains an abstract method, then the class
should be declared abstract. Otherwise, it will generate class Dog extends Animal {
an error. For example,
// error // provide implementation of abstract method
// class should be abstract public void makeSound() {
class Language { System.out.println("Bark bark");
}
// abstract method }
abstract void method1();
} class Main {
public static void main(String[] args) {
Example: Java Abstract Class and Method
Though abstract classes cannot be instantiated, we can // create an object of Dog class
create subclasses from it. We can then access members Dog d1 = new Dog();
of the abstract class using the object of the subclass.
For example, d1.makeSound();
abstract class Language { d1.eat();
}
// method of abstract class }
public void display() {
Output brake differently for different motorbikes, however,
Bark bark what brake does will be the same.
I can eat. Let's take an example that helps us to better
understand Java abstraction.
In the above example, we have created an abstract
class Animal. The class contains an abstract Example 3: Java Abstraction
method makeSound() and a non-abstract abstract class MotorBike {
method eat(). abstract void brake();
}
We have inherited a subclass Dog from the
superclass Animal. Here, the subclass Dog provides class SportsBike extends MotorBike {
the implementation for the abstract
method makeSound(). // implementation of abstract method
We then used the object d1 of the Dog class to call public void brake() {
methods makeSound() and eat(). System.out.println("SportsBike Brake");
}
}
Note: If the Dog class doesn't provide the
implementation of the abstract class MountainBike extends MotorBike {
method makeSound(), Dog should also be declared as
// implementation of abstract method
abstract. This is because the public void brake() {
subclass Dog inherits makeSound() from Animal. System.out.println("MountainBike Brake");
}
}
Accesses Constructor of Abstract Classes
An abstract class can have constructors like the regular class Main {
class. And, we can access the constructor of an public static void main(String[] args) {
abstract class from the subclass using MountainBike m1 = new MountainBike();
the super keyword. For example, m1.brake();
abstract class Animal { SportsBike s1 = new SportsBike();
Animal() { s1.brake();
…. }
} }
}
Output:
class Dog extends Animal { MountainBike Brake
Dog() { SportsBike Brake
super();
... In the above example, we have created an abstract
} super class MotorBike. The superclass MotorBike has
} an abstract method brake().
The brake() method cannot be implemented
Here, we have used the super() inside the constructor
inside MotorBike. It is because every bike has
of Dog to access the constructor of the Animal.
different implementation of brakes. So, all the
Note that the super should always be the first subclasses of MotorBike would have different
statement of the subclass constructor.
implementation of brake().
Java Abstraction So, the implementation of brake() in MotorBike is
The major use of abstract classes and methods is to kept hidden.
achieve abstraction in Java. Here, MountainBike makes its own implementation
Abstraction is an important concept of object-oriented of brake() and SportsBike makes its own
programming that allows us to hide unnecessary implementation of brake().
details and only show the needed information.
This allows us to manage complexity by omitting or Note: We can also use interfaces to achieve
hiding details with a simpler, higher-level idea.
abstraction in Java.
A practical example of abstraction can be motorbike
brakes. We know what brake does. When we apply
the brake, the motorbike will stop. However, the Key Points to Remember
working of the brake is kept hidden from us.  We use the abstract keyword to create abstract classes
The major advantage of hiding the working of the and methods.
brake is that now the manufacturer can implement  An abstract method doesn't have any implementation
(method body).
 A class containing abstract methods should also be In the above example, we have created an interface
abstract. named Polygon. The interface contains an abstract
 We cannot create objects of an abstract class. method getArea().
 To implement features of an abstract class, we inherit Here, the Rectangle class implements Polygon. And,
subclasses from it and create objects of the subclass.
provides the implementation of the getArea() method.
 A subclass must override all abstract methods of an
abstract class. However, if the subclass is declared
abstract, it's not mandatory to override abstract Example 2: Java Interface
methods. // create an interface
 We can access the static attributes and methods of an interface Language {
abstract class using the reference of the abstract class. void getName(String name);
For example, }
Animal.staticMethod();
// class implements interface
class ProgrammingLanguage implements Language {
Java Interface // implementation of abstract method
An interface is a fully abstract class. It includes a public void getName(String name) {
group of abstract methods (methods without a body). System.out.println("Programming Language: " +
We use the interface keyword to create an interface in name);
Java. For example, }
interface Language { }
public void getType();
class Main {
public void getVersion(); public static void main(String[] args) {
} ProgrammingLanguage language = new
ProgrammingLanguage();
Here, language.getName("Java");
 Language is an interface. }
 It includes abstract }
methods: getType() and getVersion().
Output
Implementing an Interface Programming Language: Java
Like abstract classes, we cannot create objects of In the above example, we have created an interface
interfaces. named Language. The interface includes an abstract
To use an interface, other classes must implement it. method getName().
We use the implements keyword to implement an Here, the ProgrammingLanguage class implements
interface. the interface and provides the implementation for the
method.
Example 1: Java Interface
interface Polygon { Implementing Multiple Interfaces
void getArea(int length, int breadth); In Java, a class can also implement multiple interfaces.
} For example,
interface A {
// implement the Polygon interface // members of A
class Rectangle implements Polygon { }

// implementation of abstract method interface B {


public void getArea(int length, int breadth) { // members of B
System.out.println("The area of the rectangle is " + }
(length * breadth));
} class C implements A, B {
} // abstract members of A
// abstract members of B
class Main { }
public static void main(String[] args) {
Rectangle r1 = new Rectangle(); Extending an Interface
r1.getArea(5, 6); Similar to classes, interfaces can extend other
} interfaces. The extends keyword is used for extending
} interfaces. For example,
interface Line {
Output // members of Line interface
The area of the rectangle is 30 }
// extending interface Here, the class Rectangle is implementing two
interface Polygon extends Line { different interfaces. This is how we achieve multiple
// members of Polygon interface inheritance in Java.
// members of Line interface Note: All the methods inside an interface are
} implicitly public and all fields are implicitly public
static final. For example,
Here, the Polygon interface extends interface Language {
the Line interface. Now, if any class
implements Polygon, it should provide // by default public static final
implementations for all the abstract methods of String type = "programming language";
both Line and Polygon.
// by default public
Extending Multiple Interfaces void getName();
An interface can extend multiple interfaces. For }
example,
interface A { default methods in Java Interfaces
... With the release of Java 8, we can now add methods
} with implementation inside an interface. These
interface B { methods are called default methods.
... To declare default methods inside interfaces, we use
} the default keyword. For example,
public default void getSides() {
interface C extends A, B { // body of getSides()
... }
}
Why default methods?
Advantages of Interface in Java Let's take a scenario to understand why default
methods are introduced in Java.
Now that we know what interfaces are, let's learn Suppose, we need to add a new method in an
about why interfaces are used in Java. interface.
 Similar to abstract classes, interfaces help us to We can add the method in our interface easily without
achieve abstraction in Java. implementation. However, that's not the end of the
story. All our classes that implement that interface
Here, we know getArea() calculates the area of must provide an implementation for the method.
polygons, but the way area is calculated is different for If a large number of classes were implementing this
different polygons. Hence, the implementation interface, we need to track all these classes and make
of getArea() is independent of one another. changes to them. This is not only tedious but error-
 Interfaces provide specifications that a class (which prone as well.
implements it) must follow. To resolve this, Java introduced default methods.
Default methods are inherited like ordinary methods.
Let's take an example to have a better understanding
In our previous example, we used getArea() as a
of default methods.
specification inside the interface Polygon. This is like
setting a rule that we should be able to get the area of Example: Default Method in Java Interface
every polygon. interface Polygon {
void getArea();
Now any class that implements the Polygon interface
must provide an implementation for // default method
the getArea() method. default void getSides() {
 Interfaces are also used to achieve multiple System.out.println("I can get sides of a polygon.");
inheritance in Java. For example, }
interface Line { }

} // implements the interface
class Rectangle implements Polygon {
interface Polygon { public void getArea() {
… int length = 6;
} int breadth = 5;
int area = length * breadth;
class Rectangle implements Line, Polygon { System.out.println("The area of the rectangle is " +
… area);
} }
}
// overrides the getSides()
public void getSides() { // access static method
System.out.println("I have 4 sides."); Polygon.staticMethod();
}
} Note: With the release of Java 9, private methods are
also supported in interfaces.
// implements the interface We cannot create objects of an interface. Hence,
class Square implements Polygon { private methods are used as helper methods that
public void getArea() { provide support to other methods in interfaces.
int length = 5;
int area = length * length; Practical Example of Interface
System.out.println("The area of the square is " + Let's see a more practical example of Java Interface.
area); // To use the sqrt function
} import java.lang.Math;
}
interface Polygon {
class Main { void getArea();
public static void main(String[] args) {
// calculate the perimeter of a Polygon
// create an object of Rectangle default void getPerimeter(int... sides) {
Rectangle r1 = new Rectangle(); int perimeter = 0;
r1.getArea(); for (int side: sides) {
r1.getSides(); perimeter += side;
}
// create an object of Square
Square s1 = new Square(); System.out.println("Perimeter: " + perimeter);
s1.getArea(); }
s1.getSides(); }
}
} class Triangle implements Polygon {
private int a, b, c;
Output private double s, area;
The area of the rectangle is 30
I have 4 sides. // initializing sides of a triangle
The area of the square is 25 Triangle(int a, int b, int c) {
I can get sides of a polygon. this.a = a;
this.b = b;
In the above example, we have created an interface this.c = c;
named Polygon. It has a default s = 0;
method getSides() and an abstract method getArea(). }
Here, we have created two
classes, Rectangle and Square, that // calculate the area of a triangle
public void getArea() {
implement Polygon.
s = (double) (a + b + c)/2;
The Rectangle class provides the implementation of area = Math.sqrt(s*(s-a)*(s-b)*(s-c));
the getArea() method and overrides System.out.println("Area: " + area);
the getSides() method. However, the Square class }
only provides the implementation of }
the getArea() method.
Now, while calling the getSides() method using class Main {
public static void main(String[] args) {
the Rectangle object, the overridden method is called.
Triangle t1 = new Triangle(2, 3, 4);
However, in the case of the Square object, the default
method is called. // calls the method of the Triangle class
t1.getArea();
private and static Methods in Interface
The Java 8 also added another feature to include static // calls the method of Polygon
methods inside an interface. t1.getPerimeter(2, 3, 4);
Similar to a class, we can access static methods of an }
interface using its references. For example, }
// create an interface
interface Polygon { Output
staticMethod(){..} Area: 2.9047375096555625
Perimeter: 9 Output
Rendering Square...
In the above program, we have created an interface Rendering Circle...
named Polygon. It includes a default
method getPerimeter() and an abstract In the above example, we have created a
method getArea(). superclass: Polygon and two
We can calculate the perimeter of all polygons in the subclasses: Square and Circle. Notice the use of
same manner so we implemented the body the render() method.
of getPerimeter() in Polygon. The main purpose of the render() method is to render
Now, all polygons that implement Polygon can the shape. However, the process of rendering a square
use getPerimeter() to calculate perimeter. is different than the process of rendering a circle.
However, the rule for calculating the area is different Hence, the render() method behaves differently in
for different polygons. Hence, getArea() is included different classes. Or, we can say render() is
without implementation. polymorphic.
Any class that implements Polygon must provide an
implementation of getArea(). Why Polymorphism?
Polymorphism allows us to create consistent code. In
the previous example, we can also create different
Java Polymorphism methods: renderSquare() and renderCircle() to
Polymorphism is an important concept of object-
render Square and Circle, respectively.
oriented programming. It simply means more than
one form. This will work perfectly. However, for every shape, we
That is, the same entity (method or operator or object) need to create different methods. It will make our code
can perform different operations in different scenarios. inconsistent.
To solve this, polymorphism in Java allows us to
Example: Java Polymorphism create a single method render() that will behave
class Polygon { differently for different shapes.

// method to render a shape


public void render() { Note: The print() method is also an example of
System.out.println("Rendering Polygon..."); polymorphism. It is used to print values of different
} types like char, int, string, etc.
}

class Square extends Polygon { We can achieve polymorphism in Java using the
following ways:
// renders Square 1. Method Overriding
public void render() { 2. Method Overloading
System.out.println("Rendering Square..."); 3. Operator Overloading
}
} 1. Java Method Overriding
During inheritance in Java, if the same method is
class Circle extends Polygon { present in both the superclass and the subclass. Then,
the method in the subclass overrides the same method
// renders circle in the superclass. This is called method overriding.
public void render() { In this case, the same method will perform one
System.out.println("Rendering Circle..."); operation in the superclass and another operation in
} the subclass. For example,
} Example 1: Polymorphism using method overriding
class Language {
class Main { public void displayInfo() {
public static void main(String[] args) { System.out.println("Common English Language");
}
// create an object of Square }
Square s1 = new Square();
s1.render(); class Java extends Language {
@Override
// create an object of Circle public void displayInfo() {
Circle c1 = new Circle(); System.out.println("Java Programming Language");
c1.render(); }
} }
}
class Main {
public static void main(String[] args) { // method with single parameter
public void display(char symbol) {
// create an object of Java class for (int i = 0; i < 10; i++) {
Java j1 = new Java(); System.out.print(symbol);
j1.displayInfo(); }
}
// create an object of Language class }
Language l1 = new Language();
l1.displayInfo(); class Main {
} public static void main(String[] args) {
} Pattern d1 = new Pattern();

Output: // call method without any argument


Java Programming Language d1.display();
Common English Language System.out.println("\n");

In the above example, we have created a superclass // call method with a single argument
named Language and a subclass named Java. Here, d1.display('#');
the method displayInfo() is present in }
both Language and Java. }Output:
**********
The use of displayInfo() is to print the information.
However, it is printing different information ##########
in Language and Java.
Based on the object used to call the method, the In the above example, we have created a class
corresponding information is printed. named Pattern. The class contains a method
named display() that is overloaded.
// method with no arguments
display() {...}

// method with a single char type argument


display(char symbol) {...}
Here, the main function of display() is to print the
pattern. However, based on the arguments passed, the
method is performing different operations:
Working of Java Polymorphism  prints a pattern of *, if no argument is passed or
 prints pattern of the parameter, if a single char type
Note: The method that is called is determined during argument is passed.
the execution of the program. Hence, method
overriding is a run-time polymorphism. Note: The method that is called is determined by the
compiler. Hence, it is also known as compile-time
polymorphism.
2. Java Method Overloading
In a Java class, we can create methods with the same
name if they differ in parameters. For example, 3. Java Operator Overloading
void func() { ... } Some operators in Java behave differently with
void func(int a) { ... } different operands. For example,
float func(double a) { ... }  + operator is overloaded to perform numeric addition
float func(int a, float b) { ... } as well as string concatenation, and
This is known as method overloading in Java. Here,  operators like &, |, and ! are overloaded for logical
the same method will perform different operations and bitwise operations.
based on the parameter. Let's see how we can achieve polymorphism using
Example 3: Polymorphism using method operator overloading.
overloading The + operator is used to add two entities. However,
class Pattern { in Java, the + operator performs two operations.
1. When + is used with numbers (integers and
// method without parameter
public void display() { floating-point numbers), it performs mathematical
for (int i = 0; i < 10; i++) { addition. For example,
System.out.print("*"); int a = 5;
} int b = 6;
}
// + with numbers
int sum = a + b; // Output = 11 In the above example, we have created an object
2. When we use the + operator with strings, it will variable pl of the ProgrammingLanguage class.
perform string concatenation (join two strings). For Here, pl is a polymorphic variable. This is because,
example,  In statement pl = new
String first = "Java "; ProgrammingLanguage(), pl refer to the object of
String second = "Programming"; the ProgrammingLanguage class.
 And, in statement pl = new Java(), pl refer to the
// + with strings object of the Java class.
name = first + second; // Output = Java
Programming Java Encapsulation
Here, we can see that the + operator is overloaded in Java Encapsulation
Java to perform two Encapsulation is one of the key features of object-
operations: addition and concatenation. oriented programming. Encapsulation refers to the
bundling of fields and methods inside a single class.
It prevents outer classes from accessing and changing
Note: In languages like C++, we can define operators fields and methods of a class. This also helps to
to work differently for different operands. However, achieve data hiding.
Java doesn't support user-defined operator
overloading. Example 1: Java Encapsulation
class Area {

Polymorphic Variables // fields to calculate area


A variable is called polymorphic if it refers to different int length;
values under different conditions. int breadth;
Object variables (instance variables) represent the
behavior of polymorphic variables in Java. It is // constructor to initialize values
because object variables of a class can refer to objects Area(int length, int breadth) {
of its class as well as objects of its subclasses. this.length = length;
Example: Polymorphic Variables this.breadth = breadth;
class ProgrammingLanguage { }
public void display() {
System.out.println("I am Programming // method to calculate area
Language."); public void getArea() {
} int area = length * breadth;
} System.out.println("Area: " + area);
}
class Java extends ProgrammingLanguage { }
@Override
public void display() { class Main {
System.out.println("I am Object-Oriented public static void main(String[] args) {
Programming Language.");
} // create object of Area
} // pass value of length and breadth
Area rectangle = new Area(5, 6);
class Main { rectangle.getArea();
public static void main(String[] args) { }
}
// declare an object variable
ProgrammingLanguage pl; Output
Area: 30
// create object of ProgrammingLanguage In the above example, we have created a class
pl = new ProgrammingLanguage(); named Area. The main purpose of this class is to
pl.display(); calculate the area.
To calculate an area, we need
// create object of Java class two variables: length and breadth and a
pl = new Java(); method: getArea(). Hence, we bundled these fields
pl.display(); and methods inside a single class.
} Here, the fields and methods can be accessed from
} other classes as well. Hence, this is not data hiding.
This is only encapsulation. We are just keeping
Output: similar codes together.
I am Programming Language. Note: People often consider encapsulation as data
I am Object-Oriented Programming Language. hiding, but that's not entirely true.
Encapsulation refers to the bundling of related fields // setter method
and methods together. This can be used to achieve public void setAge(int age) {
data hiding. Encapsulation in itself is not data hiding. this.age = age;
}
Why Encapsulation? }
 In Java, encapsulation helps us to keep related fields
and methods together, which makes our code cleaner class Main {
and easy to read. public static void main(String[] args) {
 It helps to control the values of our data fields. For
example, // create an object of Person
class Person { Person p1 = new Person();
private int age;
// change age using setter
public void setAge(int age) { p1.setAge(24);
if (age >= 0) {
this.age = age; // access age using getter
} System.out.println("My age is " + p1.getAge());
} }
} }

Here, we are making the age variable private and Output


applying logic inside the setAge() method. My age is 24
Now, age cannot be negative. In the above example, we have a private field age.
 The getter and setter methods provide read- Since it is private, it cannot be accessed from outside
only or write-only access to our class fields. For the class.
example, In order to access age, we have
getName() // provides read-only access used public methods: getAge() and setAge(). These
setName() // provides write-only access methods are called getter and setter methods.
Making age private allowed us to restrict
 It helps to decouple components of a system. For unauthorized access from outside the class. This
example, we can encapsulate code into multiple is data hiding.
bundles. If we try to access the age field from the Main class,
we will get an error.
These decoupled components (bundle) can be
// error: age has private access in Person
developed, tested, and debugged independently and
p1.age = 24;
concurrently. And, any changes in a particular
component do not have any effect on other
components.
 We can also achieve data hiding using encapsulation. Java Nested and Inner Class
In the above example, if we change the length and In Java, you can define a class within another class.
breadth variable into private, then the access to these Such class is known as nested class. For example,
fields is restricted. class OuterClass {
// ...
And, they are kept hidden from outer classes. This is class NestedClass {
called data hiding. // ...
 }
Data Hiding }
Data hiding is a way of restricting the access of our
data members by hiding the implementation details. There are two types of nested classes you can create in
Encapsulation also provides a way for data hiding. Java.
We can use access modifiers to achieve data hiding.  Non-static nested class (inner class)
For example,  Static nested class
Example 2: Data hiding using the private specifier Let's first look at non-static nested classes.
class Person {
Non-Static Nested Class (Inner Class)
// private field A non-static nested class is a class within another
private int age; class. It has access to members of the enclosing class
(outer class). It is commonly known as inner class.
// getter method Since the inner class exists within the outer class, you
public int getAge() { must instantiate the outer class first, in order to
return age; instantiate the inner class.
} Here's an example of how you can declare inner
classes in Java.
Example 1: Inner class CPU.Processor processor = cpu.new Processor;
class CPU {
double price; CPU.RAM ram = cpu.new RAM();
// nested class
class Processor{
Note: We use the dot (.) operator to create an instance
// members of nested class of the inner class using the outer class.
double cores;
String manufacturer;

double getCache(){ Accessing Members of Outer Class within Inner


return 4.3; Class
} We can access the members of the outer class by using
} this keyword.

// nested protected class Example 2: Accessing Members


protected class RAM{ class Car {
String carName;
// members of protected nested class String carType;
double memory;
String manufacturer; // assign values using constructor
public Car(String name, String type) {
double getClockSpeed(){ this.carName = name;
return 5.5; this.carType = type;
} }
}
} // private method
private String getCarName() {
public class Main { return this.carName;
public static void main(String[] args) { }

// create object of Outer class CPU // inner class


CPU cpu = new CPU(); class Engine {
String engineType;
// create an object of inner class Processor using void setEngine() {
outer class
CPU.Processor processor = cpu.new Processor(); // Accessing the carType property of Car
if(Car.this.carType.equals("4WD")){
// create an object of inner class RAM using
outer class CPU // Invoking method getCarName() of Car
CPU.RAM ram = cpu.new RAM(); if(Car.this.getCarName().equals("Crysler"))
System.out.println("Processor Cache = " + {
processor.getCache()); this.engineType = "Smaller";
System.out.println("Ram Clock speed = " + } else {
ram.getClockSpeed()); this.engineType = "Bigger";
} }
}
}else{
Output: this.engineType = "Bigger";
Processor Cache = 4.3 }
Ram Clock speed = 5.5 }
String getEngineType(){
In the above program, there are two nested return this.engineType;
classes: Processor and RAM inside the outer }
}
class: CPU. We can declare the inner class as
}
protected. Hence, we have declared the RAM class as
protected. public class Main {
Inside the Main class, public static void main(String[] args) {
 we first created an instance of an outer
class CPU named cpu. // create an object of the outer class Car
 Using the instance of the outer class, we then created Car car1 = new Car("Mazda", "8WD");
objects of inner classes:
// create an object of inner class using the outer }
class
Car.Engine engine = car1.new Engine(); }
engine.setEngine(); public class Main {
System.out.println("Engine Type for 8WD= " + public static void main(String[] args) {
engine.getEngineType());
// create an object of the static nested class
Car car2 = new Car("Crysler", "4WD"); // using the name of the outer class
Car.Engine c2engine = car2.new Engine(); MotherBoard.USB usb = new
c2engine.setEngine(); MotherBoard.USB();
System.out.println("Engine Type for 4WD = " + System.out.println("Total Ports = " +
c2engine.getEngineType()); usb.getTotalPorts());
} }
} }

Output: Output:
Engine Type for 8WD= Bigger Total Ports = 3
Engine Type for 4WD = Smaller In the above program, we have created a static class
named USB inside the class MotherBoard. Notice the
In the above program, we have the inner class line,
named Engine inside the outer class Car. Here, notice MotherBoard.USB usb = new MotherBoard.USB();
the line, Here, we are creating an object of USB using the
if(Car.this.carType.equals("4WD")) {...} name of the outer class.
We are using this keyword to access Now, let's see what would happen if you try to access
the carType variable of the outer class. You may have the members of the outer class:
noticed that instead of using this.carType we have
used Car.this.carType. Example 4: Accessing members of Outer class inside
It is because if we had not mentioned the name of the Static Inner Class
class MotherBoard {
outer class Car, then this keyword will represent the
String model;
member inside the inner class. public MotherBoard(String model) {
Similarly, we are also accessing the method of the this.model = model;
outer class from the inner class. }
if (Car.this.getCarName().equals("Crysler") {...}
It is important to note that, although // static nested class
the getCarName() is a private method, we are able to static class USB{
access it from the inner class. int usb2 = 2;
int usb3 = 1;
Static Nested Class int getTotalPorts(){
In Java, we can also define a static class inside // accessing the variable model of the outer
another class. Such class is known as static nested classs
class. Static nested classes are not called static inner if(MotherBoard.this.model.equals("MSI")) {
classes. return 4;
Unlike inner class, a static nested class cannot access }
the member variables of the outer class. It is because else {
the static nested class doesn't require you to create an return usb2 + usb3;
instance of the outer class. }
OuterClass.NestedClass obj = new }
OuterClass.NestedClass(); }
Here, we are creating an object of the static nested }
class by simply using the class name of the outer class. public class Main {
Hence, the outer class cannot be referenced public static void main(String[] args) {
using OuterClass.this.
// create an object of the static nested class
Example 3: Static Inner Class
MotherBoard.USB usb = new
class MotherBoard {
MotherBoard.USB();
System.out.println("Total Ports = " +
// static nested class
usb.getTotalPorts());
static class USB{
}
int usb2 = 2;
}
int usb3 = 1;
int getTotalPorts(){
When we try to run the program, we will get an error:
return usb2 + usb3;
}
error: non-static variable this cannot be referenced }
from a static context }
This is because we are not using the object of the outer
class to create an object of the inner class. Hence, there // static class
is no reference to the outer class Motherboard stored static class Mammal {
in Motherboard.this. public void displayInfo() {
System.out.println("I am a mammal.");
Key Points to Remember }
 Java treats the inner class as a regular member of a }
class. They are just like methods and variables }
declared inside a class.
 Since inner classes are members of the outer class, you class Main {
can apply any access modifiers public static void main(String[] args) {
// object creation of the outer class
like private, protected to your inner class which is not
Animal animal = new Animal();
possible in normal classes.
 Since the nested class is a member of its enclosing
// object creation of the non-static class
outer class, you can use the dot (.) notation to access Animal.Reptile reptile = animal.new Reptile();
the nested class and its members. reptile.displayInfo();
 Using the nested class will make your code more
readable and provide better encapsulation. // object creation of the static nested class
 Non-static nested classes (inner classes) have access to Animal.Mammal mammal = new
other members of the outer/enclosing class, even if Animal.Mammal();
they are declared private. mammal.displayInfo();

Java Nested Static Class }


As learned in previous tutorials, we can have a class }
inside another class in Java. Such classes are known as
nested classes. In Java, nested classes are of two types: Output
 Nested non-static class (Inner class) I am a reptile.
 Nested static class. I am a mammal.

In this tutorial, we will learn about nested static In the above program, we have two nested
classes. class Mammal and Reptile inside a class Animal.
AD
Java Nested Static Class To create an object of the non-static class Reptile, we
We use the keyword static to make our nested class have used
static. Animal.Reptile reptile = animal.new Reptile()
To create an object of the static class Mammal, we
Note: In Java, only nested classes are allowed to be have used
static. Animal.Mammal mammal = new Animal.Mammal()

Like regular classes, static nested classes can include Accessing Members of Outer Class
both static and non-static fields and methods. For In Java, static nested classes are associated with the
example, outer class. This is why static nested classes can only
Class Animal { access the class members (static fields and methods) of
static class Mammal { the outer class.
// static and non-static members of Mammal Let's see what will happen if we try to access non-
} static fields and methods of the outer class.
// members of Animal
} Example: Accessing Non-static members
Static nested classes are associated with the outer class Animal {
class. static class Mammal {
To access the static nested class, we don't need objects public void displayInfo() {
of the outer class. System.out.println("I am a mammal.");
}
Example: Static Nested Class }
class Animal {
class Reptile {
// inner class public void displayInfo() {
class Reptile { System.out.println("I am a reptile.");
public void displayInfo() { }
System.out.println("I am a reptile."); }
Java Anonymous Class
public void eat() { In Java, a class can contain another class known as
System.out.println("I eat food."); nested class. It's possible to create a nested class
} without giving any name.
} A nested class that doesn't have any name is known as
an anonymous class.
class Main { An anonymous class must be defined inside another
public static void main(String[] args) { class. Hence, it is also known as an anonymous inner
Animal animal = new Animal(); class. Its syntax is:
Animal.Reptile reptile = animal.new Reptile(); class outerClass {
reptile.displayInfo();
// defining anonymous class
Animal.Mammal mammal = new object1 = new Type(parameterList) {
Animal.Mammal(); // body of the anonymous class
mammal.displayInfo(); };
mammal.eat(); }
}
} Anonymous classes usually extend subclasses or
implement interfaces.
Output Here, Type can be
Main.java:28: error: cannot find symbol 1. a superclass that an anonymous class extends
mammal.eat(); 2. an interface that an anonymous class implements
^ The above code creates an object, object1, of an
symbol: method eat()
anonymous class at runtime.
location: variable mammal of type Mammal
1 error
compiler exit status 1 Note: Anonymous classes are defined inside an
expression. So, the semicolon is used at the end of
In the above example, we have created a non-static
method eat() inside the class Animal. anonymous classes to indicate the end of the
Now, if we try to access eat() using the expression.
object mammal, the compiler shows an error.
It is because mammal is an object of a static class and Example 1: Anonymous Class Extending a Class
we cannot access non-static methods from static class Polygon {
classes. public void display() {
System.out.println("Inside the Polygon class");
Static Top-level Class }
As mentioned above, only nested classes can be static. }
We cannot have static top-level classes.
Let's see what will happen if we try to make a top-level class AnonymousDemo {
class static. public void createClass() {
static class Animal {
public static void displayInfo() { // creation of anonymous class extending class
System.out.println("I am an animal"); Polygon
} Polygon p1 = new Polygon() {
} public void display() {
System.out.println("Inside an anonymous
class Main { class.");
public static void main(String[] args) { }
Animal.displayInfo(); };
} p1.display();
} }
}
Output
Main.java:1: error: modifier static not allowed here class Main {
static class Animal { public static void main(String[] args) {
^ AnonymousDemo an = new AnonymousDemo();
1 error an.createClass();
compiler exit status 1 }
In the above example, we have tried to create a static }
class Animal. Since Java doesn't allow static top-level
class, we will get an error. Output
Inside an anonymous class.
In the above example, we have created a Java Singleton Class
class Polygon. It has a single method display().
We then created an anonymous class that extends the In Java, Singleton is a design pattern that ensures that
class Polygon and overrides the display() method. a class can only have one object.
When we run the program, an object p1 of the To create a singleton class, a class must implement the
anonymous class is created. The object then calls following properties:
the display() method of the anonymous class.  Create a private constructor of the class to restrict
object creation outside of the class.
Example 2: Anonymous Class Implementing an  Create a private attribute of the class type that refers
Interface to the single object.
interface Polygon {  Create a public static method that allows us to create
public void display(); and access the object we created. Inside the method,
} we will create a condition that restricts us from
creating more than one object.
class AnonymousDemo { 
public void createClass() { Example: Java Singleton Class Syntax
class SingletonExample {
// anonymous class implementing interface
Polygon p1 = new Polygon() { // private field that refers to the object
public void display() { private static SingletonExample singleObject;
System.out.println("Inside an anonymous
class."); private SingletonExample() {
} // constructor of the SingletonExample class
}; }
p1.display();
} public static SingletonExample getInstance() {
} // write code that allows us to create only one
object
class Main { // access the object as per our need
public static void main(String[] args) { }
AnonymousDemo an = new AnonymousDemo(); }
an.createClass(); In the above example,
}
 private static SingletonExample singleObject - a
}
reference to the object of the class.
Output  private SingletonExample() - a
Inside an anonymous class. private constructor that restricts creating objects
In the above example, we have created an anonymous outside of the class.
class that implements the Polygon interface.  public static SingletonExample getInstance() - this
method returns the reference to the only object of the
Advantages of Anonymous Classes class. Since the method static, it can be accessed using
In anonymous classes, objects are created whenever the class name.
they are required. That is, objects are created to
perform some specific tasks. For example, Use of Singleton in Java
Object = new Example() { Singletons can be used while working with databases.
public void display() { They can be used to create a connection pool to access
System.out.println("Anonymous class overrides the database while reusing the same connection for all
the method display()."); the clients. For example,
} class Database {
}; private static Database dbObject;
Here, an object of the anonymous class is created
dynamically when we need to override private Database() {
the display() method. }
Anonymous classes also help us to make our code
concise. public static Database getInstance() {

// create object if it's not already created


if(dbObject == null) {
dbObject = new Database();
}

// returns the singleton object


return dbObject;
} SMALL, MEDIUM, LARGE, EXTRALARGE
}
public void getConnection() {
System.out.println("You are now connected to the class Main {
database."); public static void main(String[] args) {
} System.out.println(Size.SMALL);
} System.out.println(Size.MEDIUM);
}
class Main { }
public static void main(String[] args) {
Database db1; Output
SMALL
// refers to the only object of Database MEDIUM
db1= Database.getInstance(); As we can see from the above example, we use the
enum name to access the constant values.
db1.getConnection(); Also, we can create variables of enum types. For
} example,
} Size pizzaSize;
Here, pizzaSize is a variable of the Size type. It can
When we run the program, the output will be: only be assigned with 4 values.
You are now connected to the database. pizzaSize = Size.SMALL;
In our above example, pizzaSize = Size.MEDIUM;
 We have created a singleton class Database. pizzaSize = Size.LARGE;
 The dbObject is a class type field. This will refer to the pizzaSize = Size.EXTRALARGE;
object of the class Database.
 The private constructor Database() prevents object Example 2: Java Enum with the switch statement
creation outside of the class. enum Size {
 The static class type method getInstance() returns the SMALL, MEDIUM, LARGE, EXTRALARGE
instance of the class to the outside world. }
 In the Main class, we have class type variable db1. We
are calling getInstance() using db1 to get the only class Test {
object of the Database. Size pizzaSize;
 The method getConnection() can only be accessed public Test(Size pizzaSize) {
using the object of the Database. this.pizzaSize = pizzaSize;
 Since the Database can have only one object, all the }
clients can access the database through a single public void orderPizza() {
connection. switch(pizzaSize) {
 case SMALL:
Singleton is a design pattern rather than a feature System.out.println("I ordered a small size pizza.");
specific to Java. A design pattern is like our code break;
library that includes various coding techniques shared case MEDIUM:
by programmers around the world. System.out.println("I ordered a medium size
pizza.");
break;
Java enums default:
System.out.println("I don't know which one to
In Java, an enum (short for enumeration) is a type that
order.");
has a fixed set of constant values. We use
break;
the enum keyword to declare enums. For example, }
enum Size { }
SMALL, MEDIUM, LARGE, EXTRALARGE }
}
Here, we have created an enum named Size. It class Main {
contains fixed values SMALL, MEDIUM, LARGE, public static void main(String[] args) {
and EXTRALARGE. Test t1 = new Test(Size.MEDIUM);
These values inside the braces are called enum t1.orderPizza();
constants (values). }
}
Note: The enum constants are usually represented in
uppercase. Output
I ordered a medium size pizza.
Example 1: Java Enum
enum Size {
In the above program, we have created an enum
type Size. We then declared a variable pizzaSize of Output
the Size type. The size of the pizza is small
Here, the variable pizzaSize can only be assigned with In the above example, we have created an enum
4 values class Size. It has four
(SMALL, MEDIUM, LARGE, EXTRALARGE). constants SMALL, MEDIUM, LARGE and EXTR
Notice the statement, ALARGE.
Test t1 = new Test(Size.MEDIUM); Since Size is an enum class, the compiler
It will call the Test() constructor inside the Test class. automatically creates instances for each enum
Now, the variable pizzaSize is assigned with constants.
the MEDIUM constant. Here inside the main() method, we have used the
Based on the value, one of the cases of the switch case instance SMALL to call the getSize() method.
statement is executed.
Note: Like regular classes, an enum class also may
Enum Class in Java include constructors.
In Java, enum types are considered to be a special type
of class. It was introduced with the release of Java 5.
An enum class can include methods and fields just like Methods of Java Enum Class
regular classes. There are some predefined methods in enum classes
enum Size { that are readily available for use.
constant1, constant2, …, constantN; 1. Java Enum ordinal()
The ordinal() method returns the position of an enum
// methods and fields constant. For example,
} ordinal(SMALL)
When we create an enum class, the compiler will // returns 0
create instances (objects) of each enum constants.
Also, all enum constant is always public static final by 2. Enum compareTo()
default. The compareTo() method compares the enum
constants based on their ordinal value. For example,
Example 3: Java Enum Class Size.SMALL.compareTo(Size.MEDIUM)
enum Size{ // returns ordinal(SMALL) - ordinal(MEDIUM)
SMALL, MEDIUM, LARGE, EXTRALARGE;
3. Enum toString()
public String getSize() { The toString() method returns
the string representation of the enum constants. For
// this will refer to the object SMALL example,
switch(this) { SMALL.toString()
case SMALL: // returns "SMALL"
return "small";
4. Enum name()
case MEDIUM:
The name() method returns the defined name of an
return "medium";
enum constant in string form. The returned value from
case LARGE: the name() method is final. For example,
return "large"; name(SMALL)
// returns "SMALL"
case EXTRALARGE:
return "extra large"; 5. Java Enum valueOf()
The valueOf() method takes a string and returns an
default: enum constant having the same string name. For
return null; example,
} Size.valueOf("SMALL")
} // returns constant SMALL.

public static void main(String[] args) { 6. Enum values()


The values() method returns an array of enum type
// call getSize() containing all the enum constants. For example,
// using the object SMALL Size[] enumArray = Size.value();
System.out.println("The size of the pizza is " +
Size.SMALL.getSize()); Why Java Enums?
} In Java, enum was introduced to replace the use of int
} constants.
Suppose we have used a collection of int constants. The size is small.
class Size {
public final static int SMALL = 1; In the above example, we have created an enum Size.
public final static int MEDIUM = 2; It includes a private enum constructor. The
public final static int LARGE = 3; constructor takes a string value as a parameter and
public final static int EXTRALARGE = 4; assigns value to the variable pizzaSize.
} Since the constructor is private, we cannot access it
Here, the problem arises if we print the constants. It is
from outside the class. However, we can use enum
because only the number is printed which might not be
constants to call the constructor.
helpful.
In the Main class, we assigned SMALL to an enum
So, instead of using int constants, we can simply use
enums. For example, variable size. The constant SMALL then calls the
enum Size { constructor Size with string as an argument.
SMALL, MEDIUM, LARGE, EXTRALARGE Finally, we called getSize() using size.
}
This makes our code more intuitive. Java enum Strings
Also, enum provides compile-time type safety. Java enum Strings
If we declare a variable of the Size type. For example, Before you learn about enum strings, make sure to
Size size; know about Java enum.
In Java, we can get the string representation of enum
Here, it is guaranteed that the variable will hold one of constants using the toString() method or
the four values. Now, If we try to pass values other
the name() method. For example,
than those four values, the compiler will generate an
enum Size {
error.
SMALL, MEDIUM, LARGE, EXTRALARGE
}
Java enum Constructor
Before you learn about enum constructors, make sure class Main {
to know about Java enums. public static void main(String[] args) {
In Java, an enum class may include a constructor like
a regular class. These enum constructors are either System.out.println("string value of SMALL is " +
 private - accessible within the class Size.SMALL.toString());
or System.out.println("string value of MEDIUM is "
 package-private - accessible within the package + Size.MEDIUM.name());

Example: enum Constructor }
enum Size { }

// enum constants calling the enum constructors Output


SMALL("The size is small."), string value of SMALL is SMALL
MEDIUM("The size is medium."), string value of MEDIUM is MEDIUM
LARGE("The size is large."),
EXTRALARGE("The size is extra large."); In the above example, we have seen the default string
representation of an enum constant is the name of the
private final String pizzaSize; same constant.

// private enum constructor Change Default String Value of enums


private Size(String pizzaSize) { We can change the default string representation of
this.pizzaSize = pizzaSize; enum constants by overriding the toString() method.
} For example,
enum Size {
public String getSize() { SMALL {
return pizzaSize;
} // overriding toString() for SMALL
} public String toString() {
return "The size is small.";
class Main { }
public static void main(String[] args) { },
Size size = Size.SMALL;
System.out.println(size.getSize()); MEDIUM {
}
} // overriding toString() for MEDIUM
public String toString() {
Output return "The size is medium.";
} Now that we know how we can create objects of
}; the Class. We can use this object to get information
} about the corresponding class at runtime.

class Main { Example: Java Class Reflection


public static void main(String[] args) { import java.lang.Class;
System.out.println(Size.MEDIUM.toString()); import java.lang.reflect.*;
}
} class Animal {
}
Output
The size is medium. // put this class in different Dog.java file
public class Dog extends Animal {
In the above program, we have created an enum Size. public void display() {
And we have overridden the toString() method for System.out.println("I am a dog.");
enum constants SMALL and MEDIUM. }
}
Note: We cannot override the name() method. It is
because the name() method is final. // put this in Main.java file
class Main {
public static void main(String[] args) {
Java Reflection try {
In Java, reflection allows us to inspect and // create an object of Dog
manipulate classes, interfaces, constructors, methods, Dog d1 = new Dog();
and fields at run time.
There is a class in Java named Class that keeps all the // create an object of Class
information about objects and classes at runtime. The // using getClass()
object of Class can be used to perform reflection. Class obj = d1.getClass();

Reflection of Java Classes // get name of the class


In order to reflect a Java class, we first need to create String name = obj.getName();
an object of Class. System.out.println("Name: " + name);
And, using the object we can call various methods to
get information about methods, fields, and // get the access modifier of the class
constructors present in a class. int modifier = obj.getModifiers();
There exists three ways to create objects of Class:
1. Using forName() method // convert the access modifier to string
class Dog {...} String mod = Modifier.toString(modifier);
System.out.println("Modifier: " + mod);
// create object of Class
// to reflect the Dog class // get the superclass of Dog
Class a = Class.forName("Dog"); Class superClass = obj.getSuperclass();
System.out.println("Superclass: " +
Here, the forName() method takes the name of the superClass.getName());
class to be reflected as its argument. }

2. Using getClass() method catch (Exception e) {


// create an object of Dog class e.printStackTrace();
Dog d1 = new Dog(); }
}
// create an object of Class }
// to reflect Dog
Class b = d1.getClass(); Output
Name: Dog
Here, we are using the object of the Dog class to Modifier: public
Superclass: Animal
create an object of Class.
3. Using .class extension In the above example, we have created a
// create an object of Class superclass: Animal and a subclass: Dog. Here, we are
// to reflect the Dog class
Class c = Dog.class; trying to inspect the class Dog.
Notice the statement,

Class obj = d1.getClass();


System.out.println("Method Name: " +
Here, we are creating an object obj of Class using m.getName());
the getClass() method. Using the object, we are calling
different methods of Class. // get the access modifier of methods
int modifier = m.getModifiers();
 obj.getName() - returns the name of the class
System.out.println("Modifier: " +
 obj.getModifiers() - returns the access modifier of the
Modifier.toString(modifier));
class
 obj.getSuperclass() - returns the super class of the
// get the return types of method
class
System.out.println("Return Types: " +

m.getReturnType());
Note: We are using the Modifier class to convert the
System.out.println(" ");
integer access modifier to a string. }
}
catch (Exception e) {
Reflecting Fields, Methods, and Constructors e.printStackTrace();
The package java.lang.reflect provides classes that can }
be used for manipulating class members. For example, }
 Method class - provides information about methods in }
a class
 Field class - provides information about fields in a Output
class Method Name: display
 Constructor class - provides information about Modifier: public
constructors in a class Return Types: void

1. Reflection of Java Methods Method Name: makeSound


The Method class provides various methods that can Modifier: private
be used to get information about the methods present Return Types: void
in a class. For example,
import java.lang.Class; In the above example, we are trying to get information
import java.lang.reflect.*; about the methods present in the Dog class. As
mentioned earlier, we have first created an
class Dog { object obj of Class using the getClass() method.
Notice the expression,
// methods of the class Method[] methods = obj.getDeclaredMethod();
public void display() {
System.out.println("I am a dog."); Here, the getDeclaredMethod() returns all the
} methods present inside the class.
Also, we have created an object m of
private void makeSound() {
System.out.println("Bark Bark"); the Method class. Here,
}  m.getName() - returns the name of a method
}  m.getModifiers() - returns the access modifier of
methods in integer form
class Main {  m.getReturnType() - returns the return type of
public static void main(String[] args) { methods
try { The Method class also provides various other
methods that can be used to inspect methods at run
// create an object of Dog time.
Dog d1 = new Dog();
2. Reflection of Java Fields
// create an object of Class Like methods, we can also inspect and modify
// using getClass() different fields of a class using the methods of
Class obj = d1.getClass(); the Field class. For example,
import java.lang.Class;
// using object of Class to import java.lang.reflect.*;
// get all the declared methods of Dog
Method[] methods = obj.getDeclaredMethods(); class Dog {
public String type;
// create an object of the Method class }
for (Method m : methods) {
class Main {
// get names of methods public static void main(String[] args) {
try { // using getClass()
// create an object of Dog Class obj = d1.getClass();
Dog d1 = new Dog();
// access the private field color
// create an object of Class Field field1 = obj.getDeclaredField("color");
// using getClass()
Class obj = d1.getClass(); // allow modification of the private field
field1.setAccessible(true);
// access and set the type field
Field field1 = obj.getField("type"); // set the value of color
field1.set(d1, "labrador"); field1.set(d1, "brown");

// get the value of the field type // get the value of field color
String typeValue = (String) field1.get(d1); String colorValue = (String) field1.get(d1);
System.out.println("Value: " + typeValue); System.out.println("Value: " + colorValue);

// get the access modifier of the field type // get the access modifier of color
int mod = field1.getModifiers(); int mod2 = field1.getModifiers();

// convert the modifier to String form // convert the access modifier to string
String modifier1 = Modifier.toString(mod); String modifier2 = Modifier.toString(mod2);
System.out.println("Modifier: " + modifier1); System.out.println("Modifier: " + modifier2);
System.out.println(" "); }
}
catch (Exception e) {
catch (Exception e) { e.printStackTrace();
e.printStackTrace(); }
} }
} }
}
Output
Output Value: brown
Value: labrador Modifier: private
Modifier: public
In the above example, we have created a class
In the above example, we have created a class named Dog. The class contains a private field
named Dog. It includes a public field named type. named color. Notice the statement.
Notice the statement, Field field1 = obj.getDeclaredField("color");
Field field1 = obj.getField("type");
field1.setAccessible(true);
Here, we are accessing the public field of the Dog class
and assigning it to the object field1 of the Field class. Here, we are accessing color and assigning it to the
We then used various methods of the Field class:
object field1 of the Field class. We then used field1 to
 field1.set() - sets the value of the field
 field1.get() - returns the value of field modify the accessibility of color and allows us to
 field1.getModifiers() - returns the value of the field in make changes to it.
integer form We then used field1 to perform various operations on
Similarly, we can also access and modify private fields the private field color.
as well. However, the reflection of private field is little
bit different than the public field. For example, 3. Reflection of Java Constructor
import java.lang.Class; We can also inspect different constructors of a class
import java.lang.reflect.*; using various methods provided by
the Constructor class. For example,
class Dog { import java.lang.Class;
private String color; import java.lang.reflect.*;
}
class Dog {
class Main { // public constructor without parameter
public static void main(String[] args) { public Dog() {
try { }
// create an object of Dog // private constructor with a single parameter
Dog d1 = new Dog(); private Dog(int age) {
}}
// create an object of Class class Main {
public static void main(String[] args) { If you want to use the ResultSet interface in your
try { code, just import the java.sql package (Importing
// create an object of Dog packages will be discussed later in the article).
Dog d1 = new Dog();
// create an object of Class As mentioned earlier, packages are just containers for
// using getClass() Java classes, interfaces and so on. These packages help
Class obj = d1.getClass(); you to reserve the class namespace and create a
// get all constructors of Dog maintainable code.
Constructor[] constructors = For example, you can find two Date classes in Java.
obj.getDeclaredConstructors();
However, the rule of thumb in Java programming is
for (Constructor c : constructors) {
that only one unique class name is allowed in a Java
// get the name of constructors
project.
System.out.println("Constructor Name: " +
c.getName());
How did they manage to include two classes with
// get the access modifier of constructors
// convert it into string form the same name Date in JDK?
int modifier = c.getModifiers(); This was possible because these two Date classes
String mod = Modifier.toString(modifier); belong to two different packages:
System.out.println("Modifier: " + mod);  java.util.Date - this is a normal Date class that can be
// get the number of parameters in constructors used anywhere.
System.out.println("Parameters: " +  java.sql.Date - this is a SQL Date used for the SQL
c.getParameterCount()); query and such.
System.out.println(""); } }
catch (Exception e) { Based on whether the package is defined by the user or
e.printStackTrace(); }}} not, packages are divided into two categories:

Output Built-in Package


Constructor Name: Dog Built-in packages are existing java packages that come
Modifier: public along with the JDK. For
Parameters: 0 example, java.lang , java.util , java.io , etc. For
example:
Constructor Name: Dog
import java.util.ArrayList;
Modifier: private
Parameters: 1
class ArrayListUtilization {
public static void main(String[] args) {
In the above example, we have created a class
named Dog. The class includes two constructors.
ArrayList<Integer> myList = new
We are using reflection to find the information about
ArrayList<>(3);
the constructors of the class. Notice the statement,
myList.add(3);
Constructor[] constructors =
myList.add(2);
obj.getDeclaredConstructor();
myList.add(1);
Here, the we are accessing all the constructors present
System.out.println(myList);
in Dog and assigning them to an array constructors of
}
the Constructor type.
}
We then used object c to get different informations
Output:
about the constructor.
myList = [3, 2, 1]
 c.getName() - returns the name of the constructor
 c.getModifiers() - returns the access modifiers of the
constructor in integer form The ArrayList class belongs to java.util package . To
 c.getParameterCount() - returns the number of use it, we have to import the package first using
parameters present in each constructor the import statement.
import java.util.ArrayList;
Java Package
Java Package User-defined Package
A package is simply a container that groups related Java also allows you to create packages as per your
types (Java classes, interfaces, enumerations, and need. These packages are called user-defined packages.
annotations). For example, in core Java, How to define a Java package?
To define a package in Java, you use the
the ResultSet interface belongs to
keyword package .
the java.sql package. The package contains all the
package packageName;
related types that are needed for the SQL query and
database connection.
Java uses file system directories to store packages. 3. A pop-up box will appear where you can enter the
Let's create a Java file inside another directory. package name.
For example:
└── com
└── test
└── Test.java

Now, edit Test.java file, and at the beginning of the


file, write the package statement as:
package com.test;

Here, any class that is declared within the test Once the package is created, a similar folder structure
directory belongs to the com.test package. will be created on your file system as well. Now, you
can create classes, interfaces, and so on inside the
Here's the code: package.
package com.test;

class Test {
public static void main(String[] args){
System.out.println("Hello World!");
}
}

Output:
Hello World!

Here, the Test class now belongs to How to import packages in Java?
the com.test package. Java has an import statement that allows you to
import an entire package (as in earlier examples), or
Package Naming convention use only certain classes and interfaces defined in the
The package name must be unique (like a domain package.
name). Hence, there's a convention to create a package The general form of import statement is:
as a domain name, but in reverse order. For import package.name.ClassName; // To import a
example, com.company.name certain class only
Here, each level of the package is a directory in your import package.name.* // To import the whole
file system. Like this: package
└── com
└── company For example,
└── name import java.util.Date; // imports only Date class
import java.io.*; // imports everything inside
And, there is no limitation on how many java.io package
subdirectories (package hierarchy) you can create.
The import statement is optional in Java.
How to create a package in Intellij IDEA? If you want to use class/interface from a certain
In IntelliJ IDEA, here's how you can create a package: package, you can also use its fully qualified name,
1. Right-click on the source folder. which includes its full package hierarchy.
2. Go to new and then package. Here is an example to import a package using
the import statement.
import java.util.Date;

class MyClass implements Date {


// body
}

The same task can be done using the fully qualified


name as follows:
class MyClass implements java.util.Date {
//body
}
Example: Package and importing package
Suppose, you have defined a
package com.programiz that contains a class Helper .
Java Exception Handling
package com.programiz;

public class Helper {


public static String getFormattedDollar (double
Java Exceptions
An exception is an unexpected event that occurs
value){
during program execution. It affects the flow of the
return String.format("$%.2f", value);
program instructions which can cause the program to
}
terminate abnormally.
}
An exception can occur for many reasons. Some of
them are:
Now, you can import Helper class  Invalid user input
from com.programiz package to your implementation  Device failure
class. Once you import it, the class can be referred  Loss of network connection
directly by its name. Here's how:  Physical limitations (out of disk memory)
import com.programiz.Helper;  Code errors
 Opening an unavailable file
class UseHelper { 
public static void main(String[] args) { Java Exception hierarchy
Here is a simplified diagram of the exception
double value = 99.5; hierarchy in Java.
String formattedValue =
Helper.getFormattedDollar(value);
System.out.println("formattedValue = " +
formattedValue);
}
}

Output:
formattedValue = $99.50

Here,
1. the Helper class is defined
in com.programiz package. As you can see from the image above,
2. the Helper class is imported to a different file. The file the Throwable class is the root class in the hierarchy.
contains UseHelper class. Note that the hierarchy splits into two branches: Error
3. The getFormattedDollar() method of the Helper class and Exception.
is called from inside the UseHelper class. Errors
Errors represent irrecoverable conditions such as Java
virtual machine (JVM) running out of memory,
memory leaks, stack overflow errors, library
incompatibility, infinite recursion, etc.
Errors are usually beyond the control of the
programmer and we should not try to handle errors.

Exceptions
Java import package Exceptions can be caught and handled by the
program.
In Java, the import statement is written directly after
When an exception occurs within a method, it creates
the package statement (if it exists) and before the class an object. This object is called the exception object.
definition. It contains information about the exception such as
the name and description of the exception and state of
For example, the program when the exception occurred.
package package.name; We will learn how to handle these exceptions in the
import package.ClassName; // only import a Class next tutorial. In this tutorial, we will now focus on
different types of exceptions in Java.
class MyClass {
// body
}
Java Exception Types When an exception occurs, it is caught by
The exception hierarchy also has two the catch block. The catch block cannot be used
branches: RuntimeException and IOException . without the try block.
Example: Exception handling using try...catch
1. RuntimeException class Main {
A runtime exception happens due to a programming public static void main(String[] args) {
error. They are also known as unchecked exceptions.
These exceptions are not checked at compile-time but try {
run-time. Some of the common runtime exceptions
are: // code that generate exception
 Improper use of an API - IllegalArgumentException int divideByZero = 5 / 0;
 Null pointer access (missing the initialization of System.out.println("Rest of code in try block");
a variable) - NullPointerException }
 Out-of-bounds array access -
ArrayIndexOutOfBoundsException catch (ArithmeticException e) {
System.out.println("ArithmeticException => " +
 Dividing a number by 0 - ArithmeticException e.getMessage());
You can think about it in this way. "If it is a runtime }
exception, it is your fault". }
The NullPointerException would not have occurred if }
you had checked whether the variable was initialized
or not before using it. Output
An ArrayIndexOutOfBoundsException would not ArithmeticException => / by zero
have occurred if you tested the array index against the In the example, we are trying to divide a number
array bounds. by 0 . Here, this code generates an exception.
To handle the exception, we have put the code, 5 /
2. IOException 0 inside the try block. Now when an exception
An IOException is also known as a checked
occurs, the rest of the code inside the try block is
exception. They are checked by the compiler at the skipped.
compile-time and the programmer is prompted to
The catch block catches the exception and statements
handle these exceptions.
Some of the examples of checked exceptions are: inside the catch block is executed.
 Trying to open a file that doesn't exist results If none of the statements in the try block generates an
in FileNotFoundException exception, the catch block is skipped.
 Trying to read past the end of a file
Now we know about exceptions, we will learn 2. Java finally block
about handling exceptions in the next tutorial. In Java, the finally block is always executed no matter
whether there is an exception or not.
Java Exception Handling The finally block is optional. And, for each try block,
In the last tutorial, we learned about Java exceptions. there can be only one finally block.
We know that exceptions abnormally terminate the
execution of a program.
The basic syntax of finally block is:
This is why it is important to handle exceptions.
Here's a list of different approaches to handle try {
exceptions in Java. //code
 try...catch block }
 finally block catch (ExceptionType1 e1) {
 throw and throws keyword // catch block

}
finally {
1. Java try...catch block
// finally block always executes
The try-catch block is used to handle exceptions in
}
Java. Here's the syntax of try...catch block:
If an exception occurs, the finally block is executed
try {
// code after the try...catch block. Otherwise, it is executed
} after the try block. For each try block, there can be
catch(Exception e) { only one finally block.
// code
} Example: Java Exception Handling using finally
Here, we have placed the code that might generate an block
exception inside the try block. Every try block is class Main {
followed by a catch block. public static void main(String[] args) {
try {
// code that generates exception Example: Java throws keyword
int divideByZero = 5 / 0; import java.io.*;
}
class Main {
catch (ArithmeticException e) { // declareing the type of exception
System.out.println("ArithmeticException => " + public static void findFile() throws IOException {
e.getMessage());
} // code that may generate IOException
File newFile = new File("test.txt");
finally { FileInputStream stream = new
System.out.println("This is the finally block"); FileInputStream(newFile);
} }
}
} public static void main(String[] args) {
try {
Output findFile();
ArithmeticException => / by zero }
This is the finally block catch (IOException e) {
In the above example, we are dividing a number System.out.println(e);
by 0 inside the try block. Here, this code generates }
an ArithmeticException . }
}
The exception is caught by the catch block. And, then
the finally block is executed. Output
Note: It is a good practice to use the finally block. It is java.io.FileNotFoundException: test.txt (The system
because it can include important cleanup codes like, cannot find the file specified)
 code that might be accidentally skipped by When we run this program, if the file test.txt does not
return, continue or break exist, FileInputStream throws
 closing a file or connection a FileNotFoundException which extends
the IOException class.
3. Java throw and throws keyword The findFile() method specifies that
The Java throw keyword is used to explicitly throw a an IOException can be thrown. The main() method
single exception. calls this method and handles the exception if it is
When we throw an exception, the flow of the thrown.
If a method does not handle exceptions, the type of
program moves from the try block to the catch block. exceptions that may occur within it must be specified
in the throws clause.
Example: Exception handling using Java throw
class Main {
public static void divideByZero() { Java try...catch
The try...catch block in Java is used to handle
// throw an exception exceptions and prevents the abnormal termination of
throw new ArithmeticException("Trying to divide the program.
by 0"); Here's the syntax of a try...catch block in Java.
} try{
// code
public static void main(String[] args) { }
divideByZero(); catch(exception) {
} // code
} }

Output The try block includes the code that might generate
Exception in thread "main"
an exception.
java.lang.ArithmeticException: Trying to divide by 0
at Main.divideByZero(Main.java:5) The catch block includes the code that is executed
at Main.main(Main.java:9) when there occurs an exception inside the try block.
In the above example, we are explicitly throwing
the ArithmeticException using the throw keyword. Example: Java try...catch block
Similarly, the throws keyword is used to declare the class Main {
public static void main(String[] args) {
type of exceptions that might occur within the method.
It is used in the method declaration.
try {
int divideByZero = 5 / 0;
System.out.println("Rest of code in try block");} Java try...catch...finally block
catch (ArithmeticException e) { In Java, we can also use the finally block after
System.out.println("ArithmeticException => " + the try...catch block. For example,
e.getMessage()); }}} import java.io.*;

Output class ListOfNumbers {


ArithmeticException => / by zero
// create an integer array
In the above example, notice the line, private int[] list = {5, 6, 8, 9, 2};
int divideByZero = 5 / 0;
// method to write data from array to a fila
Here, we are trying to divide a number by zero. In this public void writeList() {
case, an exception occurs. Hence, we have enclosed PrintWriter out = null;
this code inside the try block.
When the program encounters this try {
code, ArithmeticException occurs. And, the System.out.println("Entering try statement");
exception is caught by the catch block and executes
// creating a new file OutputFile.txt
the code inside the catch block. out = new PrintWriter(new
The catch block is only executed if there exists an FileWriter("OutputFile.txt"));
exception inside the try block.
// writing values from list array to Output.txt
for (int i = 0; i < 7; i++) {
Note: In Java, we can use a try block without out.println("Value at: " + i + " = " + list[i]);
a catch block. However, we cannot use a catch block }
}
without a try block.
catch (Exception e) {
System.out.println("Exception => " +
Java try...finally block
e.getMessage());
We can also use the try block along with a finally
}
block.
In this case, the finally block is always executed finally {
whether there is an exception inside the try block or // checking if PrintWriter has been opened
not. if (out != null) {
System.out.println("Closing PrintWriter");
Example: Java try...finally block // close PrintWriter
class Main { out.close();
public static void main(String[] args) { }
try {
int divideByZero = 5 / 0; else {
} System.out.println("PrintWriter not open");
}
finally { }
System.out.println("Finally block is always
executed"); }
} }
}
} class Main {
public static void main(String[] args) {
Output ListOfNumbers list = new ListOfNumbers();
Finally block is always executed list.writeList();
Exception in thread "main" }
java.lang.ArithmeticException: / by zero }
at Main.main(Main.java:4)
Output
In the above example, we have used the try block Entering try statement
along with the finally block. We can see that the code Exception => Index 5 out of bounds for length 5
inside the try block is causing an exception. Closing PrintWriter
However, the code inside the finally block is executed
In the above example, we have created
irrespective of the exception.
an array named list and a file named output.txt .
Here, we are trying to read data from the array and IndexOutOfBoundsException => Index 10 out of
storing to the file. bounds for length 10
Notice the code,
for (int i = 0; i < 7; i++) { In this example, we have created an integer array
out.println("Value at: " + i + " = " + list[i]); named arr of size 10.
} Since the array index starts from 0, the last element of
the array is at arr[9] . Notice the statement,
Here, the size of the array is 5 and the last element of arr[10] = 11;
the array is at list[4] . However, we are trying to access
elements at a[5] and a[6] . Here, we are trying to assign a value to the index 10.
Hence, the code generates an exception that is caught Hence, IndexOutOfBoundException occurs.
by the catch block. When an exception occurs in the try block,
Since the finally block is always executed, we have  The exception is thrown to the first catch block. The
included code to close the PrintWriter inside the first catch block does not handle
finally block. an IndexOutOfBoundsException , so it is passed to
It is a good practice to use finally block to include
important cleanup code like closing a file or the next catch block.
connection.  The second catch block in the above example is the
Note: There are some cases when a finally block does appropriate exception handler because it handles
not execute: an IndexOutOfBoundsException . Hence, it is
 Use of System.exit() method executed.
 An exception occurs in the finally block 
Catching Multiple Exceptions
 The death of a thread
From Java SE 7 and later, we can now catch more

Multiple Catch blocks than one type of exception with one catch block.
For each try block, there can be zero or This reduces code duplication and increases code
simplicity and efficiency.
more catch blocks. Multiple catch blocks allow us to Each exception type that can be handled by
handle each exception differently. the catch block is separated using a vertical bar | .
The argument type of each catch block indicates the Its syntax is:
type of exception that can be handled by it. For try {
example, // code
class ListOfNumbers { } catch (ExceptionType1 | Exceptiontype2 ex) {
public int[] arr = new int[10]; // catch block
}
public void writeList() {

try { Java try-with-resources statement


arr[10] = 11; The try-with-resources statement is a try statement
} that has one or more resource declarations.
Its syntax is:
catch (NumberFormatException e1) { try (resource declaration) {
System.out.println("NumberFormatException => // use of the resource
" + e1.getMessage()); } catch (ExceptionType e1) {
} // catch block
}
catch (IndexOutOfBoundsException e2) {
System.out.println("IndexOutOfBoundsException The resource is an object to be closed at the end of the
=> " + e2.getMessage()); program. It must be declared and initialized in the try
} statement.
Let's take an example.
} try (PrintWriter out = new PrintWriter(new
} FileWriter("OutputFile.txt"))) {
// use of the resource
class Main { }
public static void main(String[] args) {
ListOfNumbers list = new ListOfNumbers(); The try-with-resources statement is also referred to
list.writeList(); as automatic resource management. This statement
} automatically closes all the resources at the end of the
} statement.
Output
Java throw and throws in the throws clause so that methods further up in the
In Java, exceptions can be categorized into two types: call stack can handle them or specify them
 Unchecked Exceptions: They are not checked at using throws keyword themselves.
compile-time but at run-time.For The findFile() method specifies that
example: ArithmeticException , NullPointerExceptio an IOException can be thrown. The main() method
n , ArrayIndexOutOfBoundsException , exceptions calls this method and handles the exception if it is
under Error class, etc. thrown.
 Checked Exceptions: They are checked at compile-
time. For Throwing multiple exceptions
example, IOException , InterruptedException , etc. Here's how we can throw multiple exceptions using
the throws keyword.
Usually, we don't need to handle unchecked import java.io.*;
exceptions. It's because unchecked exceptions occur class Main {
due to programming errors. And, it is a good practice public static void findFile() throws
to correct them instead of handling them. NullPointerException, IOException,
This tutorial will now focus on how to handle checked InvalidClassException {
exceptions using throw and throws .
// code that may produce NullPointerException
Java throws keyword ………
We use the throws keyword in the method
// code that may produce IOException
declaration to declare the type of exceptions that ………
might occur within it.
Its syntax is: // code that may produce InvalidClassException
accessModifier returnType methodName() throws ………
ExceptionType1, ExceptionType2 … { }
// code
} public static void main(String[] args) {
try{
As you can see from the above syntax, we can findFile();
use throws to declare multiple exceptions. } catch(IOException e1){
System.out.println(e1.getMessage());
Example 1: Java throws Keyword } catch(InvalidClassException e2){
import java.io.*; System.out.println(e2.getMessage());
class Main { }
public static void findFile() throws IOException { }
// code that may produce IOException }
File newFile=new File("test.txt");
FileInputStream stream=new Here, the findFile() method specifies that it can
FileInputStream(newFile);
throw NullPointerException , IOException ,
}
and InvalidClassException in its throws clause.
public static void main(String[] args) { Note that we have not handled
try{ the NullPointerException . This is because it is an
findFile(); unchecked exception. It is not necessary to specify it in
} catch(IOException e){ the throws clause and handle it.
System.out.println(e);
} throws keyword Vs. try...catch...finally
} There might be several methods that can cause
}
exceptions. Writing try...catch for each method will
be tedious and code becomes long and less-readable.
Output
java.io.FileNotFoundException: test.txt (No such file throws is also useful when you have checked
or directory) exception (an exception that must be handled) that
you don't want to catch in your current method.
When we run this program, if the file test.txt does not
Java throw keyword
exist, FileInputStream throws
The throw keyword is used to explicitly throw a single
a FileNotFoundException which extends
exception.
the IOException class. When an exception is thrown, the flow of program
If a method does not handle exceptions, the type of execution transfers from the try block to
exceptions that may occur within it must be specified
the catch block. We use the throw keyword within a We have handled this exception in
method. the main() method. The flow of program execution
Its syntax is: transfers from the try block to catch block when an
throw throwableObject; exception is thrown. So, the rest of the code in
the try block is skipped and statements in
A throwable object is an instance of
the catch block are executed.
class Throwable or subclass of the Throwable class.

Example 2: Java throw keyword Java catch Multiple Exceptions


class Main { Before Java 7, we had to write multiple exception
public static void divideByZero() { handling codes for different types of exceptions even if
throw new ArithmeticException("Trying to divide there was code redundancy.
by 0"); Let's take an example.
}
Example 1: Multiple catch blocks
public static void main(String[] args) { class Main {
divideByZero(); public static void main(String[] args) {
} try {
} int array[] = new int[10];
array[10] = 30 / 0;
Output } catch (ArithmeticException e) {
Exception in thread "main" System.out.println(e.getMessage());
java.lang.ArithmeticException: Trying to divide by 0 } catch (ArrayIndexOutOfBoundsException e) {
at Main.divideByZero(Main.java:3) System.out.println(e.getMessage());
at Main.main(Main.java:7) }}}
exit status 1
Output
In this example, we are explicitly throwing / by zero
an ArithmeticException.
In this example, two exceptions may occur:
Note: ArithmeticException is an unchecked
 ArithmeticException because we are trying to divide
exception. It's usually not necessary to handle
a number by 0.
unchecked exceptions.
 ArrayIndexOutOfBoundsException because we have
Example 3: Throwing checked exception declared a new integer array with array bounds 0 to 9
import java.io.*; and we are trying to assign a value to index 10.
class Main { We are printing out the exception message in both
public static void findFile() throws IOException { the catch blocks i.e. duplicate code.
throw new IOException("File not found"); The associativity of the assignment operator = is right
} to left, so an ArithmeticException is thrown first with
public static void main(String[] args) { the message / by zero .
try {
findFile(); Handle Multiple Exceptions in a catch Block
System.out.println("Rest of code in try block"); In Java SE 7 and later, we can now catch more than
} catch (IOException e) { one type of exception in a single catch block.
System.out.println(e.getMessage()); Each exception type that can be handled by
} the catch block is separated using a vertical bar or
} pipe | .
}
Its syntax is:
try {
Output // code
File not found } catch (ExceptionType1 | Exceptiontype2 ex) {
// catch block
The findFile() method throws an IOException with }
the message we passed to its constructor.
Note that since it is a checked exception, we must Example 2: Multi-catch block
specify it in the throws clause. class Main {
The methods that call this findFile() method need to public static void main(String[] args) {
either handle this exception or specify it try {
using throws keyword themselves. int array[] = new int[10];
array[10] = 30 / 0;
} catch (ArithmeticException | } catch (Exception | ArithmeticException |
ArrayIndexOutOfBoundsException e) { ArrayIndexOutOfBoundsException e) {
System.out.println(e.getMessage()); System.out.println(e.getMessage());
} }
} }
} }

Output Output
/ by zero Main.java:6: error: Alternatives in a multi-catch
statement cannot be related by subclassing
Catching multiple exceptions in a single catch block
reduces code duplication and increases efficiency. In this
The bytecode generated while compiling this program example, ArithmeticException and ArrayIndexOutO
will be smaller than the program having fBoundsException are both subclasses of
multiple catch blocks as there is no code redundancy. the Exception class. So, we get a compilation error.
Note: If a catch block handles multiple exceptions,
the catch parameter is implicitly final . This means we
cannot assign any values to catch parameters. Java try-with-resources
The try-with-resources statement automatically closes
Catching base Exception all the resources at the end of the statement. A
When catching multiple exceptions in a resource is an object to be closed at the end of the
single catch block, the rule is generalized to program.
specialized. Its syntax is:
This means that if there is a hierarchy of exceptions in try (resource declaration) {
the catch block, we can catch the base exception only // use of the resource
instead of catching multiple specialized exceptions. } catch (ExceptionType e1) {
Let's take an example. // catch block
Example 3: Catching base exception class only }
class Main {
public static void main(String[] args) { As seen from the above syntax, we declare the try-
try { with-resources statement by,
int array[] = new int[10]; 1. declaring and instantiating the resource within
array[10] = 30 / 0; the try clause.
} catch (Exception e) {
2. specifying and handling all exceptions that might be
System.out.println(e.getMessage());
thrown while closing the resource.
}
Note: The try-with-resources statement closes all the
}
resources that implement the AutoCloseable interface.
}

Output Let us take an example that implements the try-with-


/ by zero resources statement.

We know that all the exception classes are subclasses Example 1: try-with-resources
of the Exception class. So, instead of catching import java.io.*;
multiple specialized exceptions, we can simply catch
the Exception class. class Main {
public static void main(String[] args) {
String line;
If the base exception class has already been specified
try(BufferedReader br = new BufferedReader(new
in the catch block, do not use child exception classes FileReader("test.txt"))) {
in the same catch block. Otherwise, we will get a while ((line = br.readLine()) != null) {
compilation error. System.out.println("Line =>"+line);
Let's take an example. }
} catch (IOException e) {
Example 4: Catching base and child exception System.out.println("IOException in try block =>"
classes + e.getMessage());
class Main { }
public static void main(String[] args) { }
try { }
int array[] = new int[10];
array[10] = 30 / 0; Output if the test.txt file is not found.
IOException in try-with-resources block =>test.txt class Main {
(No such file or directory) public static void main(String[] args) {
BufferedReader br = null;
Output if the test.txt file is found. String line;
Entering try-with-resources block
Line =>test line try {
System.out.println("Entering try block");
In this example, we use an instance br = new BufferedReader(new
of BufferedReader to read data from the test.txt file. FileReader("test.txt"));
Declaring and instantiating the BufferedReader inside while ((line = br.readLine()) != null) {
System.out.println("Line =>"+line);
the try-with-resources statement ensures that its }
instance is closed regardless of whether } catch (IOException e) {
the try statement completes normally or throws an System.out.println("IOException in try block =>"
exception. + e.getMessage());
If an exception occurs, it can be handled using } finally {
the exception handling blocks or the throws keyword. System.out.println("Entering finally block");
try {
Suppressed Exceptions if (br != null) {
In the above example, exceptions can be thrown from br.close();
the try-with-resources statement when: }
 The file test.txt is not found. } catch (IOException e) {
System.out.println("IOException in finally block
 Closing the BufferedReader object. =>"+e.getMessage());
An exception can also be thrown from the try block as }
a file read can fail for many reasons at any time.
AD }
If exceptions are thrown from both the try block and }
the try-with-resources statement, exception from }
the try block is thrown and exception from the try-
Output
with-resources statement is suppressed. Entering try block
Retrieving Suppressed Exceptions Line =>line from test.txt file
In Java 7 and later, the suppressed exceptions can be Entering finally block
retrieved by calling
the Throwable.getSuppressed() method from the As we can see from the above example, the use
exception thrown by the try block. of finally block to clean up resources makes the code
This method returns an array of all suppressed more complex.
exceptions. We get the suppressed exceptions in Notice the try...catch block in the finally block as
the catch block. well? This is because an IOException can also occur
catch(IOException e) { while closing the BufferedReader instance inside
System.out.println("Thrown exception=>" +
this finally block so it is also caught and handled.
e.getMessage());
Throwable[] suppressedExceptions = The try-with-resources statement does automatic
e.getSuppressed(); resource management. We need not explicitly close
for (int i=0; i<suppressedExceptions.length; i++) { the resources as JVM automatically closes them. This
System.out.println("Suppressed exception=>" + makes the code more readable and easier to write.
suppressedExceptions[i]);
} 2. try-with-resources with multiple resources
} We can declare more than one resource in the try-
with-resources statement by separating them with a
Advantages of using try-with-resources semicolon ;
Here are the advantages of using try-with-resources:
1. finally block not required to close the resource
Before Java 7 introduced this feature, we had to use Example 3: try with multiple resources
import java.io.*;
the finally block to ensure that the resource is closed
import java.util.*;
to avoid resource leaks. class Main {
Here's a program that is similar to Example 1. public static void main(String[] args) throws
However, in this program, we have used finally block IOException{
to close resources. try (Scanner scanner = new Scanner(new
Example 2: Close resource using finally block File("testRead.txt"));
import java.io.*;
PrintWriter writer = new PrintWriter(new Example 1: @Override Annotation Example
File("testWrite.txt"))) { class Animal {
while (scanner.hasNext()) { public void displayInfo() {
writer.print(scanner.nextLine()); System.out.println("I am an animal.");
} }
} }
}
} class Dog extends Animal {
@Override
If this program executes without generating any public void displayInfo() {
exceptions, Scanner object reads a line from System.out.println("I am a dog.");
the testRead.txt file and writes it in a }
}
new testWrite.txt file.
When multiple declarations are made, the try-with- class Main {
resources statement closes these resources in reverse public static void main(String[] args) {
order. In this example, the PrintWriter object is closed Dog d1 = new Dog();
d1.displayInfo();
first and then the Scanner object is closed.
}
}
Java 9 try-with-resources enhancement
In Java 7, there is a restriction to the try-with- Output
resources statement. The resource needs to be I am a dog.
declared locally within its block.
try (Scanner scanner = new Scanner(new In this example, the method displayInfo() is present in
File("testRead.txt"))) { both the superclass Animal and subclass Dog . When
// code this method is called, the method of the subclass is
} called instead of the method in the superclass.
If we declared the resource outside the block in Java 7, Annotation formats
it would have generated an error message. Annotations may also include elements
Scanner scanner = new Scanner(new (members/attributes/parameters).
File("testRead.txt"));
try (scanner) {
1. Marker Annotations
// code
Marker annotations do not contain
} members/elements. It is only used for marking a
declaration.
To deal with this error, Java 9 improved the try-with- Its syntax is:
resources statement so that the reference of the @AnnotationName()
resource can be used even if it is not declared locally.
The above code will now execute without any Since these annotations do not contain elements,
compilation error. parentheses can be excluded. For example,
@Override
Java Annotations
Java annotations are metadata (data about data) for 2. Single element Annotations
our program source code. A single element annotation contains only one
They provide additional information about the element.
program to the compiler but are not part of the Its syntax is:
program itself. These annotations do not affect the @AnnotationName(elementName = "elementValue")
execution of the compiled program.
Annotations start with @ . Its syntax is: If there is only one element, it is a convention to name
@AnnotationName that element as value .
@AnnotationName(value = "elementValue")
Let's take an example of @Override annotation.
In this case, the element name can be excluded as
The @Override annotation specifies that the method
well. The element name will be value by default.
that has been marked with this annotation overrides
@AnnotationName("elementValue")
the method of the superclass with the same method
name, return type, and parameter list.
3. Multiple element Annotations
It is not mandatory to use @Override when These annotations contain multiple elements
overriding a method. However, if we use it, the separated by commas.
compiler gives an error if something is wrong (such as
wrong parameter type) while overriding the method. Its syntax is:
@AnnotationName(element1 = "value1", element2 =
"value2") This declaration specifies non-null variable str of
type String to avoid NullPointerException .
Annotation placement @NonNull List<String> newList;
Any declaration can be marked with annotation by
placing it above that declaration. As of Java 8,
This declaration specifies a non-null list of
annotations can also be placed before a type.
type String .
1. Above declarations
As mentioned above, Java annotations can be placed List<@NonNull String> newList;
above class, method, interface, field, and other
program element declarations. This declaration specifies a list of non-null values of
Example 2: @SuppressWarnings Annotation type String .
Example Type casts
import java.util.*; newStr = (@NonNull String) str;

class Main { extends and implements clause


@SuppressWarnings("unchecked") class Warning extends @Localized Message
static void wordsList() {
ArrayList wordList = new ArrayList<>(); throws clause
public String readMethod() throws @Localized
// This causes an unchecked warning IOException
wordList.add("programiz");
Type annotations enable Java code to be analyzed
System.out.println("Word list => " + wordList); better and provide even stronger type checks.
}
Types of Annotations
public static void main(String args[]) { 1. Predefined annotations
wordsList(); 1. @Deprecated
} 2. @Override
}
3. @SuppressWarnings
Output 4. @SafeVarargs
Word list => [programiz] 5. @FunctionalInterface
2. Meta-annotations
If the above program is compiled without using 1. @Retention
the @SuppressWarnings("unchecked") annotation, 2. @Documented
the compiler will still compile the program but it will
3. @Target
give warnings like:
Main.java uses unchecked or unsafe operations. 4. @Inherited
Word list => [programiz] 5. @Repeatable
3. Custom annotations
We are getting the warning These annotation types are described in detail in
Main.java uses unchecked or unsafe operations the Java Annotation Types tutorial.

because of the following statement. Use of Annotations


ArrayList wordList = new ArrayList<>(); 
 Compiler instructions - Annotations can be used for
This is because we haven't defined the generic type of giving instructions to the compiler, detect errors or
the array list. We can fix this warning by specifying suppress warnings. The built-in
generics inside angle brackets <> . annotations @Deprecated , @Override , @Suppress
ArrayList<String> wordList = new ArrayList<>(); Warnings are used for these purposes.

2. Type annotations  Compile-time instructions - Compile-time
Before Java 8, annotations could be applied to instructions provided by these annotations help the
declarations only. Now, type annotations can be used software build tools to generate code, XML files and
as well. This means that we can place annotations many more.
wherever we use a type. 
 Runtime instructions - Some annotations can be
Constructor invocations defined to give instructions to the program at runtime.
new @Readonly ArrayList<>() These annotations are accessed using Java Reflection.
Type definitions
@NonNull String str;
Java Annotation Types deprecatedMethod();
Java annotations are metadata (data about data) for }
our program source code. There are several predefined }
annotations provided by the Java SE. Moreover, we
can also create custom annotations as per our needs. Output
Deprecated method
These annotations can be categorized as:
2. @Override
1. Predefined annotations The @Override annotation specifies that a method of
 @Deprecated a subclass overrides the method of the superclass with
 @Override the same method name, return type, and parameter
list.
 @SuppressWarnings
It is not mandatory to use @Override when
 @SafeVarargs overriding a method. However, if we use it, the
 @FunctionalInterface compiler gives an error if something is wrong (such as
wrong parameter type) while overriding the method.
2. Custom annotations Example 2: @Override annotation example
class Animal {
3. Meta-annotations
 @Retention // overridden method
 @Documented public void display(){
System.out.println("I am an animal");
 @Target }
 @Inherited }
 @Repeatable
 class Dog extends Animal {
Predefined Annotation Types
1. @Deprecated // overriding method
The @Deprecated annotation is a marker annotation @Override
public void display(){
that indicates the element (class, method, field, etc) is
System.out.println("I am a dog");
deprecated and has been replaced by a newer element.
}
Its syntax is:
@Deprecated
public void printMessage(){
accessModifier returnType deprecatedMethodName()
display();
{ ... }
}
}
When a program uses the element that has been
declared deprecated, the compiler generates a
class Main {
warning.
public static void main(String[] args) {
We use Javadoc @deprecated tag for documenting Dog dog1 = new Dog();
the deprecated element. dog1.printMessage();
/** }
* @deprecated }
* why it was deprecated
*/ Output
@Deprecated I am a dog
accessModifier returnType deprecatedMethodName()
{ ... } In this example, by making an
object dog1 of Dog class, we can call its
Example 1: @Deprecated annotation example
class Main { method printMessage() which then executes
/** the display() statement.
* @deprecated Since display() is defined in both the classes, the
* This method is deprecated and has been replaced method of subclass Dog overrides the method of
by newMethod()
*/ superclass Animal . Hence, the display() of the
@Deprecated subclass is called.
public static void deprecatedMethod() {
System.out.println("Deprecated method"); 3. @SuppressWarnings
} As the name suggests,
the @SuppressWarnings annotation instructs the
public static void main(String args[]) {
compiler to suppress warnings that are generated while overridden. We can now use this annotation for
the program executes. private methods as well.
We can specify the type of warnings to be suppressed. Example 4: @SafeVarargs annotation example
The warnings that can be suppressed are compiler- import java.util.*;
specific but there are two categories of
warnings: deprecation and unchecked. class Main {
To suppress a particular category of warning, we use:
@SuppressWarnings("warningCategory") private void displayList(List<String>... lists) {
for (List<String> list : lists) {
For example, System.out.println(list);
@SuppressWarnings("deprecated") }
}
To suppress multiple categories of warnings, we use:
@SuppressWarnings({"warningCategory1", public static void main(String args[]) {
"warningCategory2"}) Main obj = new Main();

For example, List<String> universityList =


@SuppressWarnings({"deprecated", "unchecked"}) Arrays.asList("Tribhuvan University", "Kathmandu
University");
Category deprecated instructs the compiler to obj.displayList(universityList);
suppress warnings when we use a deprecated element.
Category unchecked instructs the compiler to List<String> programmingLanguages =
Arrays.asList("Java", "C");
suppress warnings when we use raw types.
obj.displayList(universityList,
And, undefined warnings are ignored. For example,
programmingLanguages);
@SuppressWarnings("someundefinedwarning")
}
}
Example 3: @SuppressWarnings annotation
example
Warnings
class Main {
Type safety: Potential heap pollution via varargs
@Deprecated
parameter lists
public static void deprecatedMethod() {
Type safety: A generic array of List<String> is created
System.out.println("Deprecated method");
for a varargs
}
Parameter
@SuppressWarnings("deprecated")
Output
public static void main(String args[]) {
Note: Main.java uses unchecked or unsafe operations.
Main depObj = new Main();
[Tribhuvan University, Kathmandu University]
depObj. deprecatedMethod();
[Tribhuvan University, Kathmandu University]
}
[Java, C]
}

Output Here, List ... lists specifies a variable-length argument


Deprecated method of type List . This means that the
method displayList() can have zero or more
Here, deprecatedMethod() has been marked as arguments.
deprecated and will give compiler warnings when The above program compiles without errors but gives
used. By using warnings when @SafeVarargs annotation isn't used.
the @SuppressWarnings("deprecated") annotation, When we use @SafeVarargs annotation in the above
we can avoid compiler warnings. example,
@SafeVarargs
4. @SafeVarargs private void displayList(List<String>... lists) { ... }
The @SafeVarargs annotation asserts that the
annotated method or constructor does not perform We get the same output but without any warnings.
unsafe operations on its varargs (variable number of Unchecked warnings are also suppressed when we use
arguments). this annotation.
We can only use this annotation on methods or
constructors that cannot be overridden. This is because 5. @FunctionalInterface
the methods that override them might perform unsafe Java 8 first introduced
operations. this @FunctionalInterface annotation. This
Before Java 9, we could use this annotation only on annotation indicates that the type declaration on
final or static methods because they cannot be which it is used is a functional interface. A functional
interface can have only one abstract method.
Example 5: @FunctionalInterface annotation }
example
@FunctionalInterface class Main {
public interface MyFuncInterface{ @MyCustomAnnotation(value = "programiz")
public void firstMethod(); // this is an abstract public void method1() {
method System.out.println("Test method 1");
} }

If we add another abstract method, let's say public static void main(String[] args) throws
@FunctionalInterface Exception {
public interface MyFuncInterface{ Main obj = new Main();
public void firstMethod(); // this is an abstract obj.method1();
method }
public void secondMethod(); // this throws compile }
error
} Output
Test method 1
Now, when we run the program, we will get the
following warning: Meta Annotations
Unexpected @FunctionalInterface annotation Meta-annotations are annotations that are applied to
@FunctionalInterface ^ MyFuncInterface is not a other annotations.
functional interface 1. @Retention
multiple non-overriding abstract methods found in The @Retention annotation specifies the level up to
interface MyFuncInterface which the annotation will be available.
Its syntax is:
It is not mandatory to @Retention(RetentionPolicy)
use @FunctionalInterface annotation. The compiler
will consider any interface that meets the functional There are 3 types of retention policies:
interface definition as a functional interface.  RetentionPolicy.SOURCE - The annotation is
We use this annotation to make sure that the available only at the source level and is ignored by the
functional interface has only one abstract method. compiler.
However, it can have any number of default and static  RetentionPolicy.CLASS - The annotation is available
methods because they have an implementation. to the compiler at compile-time, but is ignored by the
@FunctionalInterface Java Virtual Machine (JVM).
public interface MyFuncInterface{  RetentionPolicy.RUNTIME - The annotation is
public void firstMethod(); // this is an abstract available to the JVM.
method For example,
default void secondMethod() { ... } @Retention(RetentionPolicy.RUNTIME)
default void thirdMethod() { ... } public @interface MyCustomAnnotation{ ... }
}
2. @Documented
Custom Annotations By default, custom annotations are not included in
It is also possible to create our own custom the official Java documentation. To include our
annotations. annotation in the Javadoc documentation, we use
Its syntax is: the @Documented annotation.
[Access Specifier] @interface<AnnotationName> { For example,
DataType <Method Name>() [default value]; @Documented
} public @interface MyCustomAnnotation{ ... }
Here is what you need to know about custom 3. @Target
annotation: We can restrict an annotation to be applied to specific
 Annotations can be created by
targets using the @Target annotation.
using @interface followed by the annotation name.
Its syntax is:
 The annotation can have elements that look like @Target(ElementType)
methods but they do not have an implementation.
 The default value is optional. The parameters cannot
have a null value.
 The return type of the method can
be primitive, enum, string, class name or array of these
types.
Example 6: Custom annotation example
@interface MyCustomAnnotation {
String value() default "default value";
The ElementType can have one of the following The value defined in the @Repeatable annotation is
types: the container annotation. The container annotation
has a variable value of array type of the above
Element Type Target repeatable annotation. Here, Universities are the
containing annotation type.
ElementType.ANNOTATION_TYPE Annotation
public @interface Universities {
type
University[] value();
}
ElementType.CONSTRUCTOR Constructors

ElementType.FIELD Fields Now, the @University annotation can be used


multiple times on the same declaration.
ElementType.LOCAL_VARIABLE Local @University(name = "TU")
variables @University(name = "KU")
private String uniName;
ElementType.METHOD Methods
If we need to retrieve the annotation data, we can
ElementType.PACKAGE Package use the Reflection API.
To retrieve annotation values, we
ElementType.PARAMETER Parameter use getAnnotationsByType() or getAnnotations() met
hod defined in the Reflection API.
ElementType.TYPE Any element
of class Java Logging
Java allows us to create and capture log messages and
files through the process of logging.
For example, In Java, logging requires frameworks and APIs. Java
@Target(ElementType.METHOD) has a built-in logging framework in
public @interface MyCustomAnnotation{ ... }
the java.util.logging package.
In this example, we have restricted the use of this We can also use third-party frameworks like Log4j,
annotation to methods only. Logback, and many more for logging purposes.

Java Logging Components


Note: If the target type is not defined, the annotation
The figure below represents the core components and
can be used for any element. the flow of control of the Java Logging API
( java.util.logging ).
4. @Inherited
By default, an annotation type cannot be inherited
from a superclass. However, if we need to inherit an
annotation from a superclass to a subclass, we use
the @Inherited annotation.
Its syntax is:
@Inherited
Java Logging
For example,
@Inherited 1. Logger
public @interface MyCustomAnnotation { ... } The Logger class provides methods for logging. We
can instantiate objects from the Logger class and call
@MyCustomAnnotation its methods for logging purposes.
public class ParentClass{ ... } Let's take an example.
Logger logger =
public class ChildClass extends ParentClass { ... } Logger.getLogger("newLoggerName");

5. @Repeatable The getLogger() method of the Logger class is used


An annotation that has been marked to find or create a new Logger . The string argument
by @Repeatable can be applied multiple times to the defines the name of the logger.
same declaration. Here, this creates a new Logger object or returns an
@Repeatable(Universities.class)
public @interface University { existing Logger with the same name.
String name(); It is a convention to define a Logger after the current
} class using class.getName() .
Logger logger =
Logger.getLogger(MyClass.class.getName());
Note: This method will throw NullPointerException if
the passed name is null. Note: If a logger's level is set to null , its level is
inherited from its parent and so on up the tree.
Each Logger has a level that determines the
importance of the log message. There are 7 basic log
levels:
2. Filters
Log Level (in descending Use A filter (if it is present) determines whether
order) the LogRecord should be forwarded or not. As the
SEVERE serious failure name suggests, it filters the log messages according to
WARNING warning message, a specific criteria.
potential problem A LogRecord is only passed from the logger to the log
INFO general runtime handler and from the log handler to external systems if
information it passes the specified criteria.
CONFIG configuration information // set a filter
FINE general developer logger.setFilter(filter);
information (tracing
messages) // get a filter
FINER detailed developer Filter filter = logger.getFilter();
information (tracing
messages) 3. Handlers(Appenders)
FINEST highly detailed developer The log handler or the appenders receive
information(tracing the LogRecord and exports it to various targets.
messages) Java SE provides 5 built-in handlers:
OFF turn off logging for all Handlers Use
levels (capture nothing) StreamHandler writes to an
OutputStream
Each log level has an integer value that determines ConsoleHandler writes to console
their severity except for two special log FileHandler writes to file
levels OFF and ALL . SocketHandler writes to remote TCP
ports
Logging the message MemoryHandler writes to memory
By default, the top three log levels are always logged.
To set a different level, we can use the following code: A handler can pass the LogRecord to a filter to again
logger.setLevel(Level.LogLevel); determine whether it can be forwarded to external
systems or not.
// example To add a new handler, we use the following code:
logger.setLevel(Level.FINE); logger.addHandler(handler);

In this example, only level FINE and levels above it // example


are set to be logged. All other log messages are Handler handler = new ConsoleHandler();
dropped. logger.addHandler(handler);
Now to log a message, we use the log() method.
To remove a handler, we use the following code:
logger.log(Level.LogLevel, "log message"); logger.removeHandler(handler);
// example // example
logger.log(Level.INFO, "This is INFO log level Handler handler = new ConsoleHandler();
message"); logger.addHandler(handler);
logger.removeHandler(handler);
There are shorthand methods for logging at desired
levels. A logger can have multiple handlers. To get all the
logger.info( "This is INFO log level message"); handlers, we use the following code:
logger.warning( "This is WARNING log level Handler[] handlers = logger.getHandlers();
message");
4. Formatters
All log requests that have passed the set log level are A handler can also use a Formatter to format
then forwarded to the LogRecord. the LogRecord object into a string before exporting it
to external systems.
Java SE has two built-in Formatters:
Formatters Use }
SimpleFormatter formats LogRecord to
string Output
XMLFormatter formats LogRecord to There are 3 weekends in a week
XML form
We get the above output because this program has no
We can use the following code to format a handler: compilation errors and by default, assertions are
// formats to string form disabled.
handler.setFormatter(new SimpleFormatter()); After enabling assertions, we get the following output:
Exception in thread "main" java.lang.AssertionError
// formats to XML form
handler.setFormatter(new XMLFormatter()); Another form of assertion statement
assert condition : expression;
LogManager
The LogManager object keeps track of the global In this form of assertion statement, an expression is
logging information. It reads and maintains the passed to the constructor of the AssertionError object.
logging configuration and the logger instances. This expression has a value that is displayed as the
The log manager is a singleton, which means that only error’s detail message if the condition is false .
one instance of it is instantiated. The detailed message is used to capture and transmit
To obtain the log manager instance, we use the the information of the assertion failure to help in
following code: debugging the problem.
LogManager manager = new LogManager();
Example 2: Java assertion with expression example
Advantages of Logging class Main {
Here are some of the advantages of logging in Java. public static void main(String args[]) {
 helps in monitoring the flow of the program String[] weekends = {"Friday", "Saturday",
 helps in capturing any errors that may occur "Sunday"};
 provides support for problem diagnosis and debugging assert weekends.length==2 : "There are only 2
weekends in a week";
Java Assertions System.out.println("There are " + weekends.length
Assertions in Java help to detect bugs by testing code + " weekends in a week");
we assume to be true. }
An assertion is made using the assert keyword. }
Its syntax is:
assert condition; Output
Exception in thread "main" java.lang.AssertionError:
Here, condition is a boolean expression that we There are only 2 weekends in a week
assume to be true when the program executes.
As we see from the above example, the expression is
Enabling Assertions passed to the constructor of the AssertionError object.
By default, assertions are disabled and ignored at If our assumption is false and assertions are enabled,
runtime. an exception is thrown with an appropriate message.
To enable assertions, we use: This message helps in diagnosing and fixing the error
java -ea:arguments that caused the assertion to fail.
OR
java -enableassertions:arguments Enabling assertion for specific classes and packages
If we do not provide any arguments to the assertion
When assertions are enabled and the condition command-line switches,
is true , the program executes normally. java –ea
But if the condition evaluates to false while assertions
This enables assertions in all classes except system
are enabled, JVM throws an AssertionError , and the
classes.
program stops immediately. We can also enable assertion for specific classes and
packages using arguments. The arguments that can be
Example 1: Java assertion provided to these command-line switches are:
class Main { Enable assertion in class names
public static void main(String args[]) {
String[] weekends = {"Friday", "Saturday", To enable assertion for all classes of our program
"Sunday"}; Main,
assert weekends.length == 2; java -ea Main
System.out.println("There are " + weekends.length
+ " weekends in a week"); To enable only one class,
} java -ea:AnimalClass Main
switch (dayOfWeek) {
This enables assertion in only the AnimalClass in case "Sunday":
the Main program. System.out.println("It’s Sunday!");
break;
Enable assertion in package names
case "Monday":
To enable assertions for package com.animal and its System.out.println("It’s Monday!");
sub-packages only, break;
java -ea:com.animal... Main case "Tuesday":
System.out.println("It’s Tuesday!");
Enable assertion in unnamed packages break;
To enable assertion in unnamed packages (when we case "Wednesday":
don’t use a package statement) in the current working System.out.println("It’s Wednesday!");
directory. break;
java -ea:... Main case "Thursday":
System.out.println("It’s Thursday!");
Enable assertion in system classes break;
To enable assertion in system classes, we use a case "Friday":
different command-line switch: System.out.println("It’s Friday!");
java -esa:arguments break;
OR case "Saturday":
java -enablesystemassertions:arguments System.out.println("It’s Saturday!");
The arguments that can be provided to these switches break;
are the same. }

Disabling Assertions The above switch statement indicates that the days of
To disable assertions, we use: the week can be only one of the above 7 values.
java -da arguments Having no default case means that the programmer
OR believes that one of these cases will always be
java -disableassertions arguments executed.
To disable assertion in system classes, we use: However, there might be some cases that have not yet
java -dsa:arguments been considered where the assumption is actually
OR false.
java -disablesystemassertions:arguments This assumption should be checked using an assertion
to make sure that the default switch case is not
The arguments that can be passed while disabling reached.
assertions are the same as while enabling them. default:
assert false: dayofWeek + " is invalid day";
Advantages of Assertion
1. Quick and efficient for detecting and correcting bugs. If dayOfWeek has a value other than the valid days,
2. Assertion checks are done only during development
an AssertionError is thrown.
and testing. They are automatically removed in the
production code at runtime so that it won’t slow the
execution of the program. 2. Documenting assumptions
3. It helps remove boilerplate code and make code more To document their underlying assumptions, many
readable. programmers use comments. Let’s take an example.
4. Refactors and optimizes code with increased if (i % 2 == 0) {
confidence that it functions correctly. ...
} else { // We know (i % 2 == 1)
When to use Assertions ...
1. Unreachable codes }
Unreachable codes are codes that do not execute when
we try to run the program. Use assertions to make sure Use assertions instead.
unreachable codes are actually unreachable. Comments can get out-of-date and out-of-sync as the
Let’s take an example. program grows. However, we will be forced to update
void unreachableCodeMethod() { the assert statements; otherwise, they might fail for
System.out.println("Reachable code"); valid conditions too.
return; if (i % 2 == 0) {
// Unreachable code ...
System.out.println("Unreachable code"); } else {
assert false; assert i % 2 == 1 : i;
} ...
}
Let’s take another example of a switch statement
without a default case.
When not to use Assertions
1. Argument checking in public methods Java List
Arguments in public methods may be provided by the
user.
So, if an assertion is used to check these arguments,
the conditions may fail and result in AssertionError .
Java Collections Framework
The Java collections framework provides a set of
Instead of using assertions, let it result in the
interfaces and classes to implement various data
appropriate runtime exceptions and handle these
structures and algorithms.
exceptions.
For example, the LinkedList class of the collections
2. To evaluate expressions that affect the program framework provides the implementation of the doubly-
operation linked list data structure.
Do not call methods or evaluate exceptions that can
later affect the program operation in assertion Interfaces of Collections FrameWork
conditions. The Java collections framework provides various
Let us take an example of a list weekdays which interfaces. These interfaces include several methods to
perform different operations on collections.
contains the names of all the days in a week.

ArrayList<String> weekdays = new


ArrayList<>(Arrays.asList("Sunday", "Monday",
"Tuesday", "Wednesday", "Thursday", "Friday",
"Saturday" ));

ArrayList<String> weekends= new


ArrayList<>(Arrays.asList("Sunday", "Saturday" ));

assert weekdays.removeAll(weekends); We will learn about these interfaces, their


subinterfaces, and implementation in various classes in
Here, we are trying to remove detail in the later chapters. Let's learn about the
elements Saturday and Sunday from the commonly used interfaces in brief in this tutorial.
ArrayList weekdays .
If the assertion is enabled, the program works fine. Java Collection Interface
However, if assertions are disabled, the elements from The Collection interface is the root interface of the
the list are not removed. This may result in program collections framework hierarchy.
failure. Java does not provide direct implementations of
Instead, assign the result to a variable and then use the Collection interface but provides implementations
that variable for assertion. of its subinterfaces like List , Set , and Queue .
ArrayList<String> weekdays = new
ArrayList<>(Arrays.asList("Sunday", "Monday", Collections Framework Vs. Collection Interface
"Tuesday", "Wednesday", "Thursday", "Friday", People often get confused between the collections
"Saturday" )); framework and Collection Interface.
ArrayList<String> weekends= new The Collection interface is the root interface of the
ArrayList<>(Arrays.asList("Sunday", "Saturday" )); collections framework. The framework includes other
interfaces as well: Map and Iterator . These interfaces
boolean weekendsRemoved = may also have subinterfaces.
weekdays.removeAll(weekends);
assert weekendsRemoved; Subinterfaces of the Collection Interface

In this way, we can ensure that all the weekends are As mentioned earlier, the Collection interface
removed from the weekdays regardless of the includes subinterfaces that are implemented by Java
assertion being enabled or disabled. As a result, it does classes.
not affect the program operation in the future. All the methods of the Collection interface are also
present in its subinterfaces.
Here are the subinterfaces of the Collection Interface:

List Interface
The List interface is an ordered collection that allows
us to add and remove elements like an array.
Set Interface ArrayList: [Dog, Cat, Horse]
The Set interface allows us to store elements in
different sets similar to the set in mathematics. It In the later tutorials, we will learn about the
cannot have duplicate elements. collections framework (its interfaces and classes) in
detail with the help of examples.
Queue Interface
The Queue interface is used when we want to store Java Collection Interface
and access elements in First In, First Out manner. The Collection interface is the root interface of the
Java collections framework.
Java Map Interface There is no direct implementation of this interface.
In Java, the Map interface allows elements to be However, it is implemented through its subinterfaces
stored in key/value pairs. Keys are unique names that like List , Set , and Queue .
can be used to access a particular element in a map. For example, the ArrayList class implements
And, each key has a single value associated with it. the List interface which is a subinterface of
the Collection Interface.
Java Iterator Interface
In Java, the Iterator interface provides methods that
can be used to access elements of collections.

Why the Collections Framework?


The Java collections framework provides various data
structures and algorithms that can be used directly.
This has two main advantages:
 We do not have to write code to implement these data
structures and algorithms manually.
 Our code will be much more efficient as the
collections framework is highly optimized.
Moreover, the collections framework allows us to use
a specific data structure for a particular type of data.
Here are a few examples, Subinterfaces of Collection
 If we want our data to be unique, then we can use As mentioned above, the Collection interface includes
the Set interface provided by the collections subinterfaces that are implemented by various classes
framework. in Java.
 To store data in key/value pairs, we can use
the Map interface. 1. List Interface
The List interface is an ordered collection that allows
 The ArrayList class provides the functionality of
us to add and remove elements like an array.
resizable arrays.

2. Set Interface
Example: ArrayList Class of Collections
Before we wrap up this tutorial, let's take an example The Set interface allows us to store elements in
of the ArrayList class of the collections framework. different sets similar to the set in mathematics. It
The ArrayList class allows us to create resizable cannot have duplicate elements.
arrays. The class implements the List interface (which
3. Queue Interface
is a subinterface of the Collection interface). The Queue interface is used when we want to store
// The Collections framework is defined in the and access elements in First In, First
java.util package Out(FIFO) manner.
import java.util.ArrayList;
Methods of Collection
class Main {
The Collection interface includes various methods
public static void main(String[] args){
ArrayList<String> animals = new ArrayList<>(); that can be used to perform different operations on
// Add elements objects. These methods are available in all its
animals.add("Dog"); subinterfaces.
animals.add("Cat");  add() - inserts the specified element to the collection
animals.add("Horse");  size() - returns the size of the collection
 remove() - removes the specified element from the
System.out.println("ArrayList: " + animals); collection
}
 iterator() - returns an iterator to access elements of the
}
collection
Output:
 addAll() - adds all the elements of a specified elements of lists
collection to the collection set() changes elements of lists
 removeAll() - removes all the elements of the specified remove() removes an element from the list
collection from the collection removeAll() removes all the elements from
the list
 clear() - removes all the elements of the collection
clear() removes all the elements from
the list (more efficient than
Java List removeAll())
In Java, the List interface is an ordered collection that size() returns the length of lists
allows us to store and access elements sequentially. It toArray() converts a list into an array
extends the Collection interface. contains() returns true if a list contains
specific element
Classes that Implement List
Since List is an interface, we cannot create objects Implementation of the List Interface
from it. 1. Implementing the ArrayList Class
In order to use the functionalities of the List interface, import java.util.List;
we can use these classes: import java.util.ArrayList;
 ArrayList
 LinkedList class Main {
 Vector
 Stack public static void main(String[] args) {
 // Creating list using the ArrayList class
List<Integer> numbers = new ArrayList<>();

// Add elements to the list


numbers.add(1);
numbers.add(2);
numbers.add(3);
System.out.println("List: " + numbers);
These classes are defined in the Collections
framework and implement the List interface. // Access element from the list
int number = numbers.get(2);
How to use List? System.out.println("Accessed Element: " +
In Java, we must import java.util.List package in number);
order to use List .
// ArrayList implementation of List // Remove element from the list
List<String> list1 = new ArrayList<>(); int removedNumber = numbers.remove(1);
System.out.println("Removed Element: " +
// LinkedList implementation of List removedNumber);
List<String> list2 = new LinkedList<>(); }
}
Here, we have created objects list1 and list2 of
Output
classes ArrayList and LinkedList . These objects can List: [1, 2, 3]
use the functionalities of the List interface. Accessed Element: 3
Removed Element: 2
Methods of List
AD 2. Implementing the LinkedList Class
The List interface includes all the methods of import java.util.List;
the Collection interface. Its because Collection is a import java.util.LinkedList;
super interface of List .
class Main {
Some of the commonly used methods of
the Collection interface that's also available in public static void main(String[] args) {
the List interface are: // Creating list using the LinkedList class
Methods Description List<Integer> numbers = new LinkedList<>();
add() adds an element to a list
addAll() adds all elements of one list to // Add elements to the list
another numbers.add(1);
get() helps to randomly access numbers.add(2);
elements from lists numbers.add(3);
iterator() returns iterator object that can be System.out.println("List: " + numbers);
used to sequentially access
// Access element from the list Java ArrayList Vs Array
int number = numbers.get(2); In Java, we need to declare the size of an array before
System.out.println("Accessed Element: " + we can use it. Once the size of an array is declared, it's
number); hard to change it.
To handle this issue, we can use the ArrayList class.
// Using the indexOf() method It allows us to create resizable arrays.
int index = numbers.indexOf(2); Unlike arrays, arraylists can automatically adjust their
System.out.println("Position of 3 is " + index); capacity when we add or remove elements from them.
Hence, arraylists are also known as dynamic arrays.
// Remove element from the list
int removedNumber = numbers.remove(1); Creating an ArrayList
System.out.println("Removed Element: " + Before using ArrayList , we need to import
removedNumber);
} the java.util.ArrayList package first. Here is how we
} can create arraylists in Java:
ArrayList<Type> arrayList= new ArrayList<>();
Output
List: [1, 2, 3] Here, Type indicates the type of an arraylist. For
Accessed Element: 3 example,
Position of 3 is 1 // create Integer type arraylist
Removed Element: 2 ArrayList<Integer> arrayList = new ArrayList<>();

// create String type arraylist


Java List vs. Set ArrayList<String> arrayList = new ArrayList<>();
Both the List interface and the Set interface inherit
the Collection interface. However, there exists some In the above program, we have used Integer not int. It
difference between them. is because we cannot use primitive types while
 Lists can include duplicate elements. However, sets creating an arraylist. Instead, we have to use the
cannot have duplicate elements. corresponding wrapper classes.
 Elements in lists are stored in some order. However, Here, Integer is the corresponding wrapper class
elements in sets are stored in groups like sets in of int .
mathematics.
Now that we know what List is, we will see its Example: Create ArrayList in Java
implementations in ArrayList and LinkedList classes import java.util.ArrayList;
in detail in the next tutorials.
class Main {
public static void main(String[] args){
Java ArrayList
In Java, we use the ArrayList class to implement the // create ArrayList
ArrayList<String> languages = new ArrayList<>();
functionality of resizable-arrays.
It implements the List interface of the collections
framework . // Add elements to ArrayList
languages.add("Java");
languages.add("Python");
languages.add("Swift");
System.out.println("ArrayList: " + languages);
}
}

Output
ArrayList: [Java, Python, Swift]

In the above example, we have created


an ArrayList named languages .
Here, we have used the add() method to add elements
to the arraylist. We will learn more about
the add() method later in this tutorial.

Java ArrayList Basic Operations on ArrayList


Implementation The ArrayList class provides various methods to
perform different operations on arraylists. We will
look at some commonly used arraylist operations in Element at index 1: Dog
this tutorial:
 Add elements In the above example, we have used the get() method
 Access elements with parameter 1 . Here, the method returns the
 Change elements
element at index 1.
 Remove elements
.
1. Add Elements to an ArrayList We can also access elements of the ArrayList using
To add a single element to the arraylist, we use the iterator() method.
the add() method of the ArrayList class. For
example, 3. Change ArrayList Elements
import java.util.ArrayList;
To change elements of the arraylist, we use
class Main { the set() method of the ArrayList class. For example,
public static void main(String[] args){ import java.util.ArrayList;
// create ArrayList
ArrayList<String> languages = new ArrayList<>(); class Main {
public static void main(String[] args) {
// add() method without the index parameter ArrayList<String> languages = new ArrayList<>();
languages.add("Java");
// add elements in the array list
languages.add("C"); languages.add("Java");
languages.add("Python"); languages.add("Kotlin");
System.out.println("ArrayList: " + languages); languages.add("C++");
} System.out.println("ArrayList: " + languages);
}
// change the element of the array list
Output languages.set(2, "JavaScript");
ArrayList: [Java, C, Python]
System.out.println("Modified ArrayList: " +
In the above example, we have created languages);
an ArrayList named languages . Here, we have used }
the add() method to add elements to languages . }
.
Output
Other Ways to Add Elements to Arraylist
ArrayList: [Java, Kotlin, C++]
How to add an element at a specified position in an
Modified ArrayList: [Java, Kotlin, JavaScript]
ArrayList?
How to add all elements of a set to an arraylist?
In the above example, we have created
2. Access ArrayList Elements an ArrayList named languages . Notice the line,
To access an element from the arraylist, we use language.set(2, "JavaScript");
the get() method of the ArrayList class. For example,
import java.util.ArrayList; Here, the set() method changes the element at index
2 to JavaScript .
class Main {
public static void main(String[] args) {
ArrayList<String> animals = new ArrayList<>(); 4. Remove ArrayList Elements
To remove an element from the arraylist, we can use
// add elements in the arraylist the remove() method of the ArrayList class. For
animals.add("Cat"); example,
animals.add("Dog"); import java.util.ArrayList;
animals.add("Cow");
System.out.println("ArrayList: " + animals); class Main {
public static void main(String[] args) {
// get the element from the arraylist ArrayList<String> animals = new ArrayList<>();
String str = animals.get(1);
// add elements in the array list
System.out.print("Element at index 1: " + str); animals.add("Dog");
} animals.add("Cat");
} animals.add("Horse");
System.out.println("ArrayList: " + animals);
Output
ArrayList: [Cat, Dog, Cow]
// remove element from index 2
String str = animals.remove(2); // iterate using for-each loop
System.out.println("Accessing individual elements:
System.out.println("Updated ArrayList: " + ");
animals);
System.out.println("Removed Element: " + str); for (String language : animals) {
} System.out.print(language);
} System.out.print(", ");
}
Output
ArrayList: [Dog, Cat, Horse] }
Updated ArrayList: [Dog, Cat] }
Removed Element: Horse
Output
Here, the remove() method takes the index number as ArrayList: [Cow, Cat, Dog]
the parameter. And, removes the element specified by Accessing individual elements:
the index number. Cow, Cat, Dog,

We can also remove all the elements from the arraylist


at once. Java Vector
The Vector class is an implementation of
Methods of ArrayList Class the List interface that allows us to create resizable-
In the previous section, we have learned about arrays similar to the ArrayList class.
the add() , get() , set() , and remove() method of
the ArrayList class. Java Vector vs. ArrayList
Besides those basic methods, here are some In Java, both ArrayList and Vector implements
more ArrayList methods that are commonly used. the List interface and provides the same
Methods Descriptions functionalities. However, there exist some differences
size() Returns the length of the between them.
arraylist. The Vector class synchronizes each individual
sort() Sort the arraylist operation. This means whenever we want to perform
elements. some operation on vectors, the Vector class
clone() Creates a new arraylist automatically applies a lock to that operation.
with the same element, It is because when one thread is accessing a vector,
size, and capacity. and at the same time another thread tries to access it,
contains() Searches the arraylist for an exception
the specified element and called ConcurrentModificationException is
returns a boolean result.
generated. Hence, this continuous use of lock for each
ensureCapacity() Specifies the total element
operation makes vectors less efficient.
the arraylist can contain.
However, in array lists, methods are not synchronized.
isEmpty() Checks if the arraylist is Instead, it uses
empty.
the Collections.synchronizedList() method that
indexOf() Searches a specified
element in an arraylist synchronizes the list as a whole.
and returns the index of
the element. Note: It is recommended to use ArrayList in place
of Vector because vectors less efficient.

Iterate through an ArrayList Creating a Vector


We can use the Java for-each loop to loop through Here is how we can create vectors in Java.
each element of the arraylist. For example, Vector<Type> vector = new Vector<>();
import java.util.ArrayList;
Here, Type indicates the type of a linked list. For
class Main {
example,
public static void main(String[] args) {
// create Integer type linked list
Vector<Integer> vector= new Vector<>();
// creating an array list
ArrayList<String> animals = new ArrayList<>();
// create String type linked list
animals.add("Cow");
Vector<String> vector= new Vector<>();
animals.add("Cat");
animals.add("Dog");
System.out.println("ArrayList: " + animals);
System.out.print("Vector: ");
Methods of Vector while(iterate.hasNext()) {
System.out.print(iterate.next());
The Vector class also provides the resizable-array System.out.print(", ");
implementations of the List interface (similar to }
}
the ArrayList class). Some of the Vector methods are: }

Add Elements to Vector Output


 add(element) - adds an element to vectors Element at index 2: Cat
 add(index, element) - adds an element to the specified Vector: Dog, Horse, Cat,
position
 addAll(vector) - adds all elements of a vector to Remove Vector Elements
another vector  remove(index) - removes an element from specified
For example, position
import java.util.Vector;  removeAll() - removes all the elements
 clear() - removes all elements. It is more efficient
class Main { than removeAll()
public static void main(String[] args) {
For example,
Vector<String> mammals= new Vector<>();
import java.util.Vector;
// Using the add() method
class Main {
mammals.add("Dog");
public static void main(String[] args) {
mammals.add("Horse");
Vector<String> animals= new Vector<>();
animals.add("Dog");
// Using index number
animals.add("Horse");
mammals.add(2, "Cat");
animals.add("Cat");
System.out.println("Vector: " + mammals);
System.out.println("Initial Vector: " + animals);
// Using addAll()
Vector<String> animals = new Vector<>();
// Using remove()
animals.add("Crocodile");
String element = animals.remove(1);
System.out.println("Removed Element: " +
animals.addAll(mammals);
element);
System.out.println("New Vector: " + animals);
System.out.println("New Vector: " + animals);
}
}
// Using clear()
Output
animals.clear();
Vector: [Dog, Horse, Cat]
System.out.println("Vector after clear(): " +
New Vector: [Crocodile, Dog, Horse, Cat]
animals);
}
Access Vector Elements
}
 get(index) - returns an element specified by the index
 iterator() - returns an iterator object to sequentially Output
access vector elements Initial Vector: [Dog, Horse, Cat]
For example, Removed Element: Horse
import java.util.Iterator; New Vector: [Dog, Cat]
import java.util.Vector; Vector after clear(): []

class Main { Others Vector Methods


public static void main(String[] args) { Methods Descriptions
Vector<String> animals= new Vector<>(); set() changes an element of the
animals.add("Dog"); vector
animals.add("Horse"); size() returns the size of the
animals.add("Cat"); vector
toArray() converts the vector into
// Using get() an array
String element = animals.get(2); toString() converts the vector into a
System.out.println("Element at index 2: " + String
element); contains() searches the vector for
specified element and
// Using iterator() returns a boolean result
Iterator<String> iterate = animals.iterator();
Java Stack Class // Create String type stack
Stack<String> stacks = new Stack<>();
The Java collections framework has a class
named Stack that provides the functionality of the Stack Methods
stack data structure. Since Stack extends the Vector class, it inherits all the
The Stack class extends the Vector class. methods Vector .

Besides these methods, the Stack class includes 5


more methods that distinguish it from Vector .

push() Method

To add an element to the top of the stack, we use


the push() method. For example,
import java.util.Stack;

class Main {
public static void main(String[] args) {
Stack<String> animals= new Stack<>();

// Add elements to Stack


animals.push("Dog");
animals.push("Horse");
animals.push("Cat");

System.out.println("Stack: " + animals);


}
Stack Implementation }
In stack, elements are stored and accessed in Last In
First Out manner. That is, elements are added to the Output
top of the stack and removed from the top of the stack. Stack: [Dog, Horse, Cat]

pop() Method
To remove an element from the top of the stack, we
use the pop() method. For example,
import java.util.Stack;

class Main {
public static void main(String[] args) {
Stack<String> animals= new Stack<>();

// Add elements to Stack


animals.push("Dog");
animals.push("Horse");
animals.push("Cat");
System.out.println("Initial Stack: " + animals);

// Remove element stacks


String element = animals.pop();
System.out.println("Removed Element: " +
element);
}
Creating a Stack }
In order to create a stack, we must import
the java.util.Stack package first. Once we import the Output
package, here is how we can create a stack in Java. Initial Stack: [Dog, Horse, Cat]
Stack<Type> stacks = new Stack<>(); Removed Element: Cat

Here, Type indicates the stack's type. For example, peek() Method
// Create Integer type stack The peek() method returns an object from the top of
Stack<Integer> stacks = new Stack<>(); the stack. For example,
import java.util.Stack;
System.out.println("Stack: " + animals);
class Main {
public static void main(String[] args) { // Check if stack is empty
Stack<String> animals= new Stack<>(); boolean result = animals.empty();
System.out.println("Is the stack empty? " +
// Add elements to Stack result);
animals.push("Dog"); }
animals.push("Horse"); }
animals.push("Cat");
System.out.println("Stack: " + animals); Output
Stack: [Dog, Horse, Cat]
// Access element from the top Is the stack empty? False
String element = animals.peek();
System.out.println("Element at top: " + element); Use ArrayDeque Instead of Stack
The Stack class provides the direct implementation of
} the stack data structure. However, it is recommended
} not to use it. Instead, use the ArrayDeque class
Output (implements the Deque interface) to implement the
Stack: [Dog, Horse, Cat] stack data structure in Java.
Element at top: Cat

search() Method
To search an element in the stack, we use Java Queue
the search() method. It returns the position of the
element from the top of the stack. For example,
import java.util.Stack;
Java Queue Interface
class Main { The Queue interface of the Java collections
public static void main(String[] args) {
framework provides the functionality of the queue
Stack<String> animals= new Stack<>();
data structure. It extends the Collection interface.
// Add elements to Stack
animals.push("Dog"); Classes that Implement Queue
animals.push("Horse"); Since the Queue is an interface, we cannot provide
animals.push("Cat"); the direct implementation of it.
System.out.println("Stack: " + animals); In order to use the functionalities of Queue , we need
to use classes that implement it:
// Search an element  ArrayDeque
int position = animals.search("Horse");  LinkedList
System.out.println("Position of Horse: " +  PriorityQueue
position);
}
}

Output
Stack: [Dog, Horse, Cat]
Position of Horse: 2

empty() Method
To check whether a stack is empty or not, we use Interfaces that extend Queue
the empty() metho The Queue interface is also extended by various
d. For example, subinterfaces:
import java.util.Stack;  Deque
class Main {  BlockingQueue
public static void main(String[] args) {  BlockingDeque
Stack<String> animals= new Stack<>();

// Add elements to Stack


animals.push("Dog");
animals.push("Horse");
animals.push("Cat");
import java.util.LinkedList;

class Main {

public static void main(String[] args) {


// Creating Queue using the LinkedList class
Queue<Integer> numbers = new LinkedList<>();

Working of Queue Data Structure // offer elements to the Queue


In queues, elements are stored and accessed in First numbers.offer(1);
In, First Out manner. That is, elements are added numbers.offer(2);
from the behind and removed from the front. numbers.offer(3);
System.out.println("Queue: " + numbers);

// Access elements of the Queue


int accessedNumber = numbers.peek();
System.out.println("Accessed Element: " +
accessedNumber);

How to use Queue? // Remove elements from the Queue


In Java, we must import java.util.Queue package in int removedNumber = numbers.poll();
order to use Queue . System.out.println("Removed Element: " +
removedNumber);
// LinkedList implementation of Queue
Queue<String> animal1 = new LinkedList<>();
System.out.println("Updated Queue: " +
numbers);
// Array implementation of Queue
}
Queue<String> animal2 = new ArrayDeque<>();
}
// Priority Queue implementation of Queue
Queue<String> animal3 = new PriorityQueue<>(); Output
Queue: [1, 2, 3]
Accessed Element: 1
Here, we have created
Removed Element: 1
objects animal1 , animal2 and animal3 of
Updated Queue: [2, 3]
classes LinkedList , ArrayDeque and PriorityQueue r
espectively. These objects can use the functionalities of 2. Implementing the PriorityQueue Class
the Queue interface. import java.util.Queue;
import java.util.PriorityQueue;
Methods of Queue
The Queue interface includes all the methods of class Main {
the Collection interface. It is because Collection is
public static void main(String[] args) {
the super interface of Queue . // Creating Queue using the PriorityQueue class
Some of the commonly used methods of Queue<Integer> numbers = new
the Queue interface are: PriorityQueue<>();
 add() - Inserts the specified element into the queue. If
the task is successful, add() returns true , if not it // offer elements to the Queue
throws an exception. numbers.offer(5);
 offer() - Inserts the specified element into the queue. If numbers.offer(1);
numbers.offer(2);
the task is successful, offer() returns true , if not it
System.out.println("Queue: " + numbers);
returns false .
 element() - Returns the head of the queue. Throws an // Access elements of the Queue
exception if the queue is empty. int accessedNumber = numbers.peek();
 peek() - Returns the head of the queue. Returns null if System.out.println("Accessed Element: " +
the queue is empty. accessedNumber);
 remove() - Returns and removes the head of the
queue. Throws an exception if the queue is empty. // Remove elements from the Queue
 poll() - Returns and removes the head of the queue. int removedNumber = numbers.poll();
Returns null if the queue is empty. System.out.println("Removed Element: " +
removedNumber);
Implementation of the Queue Interface
1. Implementing the LinkedList Class
System.out.println("Updated Queue: " +
import java.util.Queue;
numbers);
}
} Insert Elements to PriorityQueue
 add() - Inserts the specified element to the queue. If
Output the queue is full, it throws an exception.
Queue: [1, 5, 2]  offer() - Inserts the specified element to the queue. If
Accessed Element: 1
Removed Element: 1 the queue is full, it returns false .
Updated Queue: [2, 5] For example,
import java.util.PriorityQueue;

class Main {
Java PriorityQueue public static void main(String[] args) {
The PriorityQueue class provides the functionality of
the heap data structure. // Creating a priority queue
It implements the Queue interface. PriorityQueue<Integer> numbers = new
PriorityQueue<>();

// Using the add() method


numbers.add(4);
numbers.add(2);
System.out.println("PriorityQueue: " + numbers);

// Using the offer() method


numbers.offer(1);
System.out.println("Updated PriorityQueue: " +
numbers);
}
}

Output
PriorityQueue: [2, 4]
Updated PriorityQueue: [1, 4, 2]
Unlike normal queues, priority queue elements are
Here, we have created a priority queue
retrieved in sorted order.
Suppose, we want to retrieve elements in the named numbers . We have inserted 4 and 2 to the
ascending order. In this case, the head of the priority queue.
queue will be the smallest element. Once this element Although 4 is inserted before 2, the head of the queue
is retrieved, the next smallest element will be the head is 2. It is because the head of the priority queue is the
of the queue. smallest element of the queue.
It is important to note that the elements of a priority We have then inserted 1 to the queue. The queue is
queue may not be sorted. However, elements are now rearranged to store the smallest element 1 to the
always retrieved in sorted order. head of the queue.

Creating PriorityQueue Access PriorityQueue Elements


In order to create a priority queue, we must import To access elements from a priority queue, we can use
the java.util.PriorityQueue package. Once we import the peek() method. This method returns the head of
the package, here is how we can create a priority the queue. For example,
queue in Java. import java.util.PriorityQueue;
PriorityQueue<Integer> numbers = new
PriorityQueue<>(); class Main {
public static void main(String[] args) {
Here, we have created a priority queue without any
arguments. In this case, the head of the priority queue // Creating a priority queue
is the smallest element of the queue. And elements are PriorityQueue<Integer> numbers = new
removed in ascending order from the queue. PriorityQueue<>();
However, we can customize the ordering of elements numbers.add(4);
with the help of the Comparator interface. We will numbers.add(2);
numbers.add(1);
learn about that later in this tutorial.
System.out.println("PriorityQueue: " + numbers);
Methods of PriorityQueue
// Using the peek() method
The PriorityQueue class provides the implementation int number = numbers.peek();
of all the methods present in the Queue interface.
System.out.println("Accessed Element: " +
number); //Using the iterator() method
} Iterator<Integer> iterate = numbers.iterator();
} while(iterate.hasNext()) {
System.out.print(iterate.next());
Output System.out.print(", ");
PriorityQueue: [1, 4, 2] }
Accessed Element: 1 }
}
Remove PriorityQueue Elements
 remove() - removes the specified element from the Output
queue PriorityQueue using iterator(): 1, 4, 2,
 poll() - returns and removes the head of the queue
Other PriorityQueue Methods
For example,
import java.util.PriorityQueue; Methods Descriptions
contains(element) Searches the priority queue
class Main { for the specified element. If
public static void main(String[] args) { the element is found, it
returns true, if not it returns
// Creating a priority queue false.
PriorityQueue<Integer> numbers = new size() Returns the length of the
PriorityQueue<>(); priority queue.
numbers.add(4); toArray() Converts a priority queue to
numbers.add(2); an array and returns it.
numbers.add(1);
System.out.println("PriorityQueue: " + numbers); PriorityQueue Comparator
In all the examples above, priority queue elements are
// Using the remove() method retrieved in the natural order (ascending order).
boolean result = numbers.remove(2); However, we can customize this ordering.
System.out.println("Is the element 2 removed? " For this, we need to create our own comparator class
+ result); that implements the Comparator interface. For
example,
// Using the poll() method import java.util.PriorityQueue;
int number = numbers.poll(); import java.util.Comparator;
System.out.println("Removed Element Using class Main {
poll(): " + number); public static void main(String[] args) {
}
} // Creating a priority queue
PriorityQueue<Integer> numbers = new
Output PriorityQueue<>(new CustomComparator());
PriorityQueue: [1, 4, 2] numbers.add(4);
Is the element 2 removed? true numbers.add(2);
Removed Element Using poll(): 1 numbers.add(1);
numbers.add(3);
Iterating Over a PriorityQueue System.out.print("PriorityQueue: " + numbers);
To iterate over the elements of a priority queue, we }
can use the iterator() method. In order to use this }
method, we must import
the java.util.Iterator package. For example, class CustomComparator implements
import java.util.PriorityQueue; Comparator<Integer> {
import java.util.Iterator;
@Override
class Main { public int compare(Integer number1, Integer
public static void main(String[] args) { number2) {
int value = number1.compareTo(number2);
// Creating a priority queue // elements are sorted in reverse order
PriorityQueue<Integer> numbers = new if (value > 0) {
PriorityQueue<>(); return -1;
numbers.add(4); }
numbers.add(2); else if (value < 0) {
numbers.add(1); return 1;
System.out.print("PriorityQueue using iterator(): }
"); else {
return 0; These objects can use the functionalities of
} the Deque interface.
}
} Methods of Deque
Since Deque extends the Queue interface, it inherits
Output
all the methods of the Queue interface.
PriorityQueue: [4, 3, 1, 2]

In the above example, we have created a priority Besides methods available in the Queue interface,
queue passing CustomComparator class as an the Deque interface also includes the following
argument. methods:

The CustomComparator class implements
 addFirst() - Adds the specified element at the
the Comparator interface. beginning of the deque. Throws an exception if the
We then override the compare() method. The method deque is full.
now causes the head of the element to be the largest 
number.  addLast() - Adds the specified element at the end of
the deque. Throws an exception if the deque is full.
Java Deque Interface 
The Deque interface of the Java collections  offerFirst() - Adds the specified element at the
framework provides the functionality of a double- beginning of the deque. Returns false if the deque is
ended queue. It extends the Queue interface. full.

 offerLast() - Adds the specified element at the end of
Working of Deque
In a regular queue, elements are added from the rear the deque. Returns false if the deque is full.
and removed from the front. However, in a deque, we 
can insert and remove elements from both front and  getFirst() - Returns the first element of the deque.
rear. Throws an exception if the deque is empty.

 getLast() - Returns the last element of the deque.
Throws an exception if the deque is empty.

 peekFirst() - Returns the first element of the deque.
Classes that implement Deque Returns null if the deque is empty.
In order to use the functionalities of

the Deque interface, we need to use classes that  peekLast() - Returns the last element of the deque.
implement it: Returns null if the deque is empty.
 ArrayDeque

 LinkedList
 removeFirst() - Returns and removes the first element
of the deque. Throws an exception if the deque is
empty.

 removeLast() - Returns and removes the last element
of the deque. Throws an exception if the deque is
empty.

 pollFirst() - Returns and removes the first element of
the deque. Returns null if the deque is empty.

How to use Deque?  pollLast() - Returns and removes the last element of
In Java, we must import the java.util.Deque package the deque. Returns null if the deque is empty.
to use Deque . 
// Array implementation of Deque Deque as Stack Data Structure
Deque<String> animal1 = new ArrayDeque<>(); The Stack class of the Java Collections
framework provides the implementation of the stack.
// LinkedList implementation of Deque However, it is recommended to use Deque as a stack
Deque<String> animal2 = new LinkedList<>(); instead of the Stack class. It is because methods
of Stack are synchronized.
Here, we have created
Here are the methods the Deque interface provides to
objects animal1 and animal2 of
implement stack:
classes ArrayDeque and LinkedList , respectively.  push() - adds an element at the beginning of deque
 pop() - removes an element from the beginning of
deque
 peek() - returns an element from the beginning of
deque

Implementation of Deque in ArrayDeque Class
import java.util.Deque;
import java.util.ArrayDeque;

class Main {
Java Doubly LinkedList
public static void main(String[] args) { Each element in a linked list is known as a node. It
// Creating Deque using the ArrayDeque class consists of 3 fields:
Deque<Integer> numbers = new  Prev - stores an address of the previous element in the
ArrayDeque<>();
list. It is null for the first element
// add elements to the Deque  Next - stores an address of the next element in the list.
numbers.offer(1); It is null for the last element
numbers.offerLast(2);  Data - stores the actual data
numbers.offerFirst(3); 
System.out.println("Deque: " + numbers); Creating a Java LinkedList
Here is how we can create linked lists in Java:
// Access elements of the Deque LinkedList<Type> linkedList = new LinkedList<>();
int firstElement = numbers.peekFirst();
System.out.println("First Element: " + Here, Type indicates the type of a linked list. For
firstElement); example,
// create Integer type linked list
int lastElement = numbers.peekLast(); LinkedList<Integer> linkedList = new
System.out.println("Last Element: " + LinkedList<>();
lastElement); // create String type linked list
LinkedList<String> linkedList = new LinkedList<>();
// Remove elements from the Deque
int removedNumber1 = numbers.pollFirst(); Example: Create LinkedList in Java
System.out.println("Removed First Element: " + import java.util.LinkedList;
removedNumber1);
class Main {
int removedNumber2 = numbers.pollLast(); public static void main(String[] args){
System.out.println("Removed Last Element: " +
removedNumber2); // create linkedlist
LinkedList<String> animals = new LinkedList<>();
System.out.println("Updated Deque: " +
numbers); // Add elements to LinkedList
} animals.add("Dog");
} animals.add("Cat");
animals.add("Cow");
System.out.println("LinkedList: " + animals);
Output }
Deque: [3, 1, 2] }
First Element: 3
Last Element: 2 Output
Removed First Element: 3 LinkedList: [Dog, Cat, Cow]
Removed Last Element: 2
Updated Deque: [1] In the above example, we have created
a LinkedList named animals .
Java LinkedList
Here, we have used the add() method to add elements
The LinkedList class of the Java collections
to the LinkedList. We will learn more about
framework provides the functionality of the linked list
the add() method later in this tutorial.
data structure (doubly linkedlist).
Working of a Java LinkedList
Elements in linked lists are not stored in sequence.
Instead, they are scattered and connected through
links (Prev and Next).
Java LinkedList Implementation In the above example, we have created a LinkedList
Here we have 3 elements in a linked list. named animals . Here, we have used
 Dog - it is the first element that holds null as previous the add() method to add elements to animals .
address and the address of Cat as the next address Notice the statement,
 Cat - it is the second element that holds an address animals.add(1, "Horse");
of Dog as the previous address and the address
Here, we have used the index number parameter. It is
of Cow as the next address an optional parameter that specifies the position where
 Cow - it is the last element that holds the address the new element is added.
of Cat as the previous address and null as the next
element
2. Access LinkedList elements
The get() method of the LinkedList class is used to
Methods of Java LinkedList access an element from the LinkedList. For example,
LinkedList provides various methods that allow us to import java.util.LinkedList;
perform different operations in linked lists. We will
look at four commonly used LinkedList Operators in class Main {
this tutorial: public static void main(String[] args) {
 Add elements LinkedList<String> languages = new
 Access elements LinkedList<>();
 Change elements
 Remove elements // add elements in the linked list
languages.add("Python");
1. Add elements to a LinkedList languages.add("Java");
We can use the add() method to add an element languages.add("JavaScript");
(node) at the end of the LinkedList. For example, System.out.println("LinkedList: " + languages);
import java.util.LinkedList;
// get the element from the linked list
class Main { String str = languages.get(1);
public static void main(String[] args){ System.out.print("Element at index 1: " + str);
// create linkedlist }
LinkedList<String> animals = new LinkedList<>(); }

// add() method without the index parameter Output


animals.add("Dog"); LinkedList: [Python, Java, JavaScript]
animals.add("Cat"); Element at index 1: Java
animals.add("Cow");
System.out.println("LinkedList: " + animals); In the above example, we have used the get() method
with parameter 1. Here, the method returns the
// add() method with the index parameter element at index 1.
animals.add(1, "Horse"); We can also access elements of the LinkedList using
System.out.println("Updated LinkedList: " + the iterator() and the listIterator() method.
animals);
} 3. Change Elements of a LinkedList
} The set() method of LinkedList class is used to
change elements of the LinkedList. For example,
Output import java.util.LinkedList;
LinkedList: [Dog, Cat, Cow]
Updated LinkedList: [Dog, Horse, Cat, Cow] class Main {
public static void main(String[] args) {
LinkedList<String> languages = new Here, the remove() method takes the index number as
LinkedList<>(); the parameter. And, removes the element specified by
the index number.
// add elements in the linked list
languages.add("Java");
languages.add("Python"); Other Methods
languages.add("JavaScript"); Methods Description
languages.add("Java"); contains() checks if the LinkedList
System.out.println("LinkedList: " + languages); contains the element
indexOf() returns the index of the
// change elements at index 3 first occurrence of the
languages.set(3, "Kotlin"); element
System.out.println("Updated LinkedList: " + lastIndexOf() returns the index of the
languages); last occurrence of the
} element
}
clear() removes all the elements
of the LinkedList
Output
iterator() returns an iterator to
LinkedList: [Java, Python, JavaScript, Java]
iterate over LinkedList
Updated LinkedList: [Java, Python, JavaScript,
Kotlin]
LinkedList as Deque and Queue
In the above example, we have created a LinkedList Since the LinkedList class also implements
named languages. Notice the line, the Queue and the Deque interface, it can implement
languages.set(3, "Kotlin"); methods of these interfaces as well. Here are some of
the commonly used methods:
Here, the set() method changes the element at Methods Descriptions
addFirst() adds the specified element
index 3 to Kotlin .
at the beginning of the
linked list
4. Remove element from a LinkedList addLast() adds the specified element
The remove() method of the LinkedList class is used at the end of the linked
to remove an element from the LinkedList. For list
example, getFirst() returns the first element
import java.util.LinkedList; getLast() returns the last element
removeFirst() removes the first element
class Main { removeLast() removes the last element
public static void main(String[] args) { peek() returns the first element
LinkedList<String> languages = new (head) of the linked list
LinkedList<>(); poll() returns and removes the
first element from the
// add elements in LinkedList linked list
languages.add("Java"); offer() adds the specified element
languages.add("Python"); at the end of the linked
languages.add("JavaScript"); list
languages.add("Kotlin");
System.out.println("LinkedList: " + languages);
Example: Java LinkedList as Queue
import java.util.LinkedList;
// remove elements from index 1
import java.util.Queue;
String str = languages.remove(1);
System.out.println("Removed Element: " + str);
class Main {
public static void main(String[] args) {
System.out.println("Updated LinkedList: " +
Queue<String> languages = new LinkedList<>();
languages);
}
// add elements
}
languages.add("Python");
languages.add("Java");
Output
languages.add("C");
LinkedList: [Java, Python, JavaScript, Kotlin]
System.out.println("LinkedList: " + languages);
Removed Element: Python
New LinkedList: [Java, JavaScript, Kotlin]
// access the first element
String str1 = languages.peek();
System.out.println("Accessed Element: " + str1);
import java.util.LinkedList;
// access and remove the first element
String str2 = languages.poll(); class Main {
System.out.println("Removed Element: " + str2); public static void main(String[] args) {
System.out.println("LinkedList after poll(): " + // Creating a linked list
languages); LinkedList<String> animals = new
LinkedList<>();
// add element at the end animals.add("Cow");
languages.offer("Swift"); animals.add("Cat");
System.out.println("LinkedList after offer(): " + animals.add("Dog");
languages); System.out.println("LinkedList: " + animals);
}
} // Using forEach loop
System.out.println("Accessing linked list
Output elements:");
LinkedList: [Python, Java, C] for(String animal: animals) {
Accessed Element: Python System.out.print(animal);
Removed Element: Python System.out.print(", ");
LinkedList after poll(): [Java, C] }
LinkedList after offer(): [Java, C, Swift] }
}
Example: LinkedList as Deque
import java.util.LinkedList; Output
import java.util.Deque; LinkedList: [Cow, Cat, Dog]
Accessing linked list elements:
class Main { Cow, Cat, Dog,
public static void main(String[] args){
Deque<String> animals = new LinkedList<>(); LinkedList Vs. ArrayList
Both the Java ArrayList and LinkedList implements
// add element at the beginning the List interface of the Collections framework.
animals.add("Cow");
However, there exists some difference between them.
System.out.println("LinkedList: " + animals);
LinkedList ArrayList
Implements List, Queue, Implements List interface.
animals.addFirst("Dog");
and Deque interfaces.
System.out.println("LinkedList after addFirst(): " +
animals); Stores 3 values (previous Stores a single value in a
address, data, and next single position.
// add elements at the end address) in a single
animals.addLast("Zebra"); position.
System.out.println("LinkedList after addLast(): " + Provides the doubly- Provides a resizable array
animals); linked list implementation.
implementation.
// remove the first element Whenever an element is Whenever an element is
animals.removeFirst(); added, prev and next added, all elements after
System.out.println("LinkedList after removeFirst(): address are changed. that position are shifted.
" + animals); To access an element, we Can randomly access
need to iterate from the elements using indexes.
// remove the last element beginning to the element.
animals.removeLast();
System.out.println("LinkedList after removeLast(): Note: We can also create a LinkedList using interfaces
" + animals); in Java. For example,
} // create linkedlist using List
} List<String> animals1 = new LinkedList<>();

Output // creating linkedlist using Queue


LinkedList: [Cow] Queue<String> animals2 = new LinkedList<>();
LinkedList after addFirst(): [Dog, Cow]
LinkedList after addLast(): [Dog, Cow, Zebra] // creating linkedlist using Deque
LinkedList after removeFirst(): [Cow, Zebra] Deque<String> animals3 = new LinkedList<>();
LinkedList after removeLast(): [Cow] Here, if the LinkedList is created using one interface,
then we cannot use methods provided by other
Iterating through LinkedList interfaces. That is, animals1 cannot use methods
We can use the Java for-each loop to iterate through specific to Queue and Deque interfaces.
LinkedList. For example,
animals.addLast("Horse");
Java ArrayDeque System.out.println("ArrayDeque: " + animals);
In Java, we can use the ArrayDeque class to }
}
implement queue and deque data structures
using arrays.
Output
ArrayDeque: [Cat, Dog, Horse]
Interfaces implemented by ArrayDeque
The ArrayDeque class implements these two 2. Insert elements using offer(), offerFirst() and
interfaces: offerLast()
 Java Queue Interface  offer() - inserts the specified element at the end of the
 Java Deque Interface
array deque
Creating ArrayDeque  offerFirst() - inserts the specified element at the
In order to create an array deque, we must import beginning of the array deque
the java.util.ArrayDeque package.  offerLast() - inserts the specified element at the end of
Here is how we can create an array deque in Java: the array deque
ArrayDeque<Type> animal = new ArrayDeque<>();
Here, Type indicates the type of the array deque. For
Note: offer(), offerFirst() and offerLast() returns true if
example,
the element is successfully inserted; if the array deque
// Creating String type ArrayDeque
ArrayDeque<String> animals = new is full, these methods return false.
ArrayDeque<>();
For example,
// Creating Integer type ArrayDeque import java.util.ArrayDeque;
ArrayDeque<Integer> age = new ArrayDeque<>();
class Main {
Methods of ArrayDeque public static void main(String[] args) {
ArrayDeque<String> animals= new
The ArrayDeque class provides implementations for
ArrayDeque<>();
all the methods present // Using offer()
in Queue and Deque interface. animals.offer("Dog");

Insert Elements to Deque // Using offerFirst()


1. Add elements using add(), addFirst() and animals.offerFirst("Cat");
addLast()
 add() - inserts the specified element at the end of the // Using offerLast()
array deque animals.offerLast("Horse");
 addFirst() - inserts the specified element at the System.out.println("ArrayDeque: " + animals);
beginning of the array deque }
}
 addLast() - inserts the specified at the end of the array
deque (equivalent to add() ) Output
ArrayDeque: [Cat, Dog, Horse]
Note: If the array deque is full
Note: If the array deque is full, all these the add() method will throw an exception
methods add(), addFirst() and addLast() throws Illegal the offer() method returns false
StateException.
Access ArrayDeque Elements
For example, 1. Access elements using getFirst() and getLast()
import java.util.ArrayDeque;  getFirst() - returns the first element of the array deque
 getLast() - returns the last element of the array deque
class Main {
public static void main(String[] args) {
ArrayDeque<String> animals= new
Note: If the array deque is
ArrayDeque<>();
empty, getFirst() and getLast() throws NoSuchElemen
// Using add() tException.
animals.add("Dog");
For example,
// Using addFirst() import java.util.ArrayDeque;
animals.addFirst("Cat");
class Main {
// Using addLast() public static void main(String[] args) {
ArrayDeque<String> animals= new Last Element: Horse
ArrayDeque<>();
animals.add("Dog"); Note: If the array deque is
animals.add("Cat"); empty, peek(), peekFirst() and getLast() throws NoSuc
animals.add("Horse"); hElementException.
System.out.println("ArrayDeque: " + animals);
Remove ArrayDeque Elements
// Get the first element 1. Remove elements using the remove(),
String firstElement = animals.getFirst(); removeFirst(), removeLast() method
System.out.println("First Element: " +  remove() - returns and removes an element from the
firstElement); first element of the array deque
 remove(element) - returns and removes the specified
// Get the last element
element from the head of the array deque
String lastElement = animals.getLast();
System.out.println("Last Element: " +  removeFirst() - returns and removes the first element
lastElement); from the array deque (equivalent to remove() )
}  removeLast() - returns and removes the last element
} from the array deque
Output
ArrayDeque: [Dog, Cat, Horse] Note: If the array deque is
First Element: Dog empty, remove(), removeFirst() and removeLast() met
Last Element: Horse
hod throws an exception.
2. Access elements using peek(), peekFirst() and Also, remove(element) throws an exception if the
peekLast() method element is not found.
 peek() - returns the first element of the array deque
For example,
 peekFirst() - returns the first element of the array import java.util.ArrayDeque;
deque (equivalent to peek() )
 peekLast() - returns the last element of the array class Main {
deque public static void main(String[] args) {
For example, ArrayDeque<String> animals= new
import java.util.ArrayDeque; ArrayDeque<>();
animals.add("Dog");
class Main { animals.add("Cat");
public static void main(String[] args) { animals.add("Cow");
ArrayDeque<String> animals= new animals.add("Horse");
ArrayDeque<>(); System.out.println("ArrayDeque: " + animals);
animals.add("Dog");
animals.add("Cat"); // Using remove()
animals.add("Horse"); String element = animals.remove();
System.out.println("ArrayDeque: " + animals); System.out.println("Removed Element: " +
element);
// Using peek()
String element = animals.peek(); System.out.println("New ArrayDeque: " +
System.out.println("Head Element: " + element); animals);

// Using peekFirst() // Using removeFirst()


String firstElement = animals.peekFirst(); String firstElement = animals.removeFirst();
System.out.println("First Element: " + System.out.println("Removed First Element: " +
firstElement); firstElement);

// Using peekLast // Using removeLast()


String lastElement = animals.peekLast(); String lastElement = animals.removeLast();
System.out.println("Last Element: " + System.out.println("Removed Last Element: " +
lastElement); lastElement);
} }
} }

Output Output
ArrayDeque: [Dog, Cat, Horse] ArrayDeque: [Dog, Cat, Cow, Horse]
Head Element: Dog Removed Element: Dog
First Element: Dog New ArrayDeque: [Cat, Cow, Horse]
Removed First Element: Cat ArrayDeque<String> animals= new
Removed Last Element: Horse ArrayDeque<>();
animals.add("Dog");
2. Remove elements using the poll(), pollFirst() and animals.add("Cat");
pollLast() method animals.add("Horse");
 poll() - returns and removes the first element of the System.out.println("ArrayDeque: " + animals);
array deque
 pollFirst() - returns and removes the first element of // Using clear()
animals.clear();
the array deque (equivalent to poll() )
 pollLast() - returns and removes the last element of System.out.println("New ArrayDeque: " +
the array deque animals);
}
Note: If the array deque is }
empty, poll(), pollFirst() and pollLast() returns null if
the element is not found. Output
For example, ArrayDeque: [Dog, Cat, Horse]
import java.util.ArrayDeque; New ArrayDeque: []

class Main { Iterating the ArrayDeque


public static void main(String[] args) {  iterator() - returns an iterator that can be used to
ArrayDeque<String> animals= new iterate over the array deque
ArrayDeque<>();  descendingIterator() - returns an iterator that can be
animals.add("Dog");
used to iterate over the array deque in reverse order
animals.add("Cat");
In order to use these methods, we must import
animals.add("Cow");
animals.add("Horse"); the java.util.Iterator package. For example,
System.out.println("ArrayDeque: " + animals); import java.util.ArrayDeque;
import java.util.Iterator;
// Using poll()
String element = animals.poll(); class Main {
System.out.println("Removed Element: " + public static void main(String[] args) {
element); ArrayDeque<String> animals= new
System.out.println("New ArrayDeque: " + ArrayDeque<>();
animals); animals.add("Dog");
animals.add("Cat");
// Using pollFirst() animals.add("Horse");
String firstElement = animals.pollFirst();
System.out.println("Removed First Element: " + System.out.print("ArrayDeque: ");
firstElement);
// Using iterator()
// Using pollLast() Iterator<String> iterate = animals.iterator();
String lastElement = animals.pollLast(); while(iterate.hasNext()) {
System.out.println("Removed Last Element: " + System.out.print(iterate.next());
lastElement); System.out.print(", ");
} }
}
System.out.print("\nArrayDeque in reverse
Output order: ");
ArrayDeque: [Dog, Cat, Cow, Horse] // Using descendingIterator()
Removed Element: Dog Iterator<String> desIterate =
New ArrayDeque: [Cat, Cow, Horse] animals.descendingIterator();
Removed First Element: Cat while(desIterate.hasNext()) {
Removed Last Element: Horse System.out.print(desIterate.next());
System.out.print(", ");
3. Remove Element: using the clear() method }
To remove all the elements from the array deque, we }
}
use the clear() method. For example,
import java.util.ArrayDeque;
Output
ArrayDeque: [Dog, Cat, Horse]
class Main {
ArrayDeque in reverse order: [Horse, Cat, Dog]
public static void main(String[] args) {
Other Methods Accessed Element: Horse
Methods element() Returns Removed Element: Horse
Descriptions an element from the head
of the array deque. ArrayDeque Vs. LinkedList Class
contains(element) Both ArrayDeque and Java LinkedList implements
Searches the array the Deque interface. However, there exist some
deque for the specified differences between them.
element.
 LinkedList supports null elements,
size() Returns the length
If the element is of the array deque. whereas ArrayDeque doesn't.
found, it returns true, if  Each node in a linked list includes links to other
not it returns false. nodes. That's why LinkedList requires more storage
toArray() Converts clone() Creates a copy of than ArrayDeque .
array deque to array and the array deque and  If you are implementing the queue or the deque data
returns it. returns it. structure, an ArrayDeque is likely to faster than
Methods element() Returns
Descriptions an element from the head a LinkedList .
of the array deque.
contains(element)
Searches the array Java BlockingQueue
deque for the specified The BlockingQueue interface of the Java Collections
element. framework extends the Queue interface. It allows any
operation to wait until it can be successfully
ArrayDeque as a Stack performed.
To implement a LIFO (Last-In-First-Out) stacks in For example, if we want to delete an element from an
Java, it is recommended to use a deque over the Stack empty queue, then the blocking queue allows the
class. The ArrayDeque class is likely to be faster than delete operation to wait until the queue contains some
elements to be deleted.
the Stack class.
ArrayDeque provides the following methods that can Classes that Implement BlockingQueue
be used for implementing a stack. Since BlockingQueue is an interface, we cannot
 push() - adds an element to the top of the stack provide the direct implementation of it.
 peek() - returns an element from the top of the stack In order to use the functionality of the BlockingQueue,
 pop() - returns and removes an element from the top we need to use classes that implement it.
ArrayBlockingQueue
of the stack
LinkedBlockingQueue
For example,
import java.util.ArrayDeque;

class Main {
public static void main(String[] args) {
ArrayDeque<String> stack = new
ArrayDeque<>();

// Add elements to stack


stack.push("Dog");
stack.push("Cat");
stack.push("Horse");
System.out.println("Stack: " + stack);
How to use blocking queues?
// Access element from top of stack We must import
String element = stack.peek(); the java.util.concurrent.BlockingQueue package in
System.out.println("Accessed Element: " + order to use BlockingQueue.
element);
// Array implementation of BlockingQueue
// Remove elements from top of stack BlockingQueue<String> animal1 = new
String remElement = stack.pop(); ArraryBlockingQueue<>();
System.out.println("Removed element: " +
remElement); // LinkedList implementation of BlockingQueue
} BlockingQueue<String> animal2 = new
} LinkedBlockingQueue<>();

Output Here, we have created objects animal1 and animal2 of


Stack: [Horse, Cat, Dog] classes ArrayBlockingQueue and LinkedBlockingQue
ue, respectively. These objects can use the class Main {
functionalities of the BlockingQueue interface.
public static void main(String[] args) {
Methods of BlockingQueue // Create a blocking queue using the
Based on whether a queue is full or empty, methods of ArrayBlockingQueue
a blocking queue can be divided into 3 categories: BlockingQueue<Integer> numbers = new
Methods that throw an exception ArrayBlockingQueue<>(5);
add() - Inserts an element to the blocking queue at the
end of the queue. Throws an exception if the queue is try {
full. // Insert element to blocking queue
element() - Returns the head of the blocking queue. numbers.put(2);
Throws an exception if the queue is empty. numbers.put(1);
remove() - Removes an element from the blocking numbers.put(3);
queue. Throws an exception if the queue is empty. System.out.println("BLockingQueue: " +
numbers);
Methods that return some value
offer() - Inserts the specified element to the blocking // Remove Elements from blocking queue
queue at the end of the queue. Returns false if the int removedNumber = numbers.take();
queue is full. System.out.println("Removed Number: " +
peek() - Returns the head of the blocking queue. removedNumber);
Returns null if the queue is empty. }
poll() - Removes an element from the blocking queue.
Returns null if the queue is empty. catch(Exception e) {
AD e.getStackTrace();
More on offer() and poll() }
The offer() and poll() method can be used with }
timeouts. That is, we can pass time units as a }
parameter. For example,
Output
offer(value, 100, milliseconds) BlockingQueue: [2, 1, 3]
Removed Element: 2
Here,
value is the element to be inserted to the queue Why BlockingQueue?
And we have set a timeout of 100 milliseconds In Java, BlockingQueue is considered as the thread-
This means the offer() method will try to insert an safe collection. It is because it can be helpful in multi-
element to the blocking queue for 100 milliseconds. If threading operations.
the element cannot be inserted in 100 milliseconds, the Suppose one thread is inserting elements to the queue
method returns false. and another thread is removing elements from the
Note: Instead of milliseconds, we can also use these queue.
time Now, if the first thread runs slower, then the blocking
units: days, hours, minutes, seconds, microseconds an queue can make the second thread wait until the first
d nanoseconds in offer() and poll() methods. thread completes its operation.

Methods that blocks the operation


The BlockingQueue also provides methods to block Java ArrayBlockingQueue
the operations and wait if the queue is full or empty.
put() - Inserts an element to the blocking queue. If the
The ArrayBlockingQueue class of the Java Collections
queue is full, it will wait until the queue has space to
framework provides the blocking queue
insert an element.
implementation using an array.
take() - Removes and returns an element from the
It implements the Java BlockingQueue interface.
blocking queue. If the queue is empty, it will wait until
the queue has elements to be deleted.
Suppose, we want to insert elements into a queue. If
the queue is full then the put() method will wait until
the queue has space to insert elements.
Similarly, if we want to delete elements from a queue.
If the queue is empty then the take() method will wait
until the queue contains elements to be deleted.

Implementation of BlockingQueue in
ArrayBlockingQueue
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ArrayBlockingQueue;
ArrayBlockingQueue: [Dog, Cat, Horse]
Creating ArrayBlockingQueue
In order to create an array blocking queue, we must Access Elements
import peek() - Returns an element from the front of the array
the java.util.concurrent.ArrayBlockingQueue package. blocking queue. It returns null if the queue is empty.
Once we import the package, here is how we can iterator() - Returns an iterator object to sequentially
create an array blocking queue in Java: access elements from the array blocking queue. It
ArrayBlockingQueue<Type> animal = new throws an exception if the queue is empty. We must
ArrayBlockingQueue<>(int capacity); import the java.util.Iterator package to use it.
For example,
Here, import java.util.concurrent.ArrayBlockingQueue;
Type - the type of the array blocking queue import java.util.Iterator;
capacity - the size of the array blocking queue
For example, class Main {
// Creating String type ArrayBlockingQueue with size public static void main(String[] args) {
5 ArrayBlockingQueue<String> animals = new
ArrayBlockingQueue<String> animals = new ArrayBlockingQueue<>(5);
ArrayBlockingQueue<>(5);
// Add elements
// Creating Integer type ArrayBlockingQueue with animals.add("Dog");
size 5 animals.add("Cat");
ArrayBlockingQueue<Integer> age = new animals.add("Horse");
ArrayBlockingQueue<>(5); System.out.println("ArrayBlockingQueue: " +
animals);
Note: It is compulsory to provide the size of the array.
// Using peek()
Methods of ArrayBlockingQueue String element = animals.peek();
The ArrayBlockingQueue class provides the System.out.println("Accessed Element: " +
implementation of all the methods in element);
the BlockingQueue interface.
These methods are used to insert, access and delete // Using iterator()
elements from array blocking queues. Iterator<String> iterate = animals.iterator();
Also, we will learn about two System.out.print("ArrayBlockingQueue
methods put() and take() that support the blocking Elements: ");
operation in the array blocking queue.
These two methods distinguish the array blocking while(iterate.hasNext()) {
queue from other typical queues. System.out.print(iterate.next());
System.out.print(", ");
Insert Elements }
add() - Inserts the specified element to the array }
blocking queue. It throws an exception if the queue is }
full.
offer() - Inserts the specified element to the array Output
blocking queue. It returns false if the queue is full. ArrayBlockingQueue: [Dog, Cat, Horse]
For example, Accessed Element: Dog
import java.util.concurrent.ArrayBlockingQueue; ArrayBlockingQueue Elements: Dog, Cat, Horse,

class Main { Remove Elements


public static void main(String[] args) { remove() - Returns and removes a specified element
ArrayBlockingQueue<String> animals = new from the array blocking queue. It throws an exception
ArrayBlockingQueue<>(5); if the queue is empty.
poll() - Returns and removes a specified element from
// Using add() the array blocking queue. It returns null if the queue is
animals.add("Dog"); empty.
animals.add("Cat"); clear() - Removes all the elements from the array
blocking queue.
// Using offer() For example,
animals.offer("Horse"); import java.util.concurrent.ArrayBlockingQueue;
System.out.println("ArrayBlockingQueue: " +
animals); class Main {
} public static void main(String[] args) {
} ArrayBlockingQueue<String> animals = new
ArrayBlockingQueue<>(5);
Output
animals.add("Dog"); ArrayBlockingQueue: [Dog, Cat]
animals.add("Cat");
animals.add("Horse"); Here, the put() method may throw
System.out.println("ArrayBlockingQueue: " + an InterruptedException if it is interrupted while
animals); waiting. Hence, we must enclose it inside
a try..catch block.
// Using remove()
String element1 = animals.remove(); take() Method
System.out.println("Removed Element:"); To return and remove an element from the front of the
System.out.println("Using remove(): " + array blocking queue, we can use the take() method.
element1); If the array blocking queue is empty, it waits until
there are elements in the array blocking queue to be
// Using poll() deleted.
String element2 = animals.poll(); For example,
System.out.println("Using poll(): " + element2); import java.util.concurrent.ArrayBlockingQueue;

// Using clear() class Main {


animals.clear(); public static void main(String[] args) {
System.out.println("Updated ArrayBlockingQueue<String> animals = new
ArrayBlockingQueue: " + animals); ArrayBlockingQueue<>(5);
}
} try {
//Add elements to animals
Output animals.put("Dog");
ArrayBlockingQueue: [Dog, Cat, Horse] animals.put("Cat");
Removed Elements: System.out.println("ArrayBlockingQueue: " +
Using remove(): Dog animals);
Using poll(): Cat
Updated ArrayBlockingQueue: [] // Remove an element
String element = animals.take();
put() and take() Method System.out.println("Removed Element: " +
In multithreading processes, we can element);
use put() and take() to block the operation of one }
thread to synchronize it with another thread. These catch(Exception e) {
methods will wait until they can be successfully System.out.println(e);
executed. }
}
put() method }
To add an element to the end of an array blocking
queue, we can use the put() method. Output
If the array blocking queue is full, it waits until there is ArrayBlockingQueue: [Dog, Cat]
space in the array blocking queue to add an element. Removed Element: Dog
For example,
import java.util.concurrent.ArrayBlockingQueue; Here, the take() method will throw
an InterrupedException if it is interrupted while
class Main { waiting. Hence, we must enclose it inside
public static void main(String[] args) { a try...catch block.
ArrayBlockingQueue<String> animals = new
ArrayBlockingQueue<>(5); Other Methods
Methods Descriptions
try { contains(element) Searches the array blocking
// Add elements to animals queue for the specified
animals.put("Dog"); element.If the element is found,
animals.put("Cat"); it returns true, if not it returns
System.out.println("ArrayBlockingQueue: " + false.
animals); size() Returns the length of the array
} blocking queue.
catch(Exception e) { toArray() Converts array blocking queue
System.out.println(e); to an array and returns it.
} toString() Converts the array blocking
} queue to string
}

Output
Why use ArrayBlockingQueue?
The ArrayBlockingQueue uses arrays as its internal Note: It is not compulsory to provide the size of the
storage. linked list.
It is considered as a thread-safe collection. Hence, it is
generally used in multi-threading applications. Methods of LinkedBlockingQueue
Suppose, one thread is inserting elements to the queue The LinkedBlockingQueue class provides the
and another thread is removing elements from the implementation of all the methods in
queue. the BlockingQueue interface.
Now, if the first thread is slower than the second These methods are used to insert, access and delete
thread, then the array blocking queue can make the elements from linked blocking queues.
second thread waits until the first thread completes its Also, we will learn about two
operations. methods put() and take() that support the blocking
operation in the linked blocking queue.
These two methods distinguish the linked blocking
Java LinkedBlockingQueue queue from other typical queues.

The LinkedBlockingQueue class of the Java Insert Elements


Collections framework provides the blocking queue add() - Inserts a specified element to the linked
implementation using a linked list. blocking queue. It throws an exception if the queue is
It implements the Java BlockingQueue interface. full.
offer() - Inserts a specified element to the linked
blocking queue. It returns false if the queue is full.
For example,
import java.util.concurrent.LinkedBlockingQueue;

class Main {
public static void main(String[] args) {
LinkedBlockingQueue<String> animals = new
LinkedBlockingQueue<>(5);

// Using add()
animals.add("Dog");
Creating LinkedBlockingQueue animals.add("Cat");
In order to create a linked blocking queue, we must
import // Using offer()
the java.util.concurrent.LinkedBlockingQueue packag animals.offer("Horse");
e. System.out.println("LinkedBlockingQueue: " +
Here is how we can create a linked blocking queue in animals);
Java: }
}
1. Without the initial capacity
LinkedBlockingQueue<Type> animal = new Output
LinkedBlockingQueue<>(); LinkedBlockingQueue: [Dog, Cat, Horse]

Here the default initial capacity will be 231-1. Access Elements


peek() - Returns an element from the front of the
2. With the initial capacity linked blocking queue. It returns null if the queue is
LinkedBlockingQueue<Type> animal = new empty.
LinkedBlockingQueue<>(int capacity); iterator() - Returns an iterator object to sequentially
access an element from the linked blocking queue. It
Here, throws an exception if the queue is empty. We must
Type - the type of the linked blocking queue import the java.util.Iterator package to use it.
capacity - the size of the linked blocking queue For example,
For example, import java.util.concurrent.LinkedBlockingQueue;
// Creating String type LinkedBlockingQueue with import java.util.Iterator;
size 5
LinkedBlockingQueue<String> animals = new class Main {
LinkedBlockingQueue<>(5); public static void main(String[] args) {
LinkedBlockingQueue<String> animals = new
// Creating Integer type LinkedBlockingQueue with LinkedBlockingQueue<>(5);
size 5
LinkedBlockingQueue<Integer> age = new // Add elements
LinkedBlockingQueue<>(5); animals.add("Dog");
animals.add("Cat");
animals.add("Horse"); }
System.out.println("LinkedBlockingQueue: " +
animals); Output
LinkedBlockingQueue: [Dog, Cat, Horse]
// Using peek() Removed Elements:
String element = animals.peek(); Using remove(): Dog
System.out.println("Accessed Element: " + Using poll(): Cat
element); Updated LinkedBlockingQueue: []

// Using iterator() put() and take() Methods


Iterator<String> iterate = animals.iterator(); In multithreading processes, we can
System.out.print("LinkedBlockingQueue use put() and take() to block the operation of one
Elements: "); thread to synchronize it with another thread. These
methods will wait until they can be successfully
while(iterate.hasNext()) { executed.
System.out.print(iterate.next());
System.out.print(", "); put() Method
} To insert the specified element to the end of a linked
} blocking queue, we use the put() method.
} If the linked blocking queue is full, it waits until there
is space in the linked blocking queue to insert the
Output element.
LinkedBlockingQueue: [Dog, Cat, Horse] For example,
Accessed Element: Dog import java.util.concurrent.LinkedBlockingQueue;
LinkedBlockingQueue Elements: Dog, Cat, Horse,
class Main {
Remove Elements public static void main(String[] args) {
remove() - Returns and removes a specified element LinkedBlockingQueue<String> animals = new
from the linked blocking queue. It throws an exception LinkedBlockingQueue<>(5);
if the queue is empty.
poll() - Returns and removes a specified element from try {
the linked blocking queue. It returns null if the queue // Add elements to animals
is empty. animals.put("Dog");
clear() - Removes all the elements from the linked animals.put("Cat");
blocking queue. System.out.println("LinkedBlockingQueue: " +
For example, animals);
import java.util.concurrent.LinkedBlockingQueue; }
catch(Exception e) {
class Main { System.out.println(e);
public static void main(String[] args) { }
LinkedBlockingQueue<String> animals = new }
LinkedBlockingQueue<>(5); }

animals.add("Dog"); Output
animals.add("Cat"); LinkedBlockingQueue: [Dog, Cat]
animals.add("Horse");
System.out.println("LinkedBlockingQueue " + Here, the put() method may throw
animals); an InterruptedException if it is interrupted while
waiting. Hence, we must enclose it inside a try..catch
// Using remove() block.
String element1 = animals.remove();
System.out.println("Removed Element:"); take() Method
System.out.println("Using remove(): " + To return and remove an element from the front of the
element1); linked blocking queue, we can use the take() method.
If the linked blocking queue is empty, it waits until
// Using poll() there are elements in the linked blocking queue to be
String element2 = animals.poll(); deleted.
System.out.println("Using poll(): " + element2); For example,
import java.util.concurrent.LinkedBlockingQueue;
// Using clear()
animals.clear(); class Main {
System.out.println("Updated public static void main(String[] args) {
LinkedBlockingQueue " + animals); LinkedBlockingQueue<String> animals = new
} LinkedBlockingQueue<>(5);
try {
//Add elements to animals
Java Map
animals.put("Dog");
animals.put("Cat"); Java Map Interface
System.out.println("LinkedBlockingQueue: " + The Map interface of the Java collections
animals); framework provides the functionality of the map data
structure.
// Remove an element
String element = animals.take(); Working of Map
System.out.println("Removed Element: " + In Java, elements of Map are stored
element); in key/value pairs. Keys are unique values associated
System.out.println("New with individual Values.
LinkedBlockingQueue: " + animals); A map cannot contain duplicate keys. And, each key
} is associated with a single value.
catch(Exception e) {
System.out.println(e);
}
}
}

Output
LinkedBlockingQueue: [Dog, Cat]
Removed Element: Dog
New LinkedBlockingQueue: [Cat]

Here, the take() method will throw


an InterrupedException if it is interrupted while
waiting. Hence, we must enclose it inside We can access and modify values using the keys
a try...catch block. associated with them.
In the above diagram, we have values: United
States, Brazil, and Spain. And we have corresponding
Other Methods
keys: us, br, and es.
Methods Descriptions
Now, we can access those values using their
contains(element) Searches the linked
corresponding keys.
blocking queue for the
Note: The Map interface maintains 3 different sets:
specified element. If the
the set of keys
element is found, it
the set of values
returns true, if not it
the set of key/value associations (mapping).
returns false.
Hence we can access keys, values, and associations
size() Returns the length of the individually.
linked blocking queue.
toArray() Converts linked blocking Classes that implement Map
queue to an array and Since Map is an interface, we cannot
return the array. create objects from it.
toString() Converts the linked In order to use the functionalities of the Map interface,
blocking queue to string we can use these classes:
HashMap
Why use LinkedBlockingQueue? EnumMap
The LinkedBlockingQueue uses linked lists as its LinkedHashMap
internal storage. WeakHashMap
It is considered as a thread-safe collection. Hence, it is TreeMap
generally used in multi-threading applications. These classes are defined in the collections framework
Suppose, one thread is inserting elements to the queue and implemented in the Map interface.
and another thread is removing elements from the
queue.
Now, if the first thread is slower than the second
thread, then the linked blocking queue can make the
second thread waits until the first thread completes its
operations.

Java Map Subclasses


Interfaces that extend Map entrySet() - Returns a set of all the key/value mapping
The Map interface is also extended by these present in a map.
subinterfaces:
SortedMap Implementation of the Map Interface
NavigableMap 1. Implementing HashMap Class
ConcurrentMap import java.util.Map;
import java.util.HashMap;

class Main {

public static void main(String[] args) {


// Creating a map using the HashMap
Map<String, Integer> numbers = new
HashMap<>();
Java Map Subinterfaces
// Insert elements to the map
How to use Map? numbers.put("One", 1);
In Java, we must import the java.util.Map package in numbers.put("Two", 2);
order to use Map. Once we import the package, here's System.out.println("Map: " + numbers);
how we can create a map.
// Map implementation using HashMap // Access keys of the map
Map<Key, Value> numbers = new HashMap<>(); System.out.println("Keys: " + numbers.keySet());

In the above code, we have created // Access values of the map


a Map named numbers. We have used System.out.println("Values: " +
the HashMap class to implement the Map interface. numbers.values());
Here,
Key - a unique identifier used to associate each // Access entries of the map
element (value) in a map System.out.println("Entries: " +
Value - elements associated by keys in a map numbers.entrySet());

// Remove Elements from the map


Methods of Map
int value = numbers.remove("Two");
The Map interface includes the following methods:
put(K, V) - Inserts the association of a key K and a System.out.println("Removed Value: " + value);
value V into the map. If the key is already present, the }
new value replaces the old value. }
putAll() - Inserts all the entries from the specified map
to this map. Output
Map: {One=1, Two=2}
putIfAbsent(K, V) - Inserts the association if the
key K is not already associated with the value V. Keys: [One, Two]
get(K) - Returns the value associated with the specified Values: [1, 2]
key K. If the key is not found, it returns null. Entries: [One=1, Two=2]
getOrDefault(K, defaultValue) - Returns the value Removed Value: 2
associated with the specified key K. If the key is not
found, it returns the defaultValue. 2. Implementing TreeMap Class
containsKey(K) - Checks if the specified key K is import java.util.Map;
present in the map or not. import java.util.TreeMap;
containsValue(V) - Checks if the specified value V is
present in the map or not. class Main {
replace(K, V) - Replace the value of the key K with the
new specified value V. public static void main(String[] args) {
replace(K, oldValue, newValue) - Replaces the value // Creating Map using TreeMap
of the key K with the new value newValue only if the Map<String, Integer> values = new
key K is associated with the value oldValue. TreeMap<>();
remove(K) - Removes the entry from the map
represented by the key K. // Insert elements to map
remove(K, V) - Removes the entry from the map that values.put("Second", 2);
has key K associated with value V. values.put("First", 1);
keySet() - Returns a set of all the keys present in a System.out.println("Map using TreeMap: " +
map. values);
values() - Returns a set of all the values present in a
map. // Replacing the values
values.replace("First", 11);
values.replace("Second", 22);
System.out.println("New Map: " + values); Example 1: Create HashMap in Java
import java.util.HashMap;
// Remove elements from the map
int removedValue = values.remove("First"); class Main {
System.out.println("Removed Value: " + public static void main(String[] args) {
removedValue);
} // create a hashmap
} HashMap<String, Integer> languages = new
HashMap<>();
Output
Map using TreeMap: {First=1, Second=2} // add elements to hashmap
New Map: {First=11, Second=22} languages.put("Java", 8);
Removed Value: 11 languages.put("JavaScript", 1);
languages.put("Python", 3);
System.out.println("HashMap: " + languages);
Java HashMap }
The HashMap class of the Java collections framework }
provides the functionality of the hash table data
structure. Output
It stores elements in key/value pairs. Here, keys are HashMap: {Java=8, JavaScript=1, Python=3}
unique identifiers used to associate each value on a
map. In the above example, we have created
a HashMap named languages.
The HashMap class implements the Map interface. Here, we have used the put() method to add elements
to the hashmap. We will learn more about
the put() method later in this tutorial.

Basic Operations on Java HashMap


The HashMap class provides various methods to
perform different operations on hashmaps. We will
look at some commonly used arraylist operations in
this tutorial:
Add elements
Access elements
Change elements
Remove elements

1. Add elements to a HashMap


To add a single element to the hashmap, we use
the put() method of the HashMap class. For example,
Java HashMap Implementation import java.util.HashMap;

class Main {
Create a HashMap public static void main(String[] args) {
In order to create a hash map, we must import
the java.util.HashMap package first. Once we import // create a hashmap
the package, here is how we can create hashmaps in HashMap<String, Integer> numbers = new
Java. HashMap<>();

// hashMap creation with 8 capacity and 0.6 load System.out.println("Initial HashMap: " + numbers);
factor // put() method to add elements
HashMap<K, V> numbers = new HashMap<>(); numbers.put("One", 1);
numbers.put("Two", 2);
In the above code, we have created a hashmap numbers.put("Three", 3);
named numbers. Here, K represents the key type System.out.println("HashMap after put(): " +
and V represents the type of values. For example, numbers);
}
HashMap<String, Integer> numbers = new }
HashMap<>();
Output
Here, the type of keys is String and the type Initial HashMap: {}
of values is Integer. HashMap after put(): {One=1, Two=2, Three=3}
In the above example, we have created
a HashMap named numbers. Here, we have used // return set view of key/value pairs
the put() method to add elements to numbers. // using entrySet()
Notice the statement, System.out.println("Key/Value mappings: " +
languages.entrySet());
numbers.put("One", 1); }
}
Here, we are passing the String value One as the key
and Integer value 1 as the value to the put() method. Output
HashMap: {1=Java, 2=Python, 3=JavaScript}
2. Access HashMap Elements Keys: [1, 2, 3]
We can use the get() method to access the value from Values: [Java, Python, JavaScript]
the hashmap. For example, Key/Value mappings: [1=Java, 2=Python,
import java.util.HashMap; 3=JavaScript]

class Main { In the above example, we have created a hashmap


public static void main(String[] args) { named languages. Here, we are accessing
the keys, values, and key/value mappings from the
HashMap<Integer, String> languages = new hashmap.
HashMap<>();
languages.put(1, "Java"); 3. Change HashMap Value
languages.put(2, "Python"); We can use the replace() method to change the value
languages.put(3, "JavaScript"); associated with a key in a hashmap. For example,
System.out.println("HashMap: " + languages); import java.util.HashMap;

// get() method to get value class Main {


String value = languages.get(1); public static void main(String[] args) {
System.out.println("Value at index 1: " + value);
} HashMap<Integer, String> languages = new
} HashMap<>();
languages.put(1, "Java");
Output languages.put(2, "Python");
HashMap: {1=Java, 2=Python, 3=JavaScript} languages.put(3, "JavaScript");
Value at index 1: Java System.out.println("Original HashMap: " +
languages);
In the above example, notice the expression,
languages.get(1); // change element with key 2
languages.replace(2, "C++");
Here, the get() method takes the key as its argument System.out.println("HashMap using replace(): " +
and returns the corresponding value associated with languages);
the key. }
We can also access the keys, values, }
and key/value pairs of the hashmap as set views
using keySet(), values(), and entrySet() methods Output
respectively. For example, Original HashMap: {1=Java, 2=Python,
import java.util.HashMap; 3=JavaScript}
HashMap using replace(): {1=Java, 2=C++,
class Main { 3=JavaScript}
public static void main(String[] args) {
HashMap<Integer, String> languages = new In the above example, we have created a hashmap
HashMap<>(); named languages. Notice the expression,
languages.replace(2, "C++");
languages.put(1, "Java"); Here, we are changing the value referred to by
languages.put(2, "Python"); key 2 with the new value C++.
languages.put(3, "JavaScript"); The HashMap class also provides some variations of
System.out.println("HashMap: " + languages); the replace() method.

// return set view of keys 4. Remove HashMap Elements


// using keySet() To remove elements from a hashmap, we can use the
System.out.println("Keys: " + languages.keySet()); remove() method. For example,
import java.util.HashMap;
// return set view of values
// using values() class Main {
System.out.println("Values: " + languages.values()); public static void main(String[] args) {
specified mapping to the the HashMap
HashMap<Integer, String> languages = new HashMap
HashMap<>(); containsKey() checks if containsValue()
languages.put(1, "Java"); the specified key is checks if
languages.put(2, "Python"); present in Hashmap Hashmap contains the
languages.put(3, "JavaScript"); specified value
System.out.println("HashMap: " + languages);

// remove element associated with key 2 Iterate through a HashMap


String value = languages.remove(2);
System.out.println("Removed value: " + value); To iterate through each entry of the hashmap, we can
use Java for-each loop. We can iterate through keys
System.out.println("Updated HashMap: " + only, vales only, and key/value mapping. For
languages); example,
}
}
import java.util.HashMap;
Output import java.util.Map.Entry;
HashMap: {1=Java, 2=Python, 3=JavaScript}
Removed value: Python class Main {
Updated HashMap: {1=Java, 3=JavaScript} public static void main(String[] args) {

Here, the remove() method takes the key as its // create a HashMap
parameter. It then returns the value associated with HashMap<Integer, String> languages = new
the key and removes the entry. HashMap<>();
We can also remove the entry only under certain languages.put(1, "Java");
conditions. For example, languages.put(2, "Python");
languages.put(3, "JavaScript");
remove(2, "C++"); System.out.println("HashMap: " + languages);

Here, the remove() method only removes the entry if // iterate through keys only
the key 2 is associated with the value C++. Since 2 is System.out.print("Keys: ");
not associated with C++, it doesn't remove the entry. for (Integer key : languages.keySet()) {
System.out.print(key);
Other Methods of Method System.out.print(", ");
HashMap Description }
clear() removes all compute() computes
mappings from the a new value for the // iterate through values only
HashMap specified key System.out.print("\nValues: ");
computeIfAbsent() computeIfPresent() for (String value : languages.values()) {
computes value if computes a value System.out.print(value);
a mapping for the key is for mapping if the key is System.out.print(", ");
not present present }
merge()merges the clone() makes the copy of
specified mapping to the the HashMap // iterate through key/value entries
HashMap System.out.print("\nEntries: ");
containsKey() checks if containsValue() for (Entry<Integer, String> entry :
the specified key is checks if languages.entrySet()) {
present in Hashmap Hashmap contains the System.out.print(entry);
specified value System.out.print(", ");
size() returns the isEmpty() checks if }
number of items in the Hashmap is empty }
HashMap }
Other Methods of Method
HashMap Description Output
clear() removes all compute() computes HashMap: {1=Java, 2=Python, 3=JavaScript}
mappings from the a new value for the Keys: 1, 2, 3,
HashMap specified key Values: Java, Python, JavaScript,
computeIfAbsent() computeIfPresent()
Entries: 1=Java, 2=Python, 3=JavaScript,
computes value if computes a value
a mapping for the key is for mapping if the key is
not present present
merge()merges the clone() makes the copy of
Note that we have used the Map.Entry in the above Java LinkedHashMap
example. It is the nested class of the Map interface that The LinkedHashMap class of the Java collections
returns a view (elements) of the map. framework provides the hash table and linked
list implementation of the Map interface.
We first need to import
The LinkedHashMap class extends the HashMap class
the java.util.Map.Entry package in order to use this to store its entries in a hash table. It internally
class. maintains a doubly-linked list among all of its entries
This nested class returns a view (elements) of the map. to order its entries.

Creating HashMap from Other Maps


In Java, we can also create a hashmap from other
maps. For example,
import java.util.HashMap;
import java.util.TreeMap;

class Main {
public static void main(String[] args) {

// create a treemap
TreeMap<String, Integer> evenNumbers = new
TreeMap<>();
evenNumbers.put("Two", 2);
evenNumbers.put("Four", 4);
System.out.println("TreeMap: " + evenNumbers); Creating a LinkedHashMap
In order to create a linked hashmap, we must import
// create hashmap from the treemap the java.util.LinkedHashMap package first. Once we
HashMap<String, Integer> numbers = new import the package, here is how we can create linked
hashmaps in Java.
HashMap<>(evenNumbers);
numbers.put("Three", 3);
System.out.println("HashMap: " + numbers); // LinkedHashMap with initial capacity 8 and load
} factor 0.6
} LinkedHashMap<Key, Value> numbers = new
LinkedHashMap<>(8, 0.6f);
Output
TreeMap: {Four=4, Two=2} In the above code, we have created a linked hashmap
HashMap: {Two=2, Three=3, Four=4} named numbers.
Here,
In the above example, we have created Key - a unique identifier used to associate each
element (value) in a map
a TreeMap named evenNumbers. Notice the
expression, Value - elements associated by the keys in a map
Notice the part new LinkedHashMap<>(8, 0.6). Here,
numbers = new HashMap<>(evenNumbers) the first parameter is capacity and the second
parameter is loadFactor.
Here, we are creating a HashMap named numbers capacity - The capacity of this linked hashmap is 8.
using the TreeMap. Meaning, it can store 8 entries.
Note: While creating a hashmap, we can include loadFactor - The load factor of this linked hashmap is
optional parameters: capacity and load factor. For 0.6. This means, whenever our hash map is filled by
example, 60%, the entries are moved to a new hash table of
double the size of the original hash table.
HashMap<K, V> numbers = new HashMap<>(8, Default capacity and load factor
0.6f); It's possible to create a linked hashmap without
defining its capacity and load factor. For example,
Here, //LinkedHashMap with default capacity and load
8 (capacity is 8) - This means it can store 8 entries. factor
LinkedHashMap<Key, Value> numbers1 = new
0.6f (load factor is 0.6) - This means whenever our
hash table is filled by 60%, the entries are moved to a LinkedHashMap<>();
new hash table double the size of the original hash
table. By default,
If the optional parameters not used, then the the capacity of the linked hashmap will be 16
the load factor will be 0.75
default capacity will be 16 and the default load
factor will be 0.75. Note: The LinkedHashMap class also allows us to
define the order of its entries. For example
// LinkedHashMap with specified order evenNumbers.put("Four", 4);
LinkedHashMap<Key, Value> numbers2 = new System.out.println("Original LinkedHashMap: "
LinkedHashMap<>(capacity, loadFactor, + evenNumbers);
accessOrder);
// Using putIfAbsent()
Here, accessOrder is a boolean value. Its default value evenNumbers.putIfAbsent("Six", 6);
is false. In this case entries in the linked hashmap are System.out.println("Updated LinkedHashMap():
ordered on the basis of their insertion order. " + evenNumbers);
However, if true is passed as accessOrder, entries in
the linked hashmap will be ordered from least-recently //Creating LinkedHashMap of numbers
accessed to most-recently accessed. LinkedHashMap<String, Integer> numbers =
new LinkedHashMap<>();
Creating LinkedHashMap from Other Maps numbers.put("One", 1);
Here is how we can create a linked hashmap
containing all the elements of other maps. // Using putAll()
import java.util.LinkedHashMap; numbers.putAll(evenNumbers);
System.out.println("New LinkedHashMap: " +
class Main { numbers);
public static void main(String[] args) { }
// Creating a LinkedHashMap of even numbers }
LinkedHashMap<String, Integer> evenNumbers
= new LinkedHashMap<>(); Output
evenNumbers.put("Two", 2); Original LinkedHashMap: {Two=2, Four=4}
evenNumbers.put("Four", 4); Updated LinkedHashMap: {Two=2, Four=4, Six=6}
System.out.println("LinkedHashMap1: " + New LinkedHashMap: {One=1, Two=2, Four=4,
evenNumbers); Six=6}

// Creating a LinkedHashMap from other


LinkedHashMap Access LinkedHashMap Elements
LinkedHashMap<String, Integer> numbers = 1. Using entrySet(), keySet() and values()
new LinkedHashMap<>(evenNumbers); entrySet() - returns a set of all the key/value mapping
numbers.put("Three", 3); of the map
System.out.println("LinkedHashMap2: " + keySet() - returns a set of all the keys of the map
numbers); values() - returns a set of all the values of the map
} For example,
} import java.util.LinkedHashMap;

Output class Main {


LinkedHashMap1: {Two=2, Four=4} public static void main(String[] args) {
LinkedHashMap2: {Two=2, Four=4, Three=3} LinkedHashMap<String, Integer> numbers =
new LinkedHashMap<>();
Methods of LinkedHashMap
The LinkedHashMap class provides methods that numbers.put("One", 1);
allow us to perform various operations on the map. numbers.put("Two", 2);
numbers.put("Three", 3);
Insert Elements to LinkedHashMap System.out.println("LinkedHashMap: " +
put() - inserts the specified key/value mapping to the numbers);
map
putAll() - inserts all the entries from the specified map // Using entrySet()
to this map System.out.println("Key/Value mappings: " +
putIfAbsent() - inserts the specified key/value numbers.entrySet());
mapping to the map if the specified key is not present
in the map // Using keySet()
For example, System.out.println("Keys: " + numbers.keySet());
import java.util.LinkedHashMap;
// Using values()
class Main { System.out.println("Values: " +
public static void main(String[] args) { numbers.values());
// Creating LinkedHashMap of even numbers }
LinkedHashMap<String, Integer> evenNumbers }
= new LinkedHashMap<>();
Output
// Using put() LinkedHashMap: {One=1, Two=2, Three=3}
evenNumbers.put("Two", 2); Key/Value mappings: [One=1, Two=2, Three=3]
Keys: [One, Two, Three] // remove method with two parameters
Values: [1, 2, 3] boolean result = numbers.remove("Three", 3);
System.out.println("Is the entry Three removed? "
2. Using get() and getOrDefault() + result);
get() - Returns the value associated with the specified
key. If the key is not found, it returns null. System.out.println("Updated LinkedHashMap: "
getOrDefault() - Returns the value associated with the + numbers);
specified key. If the key is not found, it returns the }
specified default value. }
For example,
import java.util.LinkedHashMap; Output
LinkedHashMap: {One=1, Two=2, Three=3}
class Main { Removed value: 2
public static void main(String[] args) { Is the entry {Three=3} removed? True
Updated LinkedHashMap: {One=1}
LinkedHashMap<String, Integer> numbers =
new LinkedHashMap<>(); Other Methods of LinkedHashMap
numbers.put("One", 1); Method Description
numbers.put("Two", 2); clear() removes all the entries
numbers.put("Three", 3); from the map
System.out.println("LinkedHashMap: " + containsKey() checks if the map
numbers); contains the specified key
and returns a boolean
// Using get() value
int value1 = numbers.get("Three"); containsValue() checks if the map
System.out.println("Returned Number: " + contains the specified
value1); value and returns a
boolean value
// Using getOrDefault() size() returns the size of the
int value2 = numbers.getOrDefault("Five", 5); map
System.out.println("Returned Number: " + isEmpty() checks if the map is
value2); empty and returns a
} boolean value
}
LinkedHashMap Vs. HashMap
Output Both the LinkedHashMap and
LinkedHashMap: {One=1, Two=2, Three=3} the HashMap implements the Map interface.
Returned Number: 3 However, there exist some differences between them.
Returned Number: 5 LinkedHashMap maintains a doubly-linked list
internally. Due to this, it maintains the insertion order
Removed LinkedHashMap Elements of its elements.
remove(key) - returns and removes the entry The LinkedHashMap class requires more storage
associated with the specified key from the map than HashMap. This is
remove(key, value) - removes the entry from the map because LinkedHashMap maintains linked lists
only if the specified key mapped to be the internally.
specified value and return a boolean value The performance of LinkedHashMap is slower
For example, than HashMap.
import java.util.LinkedHashMap;

class Main {
public static void main(String[] args) {
Java WeakHashMap
The WeakHashMap class of the Java collections
LinkedHashMap<String, Integer> numbers = framework provides the feature of the hash table data
new LinkedHashMap<>(); structure.
numbers.put("One", 1); It implements the Map interface.
numbers.put("Two", 2);
numbers.put("Three", 3); Note: Keys of the weak hashmap are of
System.out.println("LinkedHashMap: " + the WeakReference type.
numbers); The object of a weak reference type can be garbage
collected in Java if the reference is no longer used in
// remove method with single parameter the program.
int value = numbers.remove("Two"); Let us learn to create a weak hash map first. Then, we
System.out.println("Removed value: " + value); will learn how it differs from a hashmap.
Create a WeakHashMap // Perform garbage collection
In order to create a weak hashmap, we must import System.gc();
the java.util.WeakHashMap package first. Once we
import the package, here is how we can create weak System.out.println("WeakHashMap after garbage
hashmaps in Java. collection: " + numbers);
}
//WeakHashMap creation with capacity 8 and load }
factor 0.6
WeakHashMap<Key, Value> numbers = new Output
WeakHashMap<>(8, 0.6); WeakHashMap: {Four=4, Two=2}
WeakHashMap after garbage collection: {Four}
In the above code, we have created a weak hashmap
named numbers.
Here, As we can see, when the key two of a weak hashmap
Key - a unique identifier used to associate each is set to null and perform garbage collection, the key is
element (value) in a map removed.
Value - elements associated by keys in a map It is because unlike hashmaps, keys of weak hashmaps
Notice the part new WeakHashMap<>(8, 0.6). Here, are of weak reference type. This means the entry of a
the first parameter is capacity and the second map are removed by the garbage collector if the key to
parameter is loadFactor. that entry is no longer used. This is useful to save
capacity - The capacity of this map is 8. Meaning, it resources.
can store 8 entries. Now let us see the same implementation in a
loadFactor - The load factor of this map is 0.6. This hashmap.
means whenever our hash table is filled by 60%, the import java.util.HashMap;
entries are moved to a new hash table of double the
size of the original hash table. class Main {
Default capacity and load factor public static void main(String[] args) {
It is possible to create a weak hashmap without // Creating HashMap of even numbers
defining its capacity and load factor. For example, HashMap<String, Integer> numbers = new
HashMap<>();
// WeakHashMap with default capacity and load
factor String two = new String("Two");
WeakHashMap<Key, Value> numbers1 = new Integer twoValue = 2;
WeakHashMap<>(); String four = new String("Four");
Integer fourValue = 4;
By default,
the capacity of the map will be 16 // Inserting elements
the load factor will be 0.75 numbers.put(two, twoValue);
numbers.put(four, fourValue);
Differences Between HashMap and WeakHashMap System.out.println("HashMap: " + numbers);
Let us see the implementation of a weak hashmap in
Java. // Make the reference null
import java.util.WeakHashMap; two = null;

class Main { // Perform garbage collection


public static void main(String[] args) { System.gc();
// Creating WeakHashMap of numbers
WeakHashMap<String, Integer> numbers = new System.out.println("HashMap after garbage
WeakHashMap<>(); collection: " + numbers);
}
String two = new String("Two"); }
Integer twoValue = 2;
String four = new String("Four"); Output
Integer fourValue = 4; HashMap: {Four=4, Two=2}
HashMap after garbage collection: {Four=4, Two=2}
// Inserting elements
numbers.put(two, twoValue); Here, when the key two of the hashmap is set
numbers.put(four, fourValue); to null and perform garbage collection, the key is not
System.out.println("WeakHashMap: " + removed.
numbers); This is because unlike weak hashmaps keys of
hashmaps are of strong reference type. This means the
// Make the reference null entry of a map is not removed by the garbage collector
two = null; even though the key to that entry is no longer used.
Note: All functionalities of hashmaps and weak
hashmaps are similar except keys of a weak hashmap String four = new String("Four");
are of weak reference, whereas keys of a hashmap are Integer fourValue = 4;
of strong reference.
// Using putIfAbsent()
Creating WeakHashMap from Other Maps evenNumbers.putIfAbsent(four, fourValue);
Here is how we can create a weak hashmap from other System.out.println("WeakHashMap of even
maps. numbers: " + evenNumbers);
import java.util.HashMap;
import java.util.WeakHashMap; //Creating WeakHashMap of numbers
WeakHashMap<String, Integer> numbers = new
class Main { WeakHashMap<>();
public static void main(String[] args) {
// Creating a hashmap of even numbers String one = new String("One");
HashMap<String, Integer> evenNumbers = new Integer oneValue = 1;
HashMap<>(); numbers.put(one, oneValue);

String two = new String("Two"); // Using putAll()


Integer twoValue = 2; numbers.putAll(evenNumbers);
evenNumbers.put(two, twoValue); System.out.println("WeakHashMap of numbers:
System.out.println("HashMap: " + " + numbers);
evenNumbers); }
}
// Creating a weak hash map from other
hashmap Output
WeakHashMap<String, Integer> numbers = new WeakHashMap of even numbers: {Four=4, Two=2}
WeakHashMap<>(evenNumbers); WeakHashMap of numbers: {Two=2, Four=4,
One=1}
System.out.println("WeakHashMap: " +
numbers); Access WeakHashMap Elements
} 1. Using entrySet(), keySet() and values()
} entrySet() - returns a set of all the key/value mapping
of the map
keySet() - returns a set of all the keys of the map
Output values() - returns a set of all the values of the map
HashMap: {Two=2} For example,
WeakHashMap: {Two=2} import java.util.WeakHashMap;

Methods of WeakHashMap class Main {


The WeakHashMap class provides methods that allow public static void main(String[] args) {
us to perform various operations on the map. // Creating WeakHashMap of even numbers
WeakHashMap<String, Integer> numbers = new
Insert Elements to WeakHashMap WeakHashMap<>();
put() - inserts the specified key/value mapping to the
map String one = new String("One");
putAll() - inserts all the entries from specified map to Integer oneValue = 1;
this map numbers.put(one, oneValue);
putIfAbsent() - inserts the specified key/value
mapping to the map if the specified key is not present String two = new String("Two");
in the map Integer twoValue = 2;
For example, numbers.put(two, twoValue);
import java.util.WeakHashMap;
System.out.println("WeakHashMap: " +
class Main { numbers);
public static void main(String[] args) {
// Creating WeakHashMap of even numbers // Using entrySet()
WeakHashMap<String, Integer> evenNumbers System.out.println("Key/Value mappings: " +
= new WeakHashMap<>(); numbers.entrySet());

String two = new String("Two"); // Using keySet()


Integer twoValue = 2; System.out.println("Keys: " + numbers.keySet());

// Using put() // Using values()


evenNumbers.put(two, twoValue);
System.out.println("Values: " + public static void main(String[] args) {
numbers.values()); // Creating WeakHashMap of even numbers
} WeakHashMap<String, Integer> numbers = new
} WeakHashMap<>();

Output String one = new String("One");


WeakHashMap: {Two=2, One=1} Integer oneValue = 1;
Key/Value mappings: [Two=2, One=1] numbers.put(one, oneValue);
Keys: [Two, One]
Values: [1, 2] String two = new String("Two");
Integer twoValue = 2;
2. Using get() and getOrDefault() numbers.put(two, twoValue);
get() - Returns the value associated with the specified
key. Returns null if the key is not found. System.out.println("WeakHashMap: " +
getOrDefault() - Returns the value associated with the numbers);
specified key. Returns the specified default value if the
key is not found. // Using remove() with single parameter
For example, int value = numbers.remove("Two");
import java.util.WeakHashMap; System.out.println("Removed value: " + value);

class Main { // Using remove() with 2 parameters


public static void main(String[] args) { boolean result = numbers.remove("One", 3);
// Creating WeakHashMap of even numbers System.out.println("Is the entry {One=3}
WeakHashMap<String, Integer> numbers = new removed? " + result);
WeakHashMap<>();
System.out.println("Updated WeakHashMap: " +
String one = new String("One"); numbers);
Integer oneValue = 1; }
numbers.put(one, oneValue); }

String two = new String("Two");


Integer twoValue = 2; Output
numbers.put(two, twoValue); WeakHashMap: {Two=2, One=1}
Removed value: 2
System.out.println("WeakHashMap: " + Is the entry {One=3} removed? false
numbers); Updated WeakHashMap: {One=1}

// Using get() Other Methods of WeakHashMap


int value1 = numbers.get("Two"); Method Description
System.out.println("Using get(): " + value1); clear() Removes all the entries from the
map
// Using getOrDefault() containsKey() Checks if the map contains the
int value2 = numbers.getOrDefault("Four", 4); specified key and returns a
System.out.println("Using getOrDefault(): " + boolean value
value2); containsValue() Checks if the map contains the
specified value and returns a
} boolean value
} size() Returns the size of the map
isEmpty() Checks if the map is empty and
Output returns a boolean value
WeakHashMap: {Two=2, One=1}
Using get(): 2
Using getOrDefault(): 4
Java EnumMap
The EnumMap class of the Java collections
Remove WeakHashMap Elements
remove(key) - returns and removes the entry framework provides a map implementation for
associated with the specified key from the map elements of an enum.
remove(key, value) - removes the entry from the map In EnumMap, enum elements are used as keys. It
only if the specified key mapped to the specified value implements the Map interface.
and return a boolean value
For example,
import java.util.WeakHashMap; Creating an EnumMap
In order to create an enum map, we must import
class Main { the java.util.EnumMap package first. Once we import
the package, here is how we can create enum maps in using putAll(). However, all maps should be of the
Java. same enum type.
enum Size {
SMALL, MEDIUM, LARGE, EXTRALARGE Access EnumMap Elements
} 1. Using entrySet(), keySet() and values()
entrySet() - returns a set of all the keys/values
EnumMap<Size, Integer> sizes = new mapping (entry) of an enum map
EnumMap<>(Size.class); keySet() - returns a set of all the keys of an enum map
values() - returns a set of all the values of an enum
In the above example, we have created an enum map map
named sizes.
Here, For example,
Size - keys of the enum that map to values import java.util.EnumMap;
Integer - values of the enum map associated with the
corresponding keys class Main {

Methods of EnumMap enum Size {


The EnumMap class provides methods that allow us SMALL, MEDIUM, LARGE, EXTRALARGE
to perform various elements on the enum maps. }
public static void main(String[] args) {
Insert Elements to EnumMap
put() - inserts the specified key/value mapping (entry) // Creating an EnumMap of the Size enum
to the enum map EnumMap<Size, Integer> sizes = new
putAll() - inserts all the entries of a specified map to EnumMap<>(Size.class);
this map sizes.put(Size.SMALL, 28);
For example, sizes.put(Size.MEDIUM, 32);
import java.util.EnumMap; sizes.put(Size.LARGE, 36);
sizes.put(Size.EXTRALARGE, 40);
class Main { System.out.println("EnumMap: " + sizes);

enum Size { // Using the entrySet() Method


SMALL, MEDIUM, LARGE, EXTRALARGE System.out.println("Key/Value mappings: " +
} sizes.entrySet());
public static void main(String[] args) {
// Using the keySet() Method
// Creating an EnumMap of the Size enum System.out.println("Keys: " + sizes.keySet());
EnumMap<Size, Integer> sizes1 = new
EnumMap<>(Size.class); // Using the values() Method
System.out.println("Values: " + sizes.values());
// Using the put() Method }
sizes1.put(Size.SMALL, 28); }
sizes1.put(Size.MEDIUM, 32);
System.out.println("EnumMap1: " + sizes1); Output
EnumMap: {SMALL=28, MEDIUM=32,
EnumMap<Size, Integer> sizes2 = new LARGE=36, EXTRALARGE=40}
EnumMap<>(Size.class); Key/Value mappings: [SMALL=28, MEDIUM=32,
LARGE=36, EXTRALARGE=40]
// Using the putAll() Method Keys: [SMALL, MEDIUM, LARGE,
sizes2.putAll(sizes1); EXTRALARGE]
sizes2.put(Size.LARGE, 36); Values: [28, 32, 36, 40]
System.out.println("EnumMap2: " + sizes2);
} 2. Using the get() Method
} The get() method returns the value associated with the
specified key. It returns null if the specified key is not
Output found.
EnumMap1: {SMALL=28, MEDIUM=32} For example,
EnumMap2: {SMALL=28, MEDIUM=32, import java.util.EnumMap;
LARGE=36}
class Main {
In the above example, we have used
the putAll() method to insert all the elements of an enum Size {
enum map sizes1 to an enum map of sizes2. SMALL, MEDIUM, LARGE, EXTRALARGE
It is also possible to insert elements from other maps }
such as HashMap, TreeMap, etc. to an enum map public static void main(String[] args) {
Is the entry {SMALL=28} removed? True
// Creating an EnumMap of the Size enum Updated EnumMap: {LARGE=36,
EnumMap<Size, Integer> sizes = new EXTRALARGE=40}
EnumMap<>(Size.class);
sizes.put(Size.SMALL, 28); Replace EnumMap Elements
sizes.put(Size.MEDIUM, 32); replace(key, value) - replaces the value associated with
sizes.put(Size.LARGE, 36); the specified key by the new value
sizes.put(Size.EXTRALARGE, 40); replace(key, old, new) - replaces the old value with
System.out.println("EnumMap: " + sizes); the new value only if the old value is already
associated with the specified key
// Using the get() Method replaceAll(function) - replaces each value of the map
int value = sizes.get(Size.MEDIUM); with the result of the specified function
System.out.println("Value of MEDIUM: " + import java.util.EnumMap;
value);
} class Main {
}
enum Size {
Output SMALL, MEDIUM, LARGE, EXTRALARGE
EnumMap: {SMALL=28, MEDIUM=32, }
LARGE=36, EXTRALARGE=40} public static void main(String[] args) {
Value of MEDIUM: 32
// Creating an EnumMap of the Size enum
Remove EnumMap Elements EnumMap<Size, Integer> sizes = new
remove(key) - returns and removes the entry EnumMap<>(Size.class);
associated with the specified key from the map sizes.put(Size.SMALL, 28);
remove(key, value) - removes the entry from the map sizes.put(Size.MEDIUM, 32);
only if the specified key mapped to the specified value sizes.put(Size.LARGE, 36);
and return a boolean value sizes.put(Size.EXTRALARGE, 40);
For example, System.out.println("EnumMap: " + sizes);
import java.util.EnumMap;
// Using the replace() Method
class Main { sizes.replace(Size.MEDIUM, 30);
sizes.replace(Size.LARGE, 36, 34);
enum Size { System.out.println("EnumMap using replace(): "
SMALL, MEDIUM, LARGE, EXTRALARGE + sizes);
}
public static void main(String[] args) { // Using the replaceAll() Method
sizes.replaceAll((key, oldValue) -> oldValue + 3);
// Creating an EnumMap of the Size enum System.out.println("EnumMap using
EnumMap<Size, Integer> sizes = new replaceAll(): " + sizes);
EnumMap<>(Size.class); }
sizes.put(Size.SMALL, 28); }
sizes.put(Size.MEDIUM, 32);
sizes.put(Size.LARGE, 36); Output
sizes.put(Size.EXTRALARGE, 40); EnumMap: {SMALL=28, MEDIUM=32,
System.out.println("EnumMap: " + sizes); LARGE=36, EXTRALARGE=40}
EnumMap using replace(): {SMALL=28,
// Using the remove() Method MEDIUM=30, LARGE=34, EXTRALARGE=40}
int value = sizes.remove(Size.MEDIUM); EnumMap using replaceAll(): {SMALL=31,
System.out.println("Removed Value: " + value); MEDIUM=33, LARGE=37, EXTRALARGE=43}

boolean result = sizes.remove(Size.SMALL, 28); In the above program, notice the statement
System.out.println("Is the entry {SMALL=28} sizes.replaceAll((key, oldValue) -> oldValue + 3);
removed? " + result);
Here, the method accesses all the entries of the map. It
System.out.println("Updated EnumMap: " + then replaces all the values with the new values
sizes); provided by the lambda expressions.
}
}

Output
EnumMap: {SMALL=28, MEDIUM=32,
LARGE=36, EXTRALARGE=40}
Removed Value: 32
Other Methods Class that implements SortedMap
Method Description Since SortedMap is an interface, we cannot create
clone() Creates a copy of the EnumMap objects from it.
containsKey() Searches the EnumMap for the In order to use the functionalities of
specified key and returns a boolean the SortedMap interface, we need to use the
result class TreeMap that implements it.
containsValue() Searches the EnumMap for the
specified value and returns a
boolean result
size() Returns the size of the EnumMap
clear() Removes all the entries from the
EnumMap

EnumSet Vs. EnumMap


Both the EnumSet and EnumMap class provides data
structures to store enum values. However, there exist
some major differences between them.
Enum set is represented internally as a sequence of
bits, whereas the enum map is represented internally
as arrays.
Enum set is created using its predefined methods
like allOf(), noneOf(), of(), etc. However, an enum
map is created using its constructor.
How to use SortedMap?
Clonable and Serializable Interfaces To use the SortedMap, we must import
The EnumMap class also
the java.util.SortedMap package first. Once we import
implements Cloneable and Serializable interfaces.
the package, here's how we can create a sorted map.
Cloneable Interface
It allows the EnumMap class to make a copy of
// SortedMap implementation by TreeMap class
instances of the class. SortedMap<Key, Value> numbers = new
Serializable Interface
TreeMap<>();
Whenever Java objects need to be transmitted over a
network, objects need to be converted into bits or
We have created a sorted map called numbers using
bytes. This is because Java objects cannot be
the TreeMap class.
transmitted over the network. Here,
The Serializable interface allows classes to be
Key - a unique identifier used to associate each
serialized. This means objects of the classes
element (value) in a map
implementing Serializable can be converted into bits
Value - elements associated by keys in a map
or bytes. Here, we have used no arguments to create a sorted
map. Hence the map will be sorted naturally
(ascending order).
Java SortedMap Interface
The SortedMap interface of the Java collections Methods of SortedMap
framework provides sorting of keys stored in a map. The SortedMap interface includes all the methods of
It extends the Map interface. the Map interface. It is because Map is a super
interface of SortedMap.
Besides all those methods, here are the methods
specific to the SortedMap interface.
comparator() - returns a comparator that can be used
to order keys in a map
firstKey() - returns the first key of the sorted map
lastKey() - returns the last key of the sorted map
headMap(key) - returns all the entries of a map whose
keys are less than the specified key
tailMap(key) - returns all the entries of a map whose
keys are greater than or equal to the specified key
subMap(key1, key2) - returns all the entries of a map
whose keys lies in
between key1 and key2 including key1

Implementation of SortedMap in TreeMap Class


import java.util.SortedMap;
import java.util.TreeMap;
How to use NavigableMap?
class Main { In Java, we must import
the java.util.NavigableMap package to
public static void main(String[] args) { use NavigableMap. Once we import the package,
// Creating SortedMap using TreeMap here's how we can create a navigable map.
SortedMap<String, Integer> numbers = new
TreeMap<>(); // NavigableMap implementation by TreeMap class
NavigableMap<Key, Value> numbers = new
// Insert elements to map TreeMap<>();
numbers.put("Two", 2);
numbers.put("One", 1); In the above code, we have created a navigable map
System.out.println("SortedMap: " + numbers); named numbers of the TreeMap class.
Here,
Key - a unique identifier used to associate each
// Access the first key of the map element (value) in a map
System.out.println("First Key: " + Value - elements associated by keys in a map
numbers.firstKey());
Methods of NavigableMap
// Access the last key of the map The NavigableMap is considered as a type
System.out.println("Last Key: " + of SortedMap. It is because NavigableMap extends
numbers.lastKey()); the SortedMap interface.
Hence, all SortedMap methods are also available
// Remove elements from the map in NavigableMap.
int value = numbers.remove("One"); However, some of the methods
System.out.println("Removed Value: " + value); of SortedMap (headMap(), tailMap(), and subMap() )
} are defined differently in NavigableMap.
} Let's see how these methods are defined
in NavigableMap.
Output
SortedMap: {One=1, Two=2} headMap(key, booleanValue)
First Key: One The headMap() method returns all the entries of a
Last Key: Two navigable map associated with all those keys before
Removed Value: 1 the specified key (which is passed as an argument).
The booleanValue is an optional parameter. Its default
value is false.
Java NavigableMap Interface If true is passed as a booleanValue, the method returns
The NavigableMap interface of the Java collections all the entries associated with all those keys before the
framework provides the features to navigate among specified key, including the entry associated with the
the map entries. specified key.
It is considered as a type of SortedMap.
tailMap(key, booleanValue)
Class that implements NavigableMap The tailMap() method returns all the entries of a
Since NavigableMap is an interface, we cannot create navigable map associated with all those keys after the
objects from it. specified key (which is passed as an argument)
In order to use the functionalities of including the entry associated with the specified key.
the NavigableMap interface, we need to use The booleanValue is an optional parameter. Its default
the TreeMap class that implements NavigableMap. value is true.
If false is passed as a booleanValue, the method
returns all the entries associated with those keys after
the specified key, without including the entry
associated with the specified key.

subMap(k1, bv1, k2, bv2)


The subMap() method returns all the entries
associated with keys between k1 and k2 including the
entry associated with k1.
The bv1 and bv2 are optional parameters. The default
value of bv1 is true and the default value
of bv2 is false.
If false is passed as bv1, the method returns all the
entries associated with keys between k1 and k2,
without including the entry associated with k1.
If true is passed as bv2, the method returns all the System.out.println("Last Entry: " +
entries associated with keys between k1 and k2, numbers.lastEntry());
including the entry associated with k1.
// Remove the first entry from the map
Other Methods System.out.println("Removed First Entry: " +
The NavigableMap provides various methods that can numbers.pollFirstEntry());
be used to locate the entries of maps.
descendingMap() - reverse the order of entries in a // Remove the last entry from the map
map System.out.println("Removed Last Entry: " +
descendingKeyMap() - reverses the order of keys in a numbers.pollLastEntry());
map }
ceilingEntry() - returns an entry with the lowest key }
among all those entries whose keys are greater than or
equal to the specified key Output
ceilingKey() - returns the lowest key among those keys NavigableMap: {One=1, Three=3, Two=2}
that are greater than or equal to the specified key First Entry: One=1
floorEntry() - returns an entry with the highest key Last Entry: Two=2
among all those entries whose keys are less than or Removed First Entry: One=1
equal to the specified key Removed Last Entry: Two=2
floorKey() - returns the highest key among those keys
that are less than or equal to the specified key
higherEntry() - returns an entry with the lowest key Java NavigableMap Interface
among all those entries whose keys are greater than The NavigableMap interface of the Java collections
the specified key framework provides the features to navigate among
higherKey() - returns the lowest key among those keys the map entries.
that are greater than the specified key It is considered as a type of SortedMap.
lowerEntry() - returns an entry with the highest key
among all those entries whose keys are less than the Class that implements NavigableMap
specified key Since NavigableMap is an interface, we cannot create
lowerKey() - returns the highest key among those keys objects from it.
that are less than the specified key In order to use the functionalities of
firstEntry() - returns the first entry (the entry with the the NavigableMap interface, we need to use
lowest key) of the map the TreeMap class that implements NavigableMap.
lastEntry() - returns the last entry (the entry with the
highest key) of the map
pollFirstEntry() - returns and removes the first entry of
the map
pollLastEntry() - returns and removes the last entry of
the map

Implementation of NavigableMap in TreeMap Class


import java.util.NavigableMap;
import java.util.TreeMap;

class Main {

public static void main(String[] args) {


// Creating NavigableMap using TreeMap
NavigableMap<String, Integer> numbers = new
TreeMap<>();
How to use NavigableMap?
// Insert elements to map In Java, we must import
numbers.put("Two", 2); the java.util.NavigableMap package to
numbers.put("One", 1); use NavigableMap. Once we import the package,
numbers.put("Three", 3); here's how we can create a navigable map.
System.out.println("NavigableMap: " +
numbers); // NavigableMap implementation by TreeMap class
NavigableMap<Key, Value> numbers = new
// Access the first entry of the map TreeMap<>();
System.out.println("First Entry: " +
numbers.firstEntry()); In the above code, we have created a navigable map
named numbers of the TreeMap class.
// Access the last entry of the map Here,
Key - a unique identifier used to associate each ceilingKey() - returns the lowest key among those keys
element (value) in a map that are greater than or equal to the specified key
Value - elements associated by keys in a map floorEntry() - returns an entry with the highest key
among all those entries whose keys are less than or
Methods of NavigableMap equal to the specified key
The NavigableMap is considered as a type floorKey() - returns the highest key among those keys
of SortedMap. It is because NavigableMap extends that are less than or equal to the specified key
the SortedMap interface. higherEntry() - returns an entry with the lowest key
Hence, all SortedMap methods are also available among all those entries whose keys are greater than
in NavigableMap. the specified key
However, some of the methods higherKey() - returns the lowest key among those keys
of SortedMap (headMap(), tailMap(), and subMap() ) that are greater than the specified key
are defined differently in NavigableMap. lowerEntry() - returns an entry with the highest key
among all those entries whose keys are less than the
Let's see how these methods are defined specified key
in NavigableMap. lowerKey() - returns the highest key among those keys
that are less than the specified key
headMap(key, booleanValue) firstEntry() - returns the first entry (the entry with the
The headMap() method returns all the entries of a lowest key) of the map
navigable map associated with all those keys before lastEntry() - returns the last entry (the entry with the
the specified key (which is passed as an argument). highest key) of the map
The booleanValue is an optional parameter. Its default pollFirstEntry() - returns and removes the first entry of
value is false. the map
If true is passed as a booleanValue, the method returns pollLastEntry() - returns and removes the last entry of
all the entries associated with all those keys before the the map
specified key, including the entry associated with the
specified key. Implementation of NavigableMap in TreeMap Class
import java.util.NavigableMap;
tailMap(key, booleanValue) import java.util.TreeMap;
The tailMap() method returns all the entries of a
navigable map associated with all those keys after the class Main {
specified key (which is passed as an argument)
including the entry associated with the specified key. public static void main(String[] args) {
The booleanValue is an optional parameter. Its default // Creating NavigableMap using TreeMap
value is true. NavigableMap<String, Integer> numbers = new
If false is passed as a booleanValue, the method TreeMap<>();
returns all the entries associated with those keys after
the specified key, without including the entry // Insert elements to map
associated with the specified key. numbers.put("Two", 2);
numbers.put("One", 1);
subMap(k1, bv1, k2, bv2) numbers.put("Three", 3);
The subMap() method returns all the entries System.out.println("NavigableMap: " +
associated with keys between k1 and k2 including the numbers);
entry associated with k1.
The bv1 and bv2 are optional parameters. The default // Access the first entry of the map
value of bv1 is true and the default value System.out.println("First Entry: " +
of bv2 is false. numbers.firstEntry());
If false is passed as bv1, the method returns all the
entries associated with keys between k1 and k2, // Access the last entry of the map
without including the entry associated with k1. System.out.println("Last Entry: " +
If true is passed as bv2, the method returns all the numbers.lastEntry());
entries associated with keys between k1 and k2,
including the entry associated with k1. // Remove the first entry from the map
System.out.println("Removed First Entry: " +
Other Methods numbers.pollFirstEntry());
The NavigableMap provides various methods that can
be used to locate the entries of maps. // Remove the last entry from the map
descendingMap() - reverse the order of entries in a System.out.println("Removed Last Entry: " +
map numbers.pollLastEntry());
descendingKeyMap() - reverses the order of keys in a }
map }
ceilingEntry() - returns an entry with the lowest key
among all those entries whose keys are greater than or Output
equal to the specified key NavigableMap: {One=1, Three=3, Two=2}
First Entry: One=1 putIfAbsent() - inserts the specified key/value
Last Entry: Two=2 mapping to the map if the specified key is not present
Removed First Entry: One=1 in the map
Removed Last Entry: Two=2 For example,
import java.util.TreeMap;

Java TreeMap class Main {


The TreeMap class of the Java collections public static void main(String[] args) {
framework provides the tree data structure // Creating TreeMap of even numbers
implementation. TreeMap<String, Integer> evenNumbers = new
It implements the NavigableMap interface. TreeMap<>();

// Using put()
evenNumbers.put("Two", 2);
evenNumbers.put("Four", 4);

// Using putIfAbsent()
evenNumbers.putIfAbsent("Six", 6);
System.out.println("TreeMap of even numbers: "
+ evenNumbers);

//Creating TreeMap of numbers


TreeMap<String, Integer> numbers = new
TreeMap<>();
numbers.put("One", 1);

// Using putAll()
numbers.putAll(evenNumbers);
System.out.println("TreeMap of numbers: " +
numbers);
}
}

Creating a TreeMap Output


In order to create a TreeMap, we must import TreeMap of even numbers: {Four=4, Six=6, Two=2}
the java.util.TreeMap package first. Once we import TreeMap of numbers: {Four=4, One=1, Six=6,
the package, here is how we can create a TreeMap in Two=2}
Java.
Access TreeMap Elements
TreeMap<Key, Value> numbers = new 1. Using entrySet(), keySet() and values()
TreeMap<>(); entrySet() - returns a set of all the key/values mapping
(entry) of a treemap
In the above code, we have created keySet() - returns a set of all the keys of a tree map
a TreeMap named numbers without any arguments. values() - returns a set of all the maps of a tree map
In this case, the elements in TreeMap are sorted For example,
naturally (ascending order). import java.util.TreeMap;
However, we can customize the sorting of elements by
using the Comparator interface. We will learn about it class Main {
later in this tutorial. public static void main(String[] args) {
Here, TreeMap<String, Integer> numbers = new
Key - a unique identifier used to associate each TreeMap<>();
element (value) in a map
Value - elements associated by keys in a map numbers.put("One", 1);
numbers.put("Two", 2);
Methods of TreeMap numbers.put("Three", 3);
The TreeMap class provides various methods that System.out.println("TreeMap: " + numbers);
allow us to perform operations on the map.
// Using entrySet()
Insert Elements to TreeMap System.out.println("Key/Value mappings: " +
put() - inserts the specified key/value mapping (entry) numbers.entrySet());
to the map
putAll() - inserts all the entries from specified map to // Using keySet()
this map System.out.println("Keys: " + numbers.keySet());
// Using values() numbers.put("One", 1);
System.out.println("Values: " + numbers.put("Two", 2);
numbers.values()); numbers.put("Three", 3);
} System.out.println("TreeMap: " + numbers);
}
// remove method with single parameter
Output int value = numbers.remove("Two");
TreeMap: {One=1, Three=3, Two=2} System.out.println("Removed value: " + value);
Key/Value mappings: [One=1, Three=3, Two=2]
Keys: [One, Three, Two] // remove method with two parameters
Values: [1, 3, 2] boolean result = numbers.remove("Three", 3);
System.out.println("Is the entry {Three=3}
2. Using get() and getOrDefault() removed? " + result);
get() - Returns the value associated with the specified
key. Returns null if the key is not found. System.out.println("Updated TreeMap: " +
getOrDefault() - Returns the value associated with the numbers);
specified key. Returns the specified default value if the }
key is not found. }
For example,
import java.util.TreeMap; Output
TreeMap: {One=1, Three=3, Two=2}
class Main { Removed value = 2
public static void main(String[] args) { Is the entry {Three=3} removed? True
Updated TreeMap: {One=1}
TreeMap<String, Integer> numbers = new
TreeMap<>(); Replace TreeMap Elements
numbers.put("One", 1); replace(key, value) - replaces the value mapped by the
numbers.put("Two", 2); specified key with the new value
numbers.put("Three", 3); replace(key, old, new) - replaces the old value with the
System.out.println("TreeMap: " + numbers); new value only if the old value is already associated
with the specified key
// Using get() replaceAll(function) - replaces each value of the map
int value1 = numbers.get("Three"); with the result of the specified function
System.out.println("Using get(): " + value1); For example,
import java.util.TreeMap;
// Using getOrDefault()
int value2 = numbers.getOrDefault("Five", 5); class Main {
System.out.println("Using getOrDefault(): " + public static void main(String[] args) {
value2);
} TreeMap<String, Integer> numbers = new
} TreeMap<>();
numbers.put("First", 1);
Output numbers.put("Second", 2);
TreeMap: {One=1, Three=3, Two=2} numbers.put("Third", 3);
Using get(): 3 System.out.println("Original TreeMap: " +
Using getOrDefault(): 5 numbers);

Here, the getOrDefault() method does not find the // Using replace()
key Five. Hence it returns the specified default value 5. numbers.replace("Second", 22);
numbers.replace("Third", 3, 33);
Remove TeeMap Elements System.out.println("TreeMap using replace: " +
remove(key) - returns and removes the entry numbers);
associated with the specified key from a TreeMap
remove(key, value) - removes the entry from the map // Using replaceAll()
only if the specified key is associated with the specified numbers.replaceAll((key, oldValue) -> oldValue
value and returns a boolean value + 2);
For example, System.out.println("TreeMap using replaceAll: "
import java.util.TreeMap; + numbers);
}
class Main { }
public static void main(String[] args) { Output
Original TreeMap: {First=1, Second=2, Third=3}
TreeMap<String, Integer> numbers = new TreeMap using replace(): {First=1, Second=22,
TreeMap<>(); Third=33}
TreeMap using replaceAll(): {First=3, Second=24, higherEntry() - Returns an entry associated with a key
Third=35} that is lowest among all those keys greater than the
specified key.
In the above program notice the statement lowerKey() - Returns the greatest key among all those
numbers.replaceAll((key, oldValue) -> oldValue + 2); keys that are less than the specified key.
Here, we have passed a lambda expression as an lowerEntry() - Returns an entry associated with a key
argument. that is greatest among all those keys that are less than
The replaceAll() method accesses all the entries of the the specified key.
map. It then replaces all the elements with the new ceilingKey() - Returns the lowest key among those
values (returned from the lambda expression). keys that are greater than the specified key. If the key
passed as an argument is present in the map, it returns
Methods for Navigation that key.
Since the TreeMap class implements NavigableMap, it ceilingEntry() - Returns an entry associated with a key
provides various methods to navigate over the that is lowest among those keys that are greater than
elements of the treemap. the specified key. It an entry associated with the key
passed an argument is present in the map, it returns
1. First and Last Methods the entry associated with that key.
firstKey() - returns the first key of the map floorKey() - Returns the greatest key among those keys
firstEntry() - returns the key/value mapping of the first that are less than the specified key. If the key passed as
key of the map an argument is present, it returns that key.
lastKey() - returns the last key of the map floorEntry() - Returns an entry associated with a key
lastEntry() - returns the key/value mapping of the last that is greatest among those keys that are less than the
key of the map specified key. If the key passed as argument is present,
For example, it returns that key.
import java.util.TreeMap; For example,

class Main { import java.util.TreeMap;


public static void main(String[] args) {
TreeMap<String, Integer> numbers = new class Main {
TreeMap<>(); public static void main(String[] args) {
numbers.put("First", 1);
numbers.put("Second", 2); TreeMap<String, Integer> numbers = new
numbers.put("Third", 3); TreeMap<>();
System.out.println("TreeMap: " + numbers); numbers.put("First", 1);
numbers.put("Second", 5);
// Using the firstKey() method numbers.put("Third", 4);
String firstKey = numbers.firstKey(); numbers.put("Fourth", 6);
System.out.println("First Key: " + firstKey); System.out.println("TreeMap: " + numbers);

// Using the lastKey() method // Using higher()


String lastKey = numbers.lastKey(); System.out.println("Using higherKey(): " +
System.out.println("Last Key: " + lastKey); numbers.higherKey("Fourth"));
System.out.println("Using higherEntry(): " +
// Using firstEntry() method numbers.higherEntry("Fourth"));
System.out.println("First Entry: " +
numbers.firstEntry()); // Using lower()
System.out.println("\nUsing lowerKey(): " +
numbers.lowerKey("Fourth"));
// Using the lastEntry() method System.out.println("Using lowerEntry(): " +
System.out.println("Last Entry: " + numbers.lowerEntry("Fourth"));
numbers.lastEntry());
} // Using ceiling()
} System.out.println("\nUsing ceilingKey(): " +
numbers.ceilingKey("Fourth"));
Output System.out.println("Using ceilingEntry(): " +
TreeMap: {First=1, Second=2, Third=3} numbers.ceilingEntry("Fourth"));
First Key: First
Last Key: Third // Using floor()
First Entry: First=1 System.out.println("\nUsing floorKey(): " +
Last Entry: Third=3 numbers.floorKey("Fourth"));
System.out.println("Using floorEntry(): " +
2. Ceiling, Floor, Higher and Lower Methods numbers.floorEntry("Fourth"));
higherKey() - Returns the lowest key among those
keys that are greater than the specified key.
} If true is passed as a booleanValue, the method also
} includes the key/value pair of the key which is passed
as an argument.
Output For example,
TreeMap: {First=1, Fourth=6, Second=5, Third=4} import java.util.TreeMap;
Using higherKey(): Second
Using higherEntry(): Second=5 class Main {
public static void main(String[] args) {
Using lowerKey(): First
Using lowerEntry(): First=1 TreeMap<String, Integer> numbers = new
TreeMap<>();
Using ceilingKey(): Fourth numbers.put("First", 1);
Using ceilingEntry(): Fourth=6 numbers.put("Second", 2);
numbers.put("Third", 3);
Using floorkey(): Fourth numbers.put("Fourth", 4);
Using floorEntry(): Fourth=6 System.out.println("TreeMap: " + numbers);

3. pollFirstEntry() and pollLastEntry() Methods System.out.println("\nUsing headMap()


pollFirstEntry() - returns and removes the entry Method:");
associated with the first key of the map // Using headMap() with default booleanValue
pollLastEntry() - returns and removes the entry System.out.println("Without boolean value: " +
associated with the last key of the map numbers.headMap("Fourth"));
For example,
import java.util.TreeMap; // Using headMap() with specified booleanValue
System.out.println("With boolean value: " +
class Main { numbers.headMap("Fourth", true));
public static void main(String[] args) {
}
TreeMap<String, Integer> numbers = new }
TreeMap<>();
numbers.put("First", 1); Output
numbers.put("Second", 2); TreeMap: {First=1, Fourth=4, Second=2, Third=3}
numbers.put("Third", 3);
System.out.println("TreeMap: " + numbers); Using headMap() Method:
Without boolean value: {First=1}
//Using the pollFirstEntry() method With boolean value: {First=1, Fourth=4}
System.out.println("Using pollFirstEntry(): " + tailMap(key, booleanValue)
numbers.pollFirstEntry()); The tailMap() method returns all the key/value pairs
of a treemap starting from the specified key (which is
// Using the pollLastEntry() method passed as an argument).
System.out.println("Using pollLastEntry(): " + The booleanValue is an optional parameter. Its default
numbers.pollLastEntry()); value is true.
If false is passed as a booleanValue, the method
System.out.println("Updated TreeMap: " + doesn't include the key/value pair of the specified key.
numbers); For example,
import java.util.TreeMap;
}
} class Main {
public static void main(String[] args) {
Output
TreeMap: {First=1, Second=2, Third=3} TreeMap<String, Integer> numbers = new
Using pollFirstEntry(): First=1 TreeMap<>();
Using pollLastEntry(): Third=3 numbers.put("First", 1);
Updated TreeMap: {Second=2} numbers.put("Second", 2);
numbers.put("Third", 3);
numbers.put("Fourth", 4);
4. headMap(), tailMap() and subMap() Methods
System.out.println("TreeMap: " + numbers);
headMap(key, booleanValue)
The headMap() method returns all the key/value pairs
System.out.println("\nUsing tailMap()
of a treemap before the specified key (which is passed
Method:");
as an argument).
// Using tailMap() with default booleanValue
The booleanValue parameter is optional. Its default
System.out.println("Without boolean value: " +
value is false.
numbers.tailMap("Second"));
// Using tailMap() with specified booleanValue the specified value and
System.out.println("With boolean value: " + returns a boolean result
numbers.tailMap("Second", false)); }} size() Returns the size of the
TreeMap
Output clear() Removes all the entries
TreeMap: {First=1, Fourth=4, Second=2, Third=3} from the TreeMap

Using tailMap() Method: TreeMap Comparator


Without boolean value: {Second=2, Third=3} In all the examples above, treemap elements are sorted
With boolean value: {Third=3} naturally (in ascending order). However, we can also
subMap(k1, bV1, k2, bV2) customize the ordering of keys.
The subMap() method returns all the entries For this, we need to create our own comparator class
associated with keys between k1 and k2 including the based on which keys in a treemap are sorted. For
entry of k1. example,
The bV1 and bV2 are optional boolean parameters. import java.util.TreeMap;
The default value of bV1 is true and the default value import java.util.Comparator;
of bV2 is false.
If false is passed as bV1, the method returns all the class Main {
entries associated with keys public static void main(String[] args) {
between k1 and k2 without including the entry of k1.
If true is passed as bV2, the method returns all the // Creating a treemap with a customized
entries associated with keys comparator
between k1 and k2 including the entry of k2. TreeMap<String, Integer> numbers = new
For example, TreeMap<>(new CustomComparator());
import java.util.TreeMap;
numbers.put("First", 1);
class Main { numbers.put("Second", 2);
public static void main(String[] args) { numbers.put("Third", 3);
numbers.put("Fourth", 4);
TreeMap<String, Integer> numbers = new System.out.println("TreeMap: " + numbers);
TreeMap<>(); }
numbers.put("First", 1); // Creating a comparator class
numbers.put("Second", 2); public static class CustomComparator implements
numbers.put("Third", 3); Comparator<String> {
numbers.put("Fourth", 4);
System.out.println("TreeMap: " + numbers); @Override
public int compare(String number1, String
System.out.println("\nUsing subMap() number2) {
Method:"); int value = number1.compareTo(number2);
// Using subMap() with default booleanValue
System.out.println("Without boolean value: " + // elements are sorted in reverse order
numbers.subMap("Fourth", "Third")); if (value > 0) {
return -1;}
// Using subMap() with specified booleanValue else if (value < 0) {
System.out.println("With boolean value: " + return 1;}
numbers.subMap("Fourth", false, "Third", true)); else {
}} return 0;}}}}

Output Output
TreeMap: {First=1, Fourth=2, Second=2, Third=3} TreeMap: {Third=3, Second=2, Fourth=4, First=1}
In the above example, we have created a treemap
Using subMap() Method: passing CustomComparator class as an argument.
Without boolean value: {Fourth=4, Second=2} The CustomComparator class implements
With boolean value: {Second=2, Third=3} the Comparator interface.
We then override the compare() method to sort
Other Methods of TreeMap elements in reverse order.
Method Description
clone() Creates a copy of the
TreeMap Java ConcurrentMap Interface
containsKey() Searches the TreeMap for The ConcurrentMap interface of the Java collections
the specified key and framework provides a thread-safe map. That is,
returns a boolean result multiple threads can access the map at once without
containsValue() Searches the TreeMap for affecting the consistency of entries in a map.
ConcurrentMap is known as a synchronized map. merge() - Merges the new specified value with the old
It extends the Map interface. value of the specified key if the key is already mapped
to a certain value. If the key is not already mapped,
Class that implements ConcurrentMap the method simply associates the specified value to our
Since ConcurrentMap is an interface, we cannot create key.
objects from it.
In order to use the functionalities of Implementation of ConcurrentMap in
the ConcurrentMap interface, we need to use the ConcurrentHashMap
class ConcurrentHashMap that implements it. import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentHashMap;

class Main {

public static void main(String[] args) {


// Creating ConcurrentMap using
ConcurrentHashMap
ConcurrentMap<String, Integer> numbers = new
ConcurrentHashMap<>();

// Insert elements to map


numbers.put("Two", 2);
numbers.put("One", 1);
numbers.put("Three", 3);
System.out.println("ConcurrentMap: " +
numbers);
How to use ConcurrentMap?
To use the ConcurrentMap, we must import // Access the value of specified key
the java.util.concurrent.ConcurrentMap package first. int value = numbers.get("One");
Once we import the package, here's how we can create System.out.println("Accessed Value: " + value);
a concurrent map.
// Remove the value of specified key
// ConcurrentMap implementation by int removedValue = numbers.remove("Two");
ConcurrentHashMap System.out.println("Removed Value: " +
CocurrentMap<Key, Value> numbers = new removedValue);
ConcurrentHashMap<>(); }
}

In the above code, we have created a concurrent map Output


named numbers. ConcurrentMap: {One=1, Two=2, Three=3}
Here, Accessed Value: 1
Key - a unique identifier used to associate each Removed Value: 2
element (value) in a map
Value - elements associated by keys in a map
Java ConcurrentHashMap
Methods of ConcurrentMap The ConcurrentHashMap class of the Java collections
The ConcurrentMap interface includes all the methods framework provides a thread-safe map. That is,
of the Map interface. It is because Map is the super multiple threads can access the map at once without
interface of the ConcurrentMap interface. affecting the consistency of entries in a map.
Besides all those methods, here are the methods It implements the ConcurrentMap interface.
specific to the ConcurrentMap interface.
putIfAbsent() - Inserts the specified key/value to the
map if the specified key is not already associated with Create a ConcurrentHashMap
any value. In order to create a concurrent hashmap, we must
compute() - Computes an entry (key/value mapping) import
for the specified key and its previously mapped value. the java.util.concurrent.ConcurrentHashMap package
computeIfAbsent() - Computes a value using the first. Once we import the package, here is how we can
specified function for the specified key if the key is not create concurrent hashmaps in Java.
already mapped with any value.
computeIfPresent() - Computes a new entry // ConcurrentHashMap with capacity 8 and load
(key/value mapping) for the specified key if the key is factor 0.6
already mapped with the specified value. ConcurrentHashMap<Key, Value> numbers = new
forEach() - Access all entries of a map and perform the ConcurrentHashMap<>(8, 0.6f);
specified actions.
In the above code, we have created a concurrent Insert Elements to ConcurrentHashMap
hashmap named numbers. put() - inserts the specified key/value mapping to the
Here, map
Key - a unique identifier used to associate each putAll() - inserts all the entries from specified map to
element (value) in a map this map
Value - elements associated by keys in a map putIfAbsent() - inserts the specified key/value
Notice the part new ConcurrentHashMap<>(8, 0.6). mapping to the map if the specified key is not present
Here, the first parameter is capacity and the second in the map
parameter is loadFactor. For example,
capacity - The capacity of this map is 8. Meaning, it import java.util.concurrent.ConcurrentHashMap;
can store 8 entries.
loadFactor - The load factor of this map is 0.6. This class Main {
means, whenever our hash table is filled by 60%, the public static void main(String[] args) {
entries are moved to a new hash table of double the // Creating ConcurrentHashMap of even
size of the original hash table. numbers
Default capacity and load factor ConcurrentHashMap<String, Integer>
It's possible to create a concurrent hashmap without evenNumbers = new ConcurrentHashMap<>();
defining its capacity and load factor. For example,
// Using put()
// ConcurrentHashMap with default capacity and evenNumbers.put("Two", 2);
load factor evenNumbers.put("Four", 4);
ConcurrentHashMap<Key, Value> numbers1 = new
ConcurrentHashMap<>(); // Using putIfAbsent()
evenNumbers.putIfAbsent("Six", 6);
By default, System.out.println("ConcurrentHashMap of even
the capacity of the map will be 16 numbers: " + evenNumbers);
the load factor will be 0.75
//Creating ConcurrentHashMap of numbers
Creating ConcurrentHashMap from Other Maps ConcurrentHashMap<String, Integer> numbers
Here is how we can create a concurrent hashmap = new ConcurrentHashMap<>();
containing all the elements of other maps. numbers.put("One", 1);
import java.util.concurrent.ConcurrentHashMap;
import java.util.HashMap; // Using putAll()
numbers.putAll(evenNumbers);
class Main { System.out.println("ConcurrentHashMap of
public static void main(String[] args) { numbers: " + numbers);
}
// Creating a hashmap of even numbers }
HashMap<String, Integer> evenNumbers = new
HashMap<>(); Output
evenNumbers.put("Two", 2); ConcurrentHashMap of even numbers: {Six=6,
evenNumbers.put("Four", 4); Four=4, Two=2}
System.out.println("HashMap: " + ConcurrentHashMap of numbers: {Six=6, One=1,
evenNumbers); Four=-4, Two=2}

// Creating a concurrent hashmap from other Access ConcurrentHashMap Elements


map 1. Using entrySet(), keySet() and values()
ConcurrentHashMap<String, Integer> numbers entrySet() - returns a set of all the key/value mapping
= new ConcurrentHashMap<>(evenNumbers); of the map
numbers.put("Three", 3); keySet() - returns a set of all the keys of the map
System.out.println("ConcurrentHashMap: " + values() - returns a set of all the values of the map
numbers); For example,
} import java.util.concurrent.ConcurrentHashMap;
}
class Main {
Output public static void main(String[] args) {
HashMap: {Four=4, Two=2} ConcurrentHashMap<String, Integer> numbers
ConcurrentHashMap: {Four=4, Two=2, Three=3} = new ConcurrentHashMap<>();

numbers.put("One", 1);
Methods of ConcurrentHashMap numbers.put("Two", 2);
The ConcurrentHashMap class provides methods that numbers.put("Three", 3);
allow us to perform various operations on the map. System.out.println("ConcurrentHashMap: " +
numbers);
// Using entrySet() class Main {
System.out.println("Key/Value mappings: " + public static void main(String[] args) {
numbers.entrySet());
ConcurrentHashMap<String, Integer> numbers
// Using keySet() = new ConcurrentHashMap<>();
System.out.println("Keys: " + numbers.keySet()); numbers.put("One", 1);
numbers.put("Two", 2);
// Using values() numbers.put("Three", 3);
System.out.println("Values: " + System.out.println("ConcurrentHashMap: " +
numbers.values()); numbers);
}
} // remove method with single parameter
int value = numbers.remove("Two");
Output System.out.println("Removed value: " + value);
ConcurrentHashMap: {One=1, Two=2, Three=3}
Key/Value mappings: [One=1, Two=2, Three=3] // remove method with two parameters
Keys: [One, Two, Three] boolean result = numbers.remove("Three", 3);
Values: [1, 2, 3] System.out.println("Is the entry {Three=3}
removed? " + result);
2. Using get() and getOrDefault()
get() - Returns the value associated with the specified System.out.println("Updated
key. Returns null if the key is not found. ConcurrentHashMap: " + numbers);
getOrDefault() - Returns the value associated with the }
specified key. Returns the specified default value if the }
key is not found.
For example, Output
import java.util.concurrent.ConcurrentHashMap; ConcurrentHashMap: {One=1, Two=2, Three=3}
Removed value: 2
class Main { Is the entry {Three=3} removed? True
public static void main(String[] args) { Updated ConcurrentHashMap: {One=1}

ConcurrentHashMap<String, Integer> numbers Bulk ConcurrentHashMap Operations


= new ConcurrentHashMap<>(); The ConcurrentHashMap class provides different bulk
numbers.put("One", 1); operations that can be applied safely to concurrent
numbers.put("Two", 2); maps.
numbers.put("Three", 3); 1. forEach() Method
System.out.println("ConcurrentHashMap: " + The forEach() method iterates over our entries and
numbers); executes the specified function.
It includes two parameters.
// Using get() parallelismThreshold - It specifies that after how many
int value1 = numbers.get("Three"); elements operations in a map are executed in parallel.
System.out.println("Using get(): " + value1); transformer - This will transform the data before the
data is passed to the specified function.
// Using getOrDefault() For example,
int value2 = numbers.getOrDefault("Five", 5); import java.util.concurrent.ConcurrentHashMap;
System.out.println("Using getOrDefault(): " +
value2); class Main {
} public static void main(String[] args) {
}
ConcurrentHashMap<String, Integer> numbers
Output = new ConcurrentHashMap<>();
ConcurrentHashMap: {One=1, Two=2, Three=3} numbers.put("One", 1);
Using get(): 3 numbers.put("Two", 2);
Using getOrDefault(): 5 numbers.put("Three", 3);
System.out.println("ConcurrentHashMap: " +
Remove ConcurrentHashMap Elements numbers);
remove(key) - returns and removes the entry
associated with the specified key from the map // forEach() without transformer function
remove(key, value) - removes the entry from the map numbers.forEach(4, (k, v) ->
only if the specified key mapped to the specified value System.out.println("key: " + k + " value: " + v));
and return a boolean value
For example, // forEach() with transformer function
import java.util.concurrent.ConcurrentHashMap; System.out.print("Values are ");
numbers.forEach(4, (k, v) -> v, (v) ->
System.out.print(v + ", ")); 3. reduce() Method
} The reduce() method accumulates (gather together)
} each entry in a map. This can be used when we need
all the entries to perform a common task, like adding
Output all the values of a map.
ConcurrentHashMap: {One = 1, Two = 2, Three = 3} It includes two parameters.
key: One value: 1 parallelismThreshold - It specifies that after how many
key: Two value: 2 elements, operations in a map are executed in parallel.
key: Three value: 3 transformer - This will transform the data before the
Values are 1, 2, 3, data is passed to the specified function.
In the above program, we have used parallel For example,
threshold 4. This means if the map contains 4 entries, import java.util.concurrent.ConcurrentHashMap;
the operation will be executed in parallel.
Variation of forEach() Method class Main {
forEachEntry() - executes the specified function for public static void main(String[] args) {
each entry
forEachKey() - executes the specified function for each ConcurrentHashMap<String, Integer> numbers
key = new ConcurrentHashMap<>();
forEachValue() - executes the specified function for numbers.put("One", 1);
each value numbers.put("Two", 2);
numbers.put("Three", 3);
2. search() Method System.out.println("ConcurrentHashMap: " +
The search() method searches the map based on the numbers);
specified function and returns the matched entry.
Here, the specified function determines what entry is // Using search()
to be searched. int sum = numbers.reduce(4, (k, v) -> v, (v1, v2) -
It also includes an optional > v1 + v2);
parameter parallelThreshold. The parallel threshold System.out.println("Sum of all values: " + sum);
specifies that after how many elements in the map the
operation is executed in parallel. }
For example, }
import java.util.concurrent.ConcurrentHashMap; Output
ConcurrentHashMap: {One=1, Two=2, Three=3}
class Main { Sum of all values: 6
public static void main(String[] args) {
In the above program, notice the statement
ConcurrentHashMap<String, Integer> numbers
= new ConcurrentHashMap<>(); numbers.reduce(4, (k, v) -> v, (v1, v2) -> v1+v2);
numbers.put("One", 1);
numbers.put("Two", 2); Here,
numbers.put("Three", 3); 4 is a parallel threshold
System.out.println("ConcurrentHashMap: " + (k, v) -> v is a transformer function. It transfers the
numbers); key/value mappings into values only.
(v1, v2) -> v1+v2 is a reducer function. It gathers
// Using search() together all the values and adds all values.
String key = numbers.search(4, (k, v) -> {return v Variants of reduce() Method
== 3 ? k: null;}); reduceEntries() - returns the result of gathering all the
System.out.println("Searched value: " + key); entries using the specified reducer function
reduceKeys() - returns the result of gathering all the
} keys using the specified reducer function
} reduceValues() - returns the result of gathering all the
values using the specified reducer function
Output
ConcurrentHashMap: {One=1, Two=2, Three=3} ConcurrentHashMap vs HashMap
Searched value: Three Here are some of the differences
between ConcurrentHashMap and HashMap,
Variants of search() Method ConcurrentHashMap is a thread-safe collection. That
searchEntries() - search function is applied to is, multiple threads can access and modify it at the
key/value mappings same time.
searchKeys() - search function is only applied to the ConcurrentHashMap provides methods for bulk
keys operations like forEach(), search() and reduce().
searchValues() - search function is only applied to the
values
Why ConcurrentHashMap? Methods of Set
The ConcurrentHashMap class allows multiple The Set interface includes all the methods of
threads to access its entries concurrently. the Collection interface. It's because Collection is a
By default, the concurrent hashmap is divided into 16 super interface of Set.
segments. This is the reason why 16 threads are Some of the commonly used methods of
allowed to concurrently modify the map at the same the Collection interface that's also available in
time. However, any number of threads can access the the Set interface are:
map at a time. add() - adds the specified element to the set
The putIfAbsent() method will not override the entry addAll() - adds all the elements of the specified
in the map if the specified key already exists. collection to the set
It provides its own synchronization. iterator() - returns an iterator that can be used to access
elements of the set sequentially
remove() - removes the specified element from the set
removeAll() - removes all the elements from the set
that is present in another specified set
Java Set retainAll() - retains all the elements in the set that are
also present in another specified set
clear() - removes all the elements from the set
size() - returns the length (number of elements) of the
Java Set Interface set
The Set interface of the Java Collections toArray() - returns an array containing all the elements
framework provides the features of the mathematical of the set
set in Java. It extends the Collection interface. contains() - returns true if the set contains the specified
Unlike the List interface, sets cannot contain duplicate element
elements. containsAll() - returns true if the set contains all the
elements of the specified collection
Classes that implement Set hashCode() - returns a hash code value (address of the
Since Set is an interface, we cannot create objects from element in the set)
it.
In order to use functionalities of the Set interface, we Set Operations
can use these classes: The Java Set interface allows us to perform basic
HashSet mathematical set operations like union, intersection,
LinkedHashSet and subset.
EnumSet Union - to get the union of two sets x and y, we can
TreeSet use x.addAll(y)
These classes are defined in the Collections framework Intersection - to get the intersection of two
and implement the Set interface. sets x and y, we can use x.retainAll(y)
Subset - to check if x is a subset of y, we can
Interfaces that extend Set use y.containsAll(x)
The Set interface is also extended by these
subinterfaces: Implementation of the Set Interface
SortedSet 1. Implementing HashSet Class
NavigableSet import java.util.Set;
import java.util.HashSet;

class Main {

public static void main(String[] args) {


// Creating a set using the HashSet class
Set<Integer> set1 = new HashSet<>();

// Add elements to the set1


set1.add(2);
set1.add(3);
How to use Set? System.out.println("Set1: " + set1);
In Java, we must import java.util.Set package in order
to use Set. // Creating another set using the HashSet class
Set<Integer> set2 = new HashSet<>();
// Set implementation using HashSet
Set<String> animals = new HashSet<>(); // Add elements
set2.add(1);
Here, we have created a Set called animals. We have set2.add(2);
used the HashSet class to implement the Set interface. System.out.println("Set2: " + set2);
// Union of two sets Creating a HashSet
set2.addAll(set1); In order to create a hash set, we must import
System.out.println("Union is: " + set2); the java.util.HashSet package first.
} Once we import the package, here is how we can
} create hash sets in Java.

Output // HashSet with 8 capacity and 0.75 load factor


Set1: [2, 3] HashSet<Integer> numbers = new HashSet<>(8,
Set2: [1, 2] 0.75);
Union is: [1, 2, 3]
Here, we have created a hash set named numbers.
2. Implementing TreeSet Class Notice, the part new HashSet<>(8, 0.75). Here, the
import java.util.Set; first parameter is capacity, and the second parameter
import java.util.TreeSet; is loadFactor.
import java.util.Iterator; capacity - The capacity of this hash set is 8. Meaning,
it can store 8 elements.
class Main {  loadFactor - The load factor of this hash set is 0.6.
This means, whenever our hash set is filled by 60%,
public static void main(String[] args) { the elements are moved to a new hash table of double
// Creating a set using the TreeSet class the size of the original hash table.
Set<Integer> numbers = new TreeSet<>(); Default capacity and load factor
It's possible to create a hash table without defining its
// Add elements to the set capacity and load factor. For example,
numbers.add(2);
numbers.add(3); // HashSet with default capacity and load factor
numbers.add(1); HashSet<Integer> numbers1 = new HashSet<>();
System.out.println("Set using TreeSet: " +
numbers); By default,
the capacity of the hash set will be 16
// Access Elements using iterator() the load factor will be 0.75
System.out.print("Accessing elements using
iterator(): "); Methods of HashSet
Iterator<Integer> iterate = numbers.iterator(); The HashSet class provides various methods that
while(iterate.hasNext()) { allow us to perform various operations on the set.
System.out.print(iterate.next());
System.out.print(", "); Insert Elements to HashSet
} add() - inserts the specified element to the set
addAll() - inserts all the elements of the specified
} collection to the set
} For example,

Output import java.util.HashSet;


Set using TreeSet: [1, 2, 3]
Accessing elements using iterator(): 1, 2, 3, class Main {
public static void main(String[] args) {
HashSet<Integer> evenNumber = new
Java HashSet Class HashSet<>();
The HashSet class of the Java Collections framework
provides the functionalities of the hash table data // Using add() method
structure. evenNumber.add(2);
It implements the Set interface. evenNumber.add(4);
evenNumber.add(6);
System.out.println("HashSet: " + evenNumber);

HashSet<Integer> numbers = new HashSet<>();

// Using addAll() method


numbers.addAll(evenNumber);
numbers.add(5);
System.out.println("New HashSet: " + numbers);
}
}

Output
HashSet: [2, 4, 6]
New HashSet: [2, 4, 5, 6] Set Operations
The various methods of the HashSet class can also be
Access HashSet Elements used to perform various set operations.
To access the elements of a hash set, we can use
the iterator() method. In order to use this method, we Union of Sets
must import the java.util.Iterator package. For To perform the union between two sets, we can use
example, the addAll() method. For example,

import java.util.HashSet; import java.util.HashSet;


import java.util.Iterator;
class Main {
class Main { public static void main(String[] args) {
public static void main(String[] args) { HashSet<Integer> evenNumbers = new
HashSet<Integer> numbers = new HashSet<>(); HashSet<>();
numbers.add(2); evenNumbers.add(2);
numbers.add(5); evenNumbers.add(4);
numbers.add(6); System.out.println("HashSet1: " +
System.out.println("HashSet: " + numbers); evenNumbers);

// Calling iterator() method HashSet<Integer> numbers = new HashSet<>();


Iterator<Integer> iterate = numbers.iterator(); numbers.add(1);
System.out.print("HashSet using Iterator: "); numbers.add(3);
// Accessing elements System.out.println("HashSet2: " + numbers);
while(iterate.hasNext()) {
System.out.print(iterate.next()); // Union of two set
System.out.print(", "); numbers.addAll(evenNumbers);
} System.out.println("Union is: " + numbers);
} }
} }

Output Output
HashSet: [2, 5, 6] HashSet1: [2, 4]
HashSet using Iterator: 2, 5, 6, HashSet2: [1, 3]
Union is: [1, 2, 3, 4]
Remove Elements
remove() - removes the specified element from the set Intersection of Sets
removeAll() - removes all the elements from the set To perform the intersection between two sets, we can
For example, use the retainAll() method. For example

import java.util.HashSet; import java.util.HashSet;

class Main { class Main {


public static void main(String[] args) { public static void main(String[] args) {
HashSet<Integer> numbers = new HashSet<>(); HashSet<Integer> primeNumbers = new
numbers.add(2); HashSet<>();
numbers.add(5); primeNumbers.add(2);
numbers.add(6); primeNumbers.add(3);
System.out.println("HashSet: " + numbers); System.out.println("HashSet1: " +
primeNumbers);
// Using remove() method
boolean value1 = numbers.remove(5); HashSet<Integer> evenNumbers = new
System.out.println("Is 5 removed? " + value1); HashSet<>();
evenNumbers.add(2);
boolean value2 = numbers.removeAll(numbers); evenNumbers.add(4);
System.out.println("Are all elements removed? " System.out.println("HashSet2: " +
+ value2); evenNumbers);
}
} // Intersection of two sets
evenNumbers.retainAll(primeNumbers);
Output System.out.println("Intersection is: " +
HashSet: [2, 5, 6] evenNumbers);
Is 5 removed? true }
Are all elements removed? True }
boolean result =
Output numbers.containsAll(primeNumbers);
HashSet1: [2, 3] System.out.println("Is HashSet2 is subset of
HashSet2: [2, 4] HashSet1? " + result);
Intersection is: [2] }
}
Difference of Sets
To calculate the difference between the two sets, we Output
can use the removeAll() method. For example, HashSet1: [1, 2, 3, 4]
HashSet2: [2, 3]
import java.util.HashSet; Is HashSet2 is a subset of HashSet1? true

class Main { Other Methods Of HashSet


public static void main(String[] args) { Method Description
HashSet<Integer> primeNumbers = new clone() Creates a copy of the
HashSet<>(); HashSet
primeNumbers.add(2); contains() Searches the HashSet for
primeNumbers.add(3); the specified element and
primeNumbers.add(5); returns a boolean result
System.out.println("HashSet1: " + isEmpty() Checks if the HashSet is
primeNumbers); empty
size() Returns the size of the
HashSet<Integer> oddNumbers = new HashSet
HashSet<>(); clear() Removes all the elements
oddNumbers.add(1); from the HashSet
oddNumbers.add(3);
oddNumbers.add(5); Why HashSet?
System.out.println("HashSet2: " + oddNumbers); In Java, HashSet is commonly used if we have to
access elements randomly. It is because elements in a
// Difference between HashSet1 and HashSet2 hash table are accessed using hash codes.
primeNumbers.removeAll(oddNumbers); The hashcode of an element is a unique identity that
System.out.println("Difference : " + helps to identify the element in a hash table.
primeNumbers); HashSet cannot contain duplicate elements. Hence,
} each hash set element has a unique hashcode.
}
Note: HashSet is not synchronized. That is if multiple
Output threads access the hash set at the same time and one of
HashSet1: [2, 3, 5] the threads modifies the hash set. Then it must be
HashSet2: [1, 3, 5] externally synchronized.
Difference: [2]

Subset
Java EnumSet
To check if a set is a subset of another set or not, we The EnumSet class of the Java collections
can use the containsAll() method. For example, framework provides a set implementation of elements
import java.util.HashSet; of a single enum.
Before you learn about EnumSet, make sure to know
class Main { about Java Enums.
public static void main(String[] args) { It implements the Set interface.
HashSet<Integer> numbers = new HashSet<>();
numbers.add(1);
numbers.add(2);
numbers.add(3);
numbers.add(4);
System.out.println("HashSet1: " + numbers);

HashSet<Integer> primeNumbers = new


HashSet<>();
primeNumbers.add(2);
primeNumbers.add(3);
System.out.println("HashSet2: " +
primeNumbers);

// Check if primeNumbers is a subset of numbers


Creating EnumSet Empty EnumSet : []
In order to create an enum set, we must import
the java.util.EnumSet package first. Here, we have created an empty enum named sizes.
Unlike other set implementations, the enum set does Note: We can only insert elements of enum
not have public constructors. We must use the type Size in the above program. It's because we
predefined methods to create an enum set. created our empty enum set using Size enum.
1. Using allOf(Size)
The allof() method creates an enum set that contains 3. Using range(e1, e2) Method
all the values of the specified enum type Size. For The range() method creates an enum set containing all
example, the values of an enum between e1 and e2 including
both values. For example,
import java.util.EnumSet;
import java.util.EnumSet;
class Main {
// an enum named Size class Main {
enum Size {
SMALL, MEDIUM, LARGE, EXTRALARGE enum Size {
} SMALL, MEDIUM, LARGE, EXTRALARGE
}
public static void main(String[] args) {
public static void main(String[] args) {
// Creating an EnumSet using allOf()
EnumSet<Size> sizes = // Creating an EnumSet using range()
EnumSet.allOf(Size.class); EnumSet<Size> sizes =
EnumSet.range(Size.MEDIUM,
System.out.println("EnumSet: " + sizes); Size.EXTRALARGE);
}
System.out.println("EnumSet: " + sizes);
} }
}
Output
EnumSet: [SMALL, MEDIUM, LARGE, Output
EXTRALARGE] EnumSet: [MEDIUM, LARGE, EXTRALARGE]

Notice the statement, 4. Using of() Method


EnumSet<Size> sizes = EnumSet.allOf(Size.class); The of() method creates an enum set containing the
specified elements. For example,
Here, Size.class denotes the Size enum that we have
created. import java.util.EnumSet;

2. Using noneOf(Size) class Main {


The noneOf() method creates an empty enum set. For
example, enum Size {
SMALL, MEDIUM, LARGE, EXTRALARGE
import java.util.EnumSet; }

class Main { public static void main(String[] args) {

// an enum type Size // Using of() with a single parameter


enum Size { EnumSet<Size> sizes1 =
SMALL, MEDIUM, LARGE, EXTRALARGE EnumSet.of(Size.MEDIUM);
} System.out.println("EnumSet1: " + sizes1);

public static void main(String[] args) { EnumSet<Size> sizes2 =


EnumSet.of(Size.SMALL, Size.LARGE);
// Creating an EnumSet using noneOf() System.out.println("EnumSet2: " + sizes2);
EnumSet<Size> sizes = }
EnumSet.noneOf(Size.class); }

System.out.println("Empty EnumSet: " + sizes);


} Output
} EnumSet1: [MEDIUM]
EnumSet2: [SMALL, LARGE]
Output
Methods of EnumSet class Main {
The EnumSet class provides methods that allow us to
perform various elements on the enum set. enum Size {
SMALL, MEDIUM, LARGE, EXTRALARGE
Insert Elements to EnumSet }
add() - inserts specified enum values to the enum set
addAll() inserts all the elements of the specified public static void main(String[] args) {
collection to the set
For example, // Creating an EnumSet using allOf()
EnumSet<Size> sizes =
import java.util.EnumSet; EnumSet.allOf(Size.class);

class Main { Iterator<Size> iterate = sizes.iterator();

enum Size { System.out.print("EnumSet: ");


SMALL, MEDIUM, LARGE, EXTRALARGE while(iterate.hasNext()) {
} System.out.print(iterate.next());
System.out.print(", ");
public static void main(String[] args) { }
}
// Creating an EnumSet using allOf() }
EnumSet<Size> sizes1 =
EnumSet.allOf(Size.class); Output
EnumSet: SMALL, MEDIUM, LARGE,
// Creating an EnumSet using noneOf() EXTRALARGE,
EnumSet<Size> sizes2 =
EnumSet.noneOf(Size.class); Note:
hasNext() returns true if there is a next element in the
// Using add method enum set
sizes2.add(Size.MEDIUM); next() returns the next element in the enum set
System.out.println("EnumSet Using add(): " +
sizes2); Remove EnumSet Elements
remove() - removes the specified element from the
// Using addAll() method enum set
sizes2.addAll(sizes1); removeAll() - removes all the elements from the enum
System.out.println("EnumSet Using addAll(): " + set
sizes2); For example,
}
} import java.util.EnumSet;

Output class Main {


EnumSet using add(): [MEDIUM]
EnumSet using addAll(): [SMALL, MEDIUM, enum Size {
LARGE, EXTRALARGE] SMALL, MEDIUM, LARGE, EXTRALARGE
}
In the above example, we have used
the addAll() method to insert all the elements of an public static void main(String[] args) {
enum set sizes1 to an enum set sizes2 .
// Creating EnumSet using allOf()
It's also possible to insert elements from other
EnumSet<Size> sizes =
collections such as ArrayList , LinkedList , etc. to an EnumSet.allOf(Size.class);
enum set using addAll() . However, all collections System.out.println("EnumSet: " + sizes);
should be of the same enum type.
// Using remove()
Access EnumSet Elements boolean value1 = sizes.remove(Size.MEDIUM);
To access elements of an enum set, we can use System.out.println("Is MEDIUM removed? " +
the iterator() method. In order to use this method, we value1);
must import the java.util.Iterator package. For
// Using removeAll()
example,
boolean value2 = sizes.removeAll(sizes);
import java.util.EnumSet; System.out.println("Are all elements removed? "
import java.util.Iterator; + value2);
}
}
Java LinkedHashSet
Output
EnumSet: [SMALL, MEDIUM, LARGE, The LinkedHashSet class of the Java collections
EXTRALARGE] framework provides functionalities of both
Is MEDIUM removed? true the hashtable and the linked list data structure.
Are all elements removed? true It implements the Set interface.

Other Methods
Method Description
copyOf() Creates a copy of the
EnumSet
contains() Searches the EnumSet for
the specified element and
returns a boolean result
isEmpty() Checks if the EnumSet is
empty
size() Returns the size of the
EnumSet
clear() Removes all the elements
from the EnumSet

Clonable and Serializable Interfaces Elements of LinkedHashSet are stored in hash tables
The EnumSet class also similar to HashSet.
implements Cloneable and Serializable interfaces. However, linked hash sets maintain a doubly-linked
Cloneable Interface list internally for all of its elements. The linked list
It allows the EnumSet class to make a copy of defines the order in which elements are inserted in
instances of the class. hash tables.
Serializable Interface
Whenever Java objects need to be transmitted over a Create a LinkedHashSet
network, objects need to be converted into bits or In order to create a linked hash set, we must import
bytes. This is because Java objects cannot be the java.util.LinkedHashSet package first.
transmitted over the network. Once we import the package, here is how we can
The Serializable interface allows classes to be create linked hash sets in Java.
serialized. This means objects of the classes
implementing Serializable can be converted into bits // LinkedHashSet with 8 capacity and 0.75 load
or bytes. factor
LinkedHashSet<Integer> numbers = new
LinkedHashSet<>(8, 0.75);
Why EnumSet?
The EnumSet provides an efficient way to store enum
Here, we have created a linked hash set
values than other set implementations
named numbers.
(like HashSet, TreeSet).
Notice, the part new LinkedHashSet<>(8, 0.75). Here,
An enum set only stores enum values of a specific
the first parameter is capacity and the second
enum. Hence, the JVM already knows all the possible
parameter is loadFactor.
values of the set.
capacity - The capacity of this hash set is 8. Meaning,
This is the reason why enum sets are internally
it can store 8 elements.
implemented as a sequence of bits. Bits specifies
loadFactor - The load factor of this hash set is 0.6.
whether elements are present in the enum set or not.
This means, whenever our hash table is filled by 60%,
The bit of a corresponding element is turned on if that
the elements are moved to a new hash table of double
element is present in the set.
the size of the original hash table.

Default capacity and load factor


It's possible to create a linked hash set without
defining its capacity and load factor. For example,

// LinkedHashSet with default capacity and load


factor
LinkedHashSet<Integer> numbers1 = new
LinkedHashSet<>();

By default,
the capacity of the linked hash set will be 16
the load factor will be 0.75
}
Creating LinkedHashSet from Other Collections }
Here is how we can create a linked hash set containing
all the elements of other collections. Output
LinkedHashSet: [2, 4, 6]
import java.util.LinkedHashSet; New LinkedHashSet: [2, 4, 6, 5]
import java.util.ArrayList;
Access LinkedHashSet Elements
class Main { To access the elements of a linked hash set, we can use
public static void main(String[] args) { the iterator()method. In order to use this method, we
// Creating an arrayList of even numbers must import the java.util.Iterator package. For
ArrayList<Integer> evenNumbers = new example,
ArrayList<>();
evenNumbers.add(2); import java.util.LinkedHashSet;
evenNumbers.add(4); import java.util.Iterator;
System.out.println("ArrayList: " +
evenNumbers); class Main {
public static void main(String[] args) {
// Creating a LinkedHashSet from an ArrayList LinkedHashSet<Integer> numbers = new
LinkedHashSet<Integer> numbers = new LinkedHashSet<>();
LinkedHashSet<>(evenNumbers); numbers.add(2);
System.out.println("LinkedHashSet: " + numbers.add(5);
numbers); numbers.add(6);
} System.out.println("LinkedHashSet: " +
} numbers);

Output // Calling the iterator() method


ArrayList: [2, 4] Iterator<Integer> iterate = numbers.iterator();
LinkedHashSet: [2, 4]
System.out.print("LinkedHashSet using Iterator:
Methods of LinkedHashSet ");
The LinkedHashSet class provides methods that allow
us to perform various operations on the linked hash // Accessing elements
set. while(iterate.hasNext()) {
System.out.print(iterate.next());
Insert Elements to LinkedHashSet System.out.print(", ");
add() - inserts the specified element to the linked hash }
set }
addAll() - inserts all the elements of the specified }
collection to the linked hash set
For example, Output
LinkedHashSet: [2, 5, 6]
import java.util.LinkedHashSet; LinkedHashSet using Iterator: 2, 5, 6,

class Main { Note:


public static void main(String[] args) { hasNext() returns true if there is a next element in the
LinkedHashSet<Integer> evenNumber = new linked hash set
LinkedHashSet<>(); next() returns the next element in the linked hash set

// Using add() method Remove Elements from HashSet


evenNumber.add(2); remove() - removes the specified element from the
evenNumber.add(4); linked hash set
evenNumber.add(6); removeAll() - removes all the elements from the linked
System.out.println("LinkedHashSet: " + hash set
evenNumber); For example,

LinkedHashSet<Integer> numbers = new import java.util.LinkedHashSet;


LinkedHashSet<>();
class Main {
// Using addAll() method public static void main(String[] args) {
numbers.addAll(evenNumber); LinkedHashSet<Integer> numbers = new
numbers.add(5); LinkedHashSet<>();
System.out.println("New LinkedHashSet: " + numbers.add(2);
numbers); numbers.add(5);
numbers.add(6); LinkedHashSet<Integer> primeNumbers = new
System.out.println("LinkedHashSet: " + LinkedHashSet<>();
numbers); primeNumbers.add(2);
primeNumbers.add(3);
// Using the remove() method System.out.println("LinkedHashSet1: " +
boolean value1 = numbers.remove(5); primeNumbers);
System.out.println("Is 5 removed? " + value1);
LinkedHashSet<Integer> evenNumbers = new
boolean value2 = numbers.removeAll(numbers); LinkedHashSet<>();
System.out.println("Are all elements removed? " evenNumbers.add(2);
+ value2); evenNumbers.add(4);
} System.out.println("LinkedHashSet2: " +
} evenNumbers);

Output // Intersection of two sets


LinkedHashSet: [2, 5, 6] evenNumbers.retainAll(primeNumbers);
Is 5 removed? true System.out.println("Intersection is: " +
Are all elements removed? True evenNumbers);
}
Set Operations }
The various methods of the LinkedHashSet class can
also be used to perform various set operations. Output
LinkedHashSet1: [2, 3]
Union of Sets LinkedHashSet2: [2, 4]
Two perform the union between two sets, we can use Intersection is: [2]
the addAll() method. For example,
Difference of Sets
import java.util.LinkedHashSet; To calculate the difference between the two sets, we
can use the removeAll() method. For example,
class Main {
public static void main(String[] args) { import java.util.LinkedHashSet;
LinkedHashSet<Integer> evenNumbers = new
LinkedHashSet<>(); class Main {
evenNumbers.add(2); public static void main(String[] args) {
evenNumbers.add(4); LinkedHashSet<Integer> primeNumbers = new
System.out.println("LinkedHashSet1: " + LinkedHashSet<>();
evenNumbers); primeNumbers.add(2);
primeNumbers.add(3);
LinkedHashSet<Integer> numbers = new primeNumbers.add(5);
LinkedHashSet<>(); System.out.println("LinkedHashSet1: " +
numbers.add(1); primeNumbers);
numbers.add(3);
System.out.println("LinkedHashSet2: " + LinkedHashSet<Integer> oddNumbers = new
numbers); LinkedHashSet<>();
oddNumbers.add(1);
// Union of two set oddNumbers.add(3);
numbers.addAll(evenNumbers); oddNumbers.add(5);
System.out.println("Union is: " + numbers); System.out.println("LinkedHashSet2: " +
} oddNumbers);
}
// Difference between LinkedHashSet1 and
Output LinkedHashSet2
LinkedHashSet1: [2, 4] primeNumbers.removeAll(oddNumbers);
LinkedHashSet2: [1, 3] System.out.println("Difference : " +
Union is: [1, 3, 2, 4] primeNumbers);
}
Intersection of Sets }
To perform the intersection between two sets, we can
use the retainAll() method. For example Output
LinkedHashSet1: [2, 3, 5]
import java.util.LinkedHashSet; LinkedHashSet2: [1, 3, 5]
Difference: [2]
class Main {
public static void main(String[] args) {
Subset because LinkedHashSet maintains linked lists
To check if a set is a subset of another set or not, we internally.
can use the containsAll() method. For example, The performance of LinkedHashSet is slower
than HashSet. It is because of linked lists present
import java.util.LinkedHashSet; in LinkedHashSet.

class Main {
public static void main(String[] args) { LinkedHashSet Vs. TreeSet
LinkedHashSet<Integer> numbers = new Here are the major differences
LinkedHashSet<>(); between LinkedHashSet and TreeSet:
numbers.add(1); The TreeSet class implements the SortedSet interface.
numbers.add(2); That's why elements in a tree set are sorted. However,
numbers.add(3); the LinkedHashSet class only maintains the insertion
numbers.add(4); order of its elements.
System.out.println("LinkedHashSet1: " + A TreeSet is usually slower than a LinkedHashSet. It
numbers); is because whenever an element is added to a TreeSet,
it has to perform the sorting operation.
LinkedHashSet<Integer> primeNumbers = new LinkedHashSet allows the insertion of null values.
LinkedHashSet<>(); However, we cannot insert a null value to TreeSet.
primeNumbers.add(2);
primeNumbers.add(3);
System.out.println("LinkedHashSet2: " +
primeNumbers); Java SortedSet Interface

// Check if primeNumbers is a subset of numbers The SortedSet interface of the Java collections
boolean result = framework is used to store elements with some order
numbers.containsAll(primeNumbers); in a set.
System.out.println("Is LinkedHashSet2 is subset It extends the Set interface.
of LinkedHashSet1? " + result);
}
}

Output
LinkedHashSet1: [1, 2, 3, 4]
LinkedHashSet2: [2, 3]
Is LinkedHashSet2 is a subset of LinkedHashSet1?
True

Other Methods Of LinkedHashSet

Method Description
clone() Creates a copy of the
LinkedHashSet
contains() Searches the
LinkedHashSet for the Class that implements SortedSet
specified element and In order to use the functionalities of
returns a boolean result the SortedSet interface, we need to use
isEmpty() Checks if the the TreeSet class that implements it.
LinkedHashSet is empty
size() Returns the size of the
LinkedHashSet
clear() Removes all the elements
from the LinkedHashSet

LinkedHashSet Vs. HashSet


Both LinkedHashSet and HashSet implements
the Set interface. However, there exist some
differences between them.
LinkedHashSet maintains a linked list internally. Due
to this, it maintains the insertion order of its elements.
The LinkedHashSet class requires more storage
than HashSet. This is
}
How to use SortedSet?
To use SortedSet, we must import Output
the java.util.SortedSet package first. SortedSet: [1, 2, 3, 4]
First Number: 1
// SortedSet implementation by TreeSet class Last Number: 4
SortedSet<String> animals = new TreeSet<>(); Is the number 2 removed? True

We have created a sorted set called animals using


the TreeSet class. Java NavigableSet Interface
The NavigableSet interface of the Java Collections
Here we have used no arguments to create a sorted set.
framework provides the features to navigate among
Hence the set will be sorted naturally.
the set elements.
Methods of SortedSet It is considered as a type of SortedSet.
The SortedSet interface includes all the methods of the
Set interface. It's because Set is a super interface Class that implements NavigableSet
of SortedSet. In order to use the functionalities of
Besides methods included in the Set interface, the NavigableSet interface, we need to use
the SortedSet interface also includes these methods:
the TreeSet class that implements NavigableSet.
comparator() - returns a comparator that can be used
to order elements in the set
first() - returns the first element of the set How to use NavigableSet?
last() - returns the last element of the set In Java, we must import
headSet(element) - returns all the elements of the set the java.util.NavigableSet package to
before the specified element use NavigableSet. Once we import the package, here's
tailSet(element) - returns all the elements of the set how we can create navigable sets.
after the specified element including the specified
element
subSet(element1, element2) - returns all the elements // SortedSet implementation by TreeSet class
between NavigableSet<String> numbers = new TreeSet<>();
the element1 and element2 including element1
Here, we have created a navigable set
Implementation of SortedSet in TreeSet Class named numbers of the TreeSet class.
import java.util.SortedSet;
import java.util.TreeSet;
Methods of NavigableSet
class Main { The NavigableSet is considered as a type of SortedSet.
It is because NavigableSet extends
public static void main(String[] args) { the SortedSet interface.
// Creating SortedSet using the TreeSet Hence, all SortedSet methods are also available
SortedSet<Integer> numbers = new TreeSet<>(); in NavigableSet.
However, some of the methods
// Insert elements to the set
numbers.add(1); of SortedSet (headSet(), tailSet() and subSet()) are
numbers.add(2); defined differently in NavigableSet.
numbers.add(3); Let's see how these methods are defined
numbers.add(4); in NavigableSet.
System.out.println("SortedSet: " + numbers);
headSet(element, booleanValue)
// Access the element
The headSet() method returns all the elements of a
int firstNumber = numbers.first();
System.out.println("First Number: " + navigable set before the specified element (which is
firstNumber); passed as an argument).

int lastNumber = numbers.last(); The booleanValue parameter is optional. Its default


System.out.println("Last Number: " + value is false.
lastNumber); If true is passed as a booleanValue, the method returns
all the elements before the specified element including
// Remove elements
boolean result = numbers.remove(2); the specified element.
System.out.println("Is the number 2 removed? " +
result); tailSet(element, booleanValue)
}
The tailSet() method returns all the elements of a numbers.add(1);
navigable set after the specified element (which is numbers.add(2);
passed as an argument) including the specified numbers.add(3);
element. System.out.println("NavigableSet: " + numbers);
The booleanValue parameter is optional. Its default
value is true. // Access the first element
If false is passed as a booleanValue, the method int firstElement = numbers.first();
returns all the elements after the specified element System.out.println("First Number: " +
without including the specified element. firstElement);

subSet(e1, bv1, e2, bv2) // Access the last element


The subSet() method returns all the elements int lastElement = numbers.last();
between e1 and e2 including e1. System.out.println("Last Element: " +
The bv1 and bv2 are optional parameters. The default lastElement);
value of bv1 is true, and the default value
of bv2 is false. // Remove the first element
If false is passed as bv1, the method returns all the int number1 = numbers.pollFirst();
elements between e1 and e2 without including e1. System.out.println("Removed First Element: " +
If true is passed as bv2, the method returns all the number1);
elements between e1 and e2, including e1.
// Remove the last element
Methods for Navigation int number2 = numbers.pollLast();
The NavigableSet provides various methods that can System.out.println("Removed Last Element: " +
be used to navigate over its elements. number2);
descendingSet() - reverses the order of elements in a
set }
descendingIterator() - returns an iterator that can be }
used to iterate over a set in reverse order
ceiling() - returns the lowest element among those Output
elements that are greater than or equal to the specified NavigableSet: [1, 2, 3]
element First Element: 1
floor() - returns the greatest element among those Last Element: 3
elements that are less than or equal to the specified Removed First Element: 1
element Removed Last Element: 3
higher() - returns the lowest element among those
elements that are greater than the specified element
lower() - returns the greatest element among those Java TreeSet
elements that are less than the specified element
pollFirst() - returns and removes the first element from The TreeSet class of the Java collections
the set framework provides the functionality of a tree data
pollLast() - returns and removes the last element from structure.
the set It extends the NavigableSet interface.

Creating a TreeSet
Implementation of NavigableSet in TreeSet Class In order to create a tree set, we must import
import java.util.NavigableSet; the java.util.TreeSet package first.
import java.util.TreeSet; Once we import the package, here is how we can
create a TreeSet in Java.
class Main {
TreeSet<Integer> numbers = new TreeSet<>();
public static void main(String[] args) { Here, we have created a TreeSet without any
// Creating NavigableSet using the TreeSet arguments. In this case, the elements in TreeSet are
NavigableSet<Integer> numbers = new sorted naturally (ascending order).
TreeSet<>(); However, we can customize the sorting of elements by
using the Comparator interface. We will learn about it
// Insert elements to the set later in this tutorial.
Methods of TreeSet
The TreeSet class provides various methods that allow Output
us to perform various operations on the set. TreeSet: [2, 5, 6]
TreeSet using Iterator: 2, 5, 6,
Insert Elements to TreeSet
 add() - inserts the specified element to the set Remove Elements
 addAll() - inserts all the elements of the specified remove() - removes the specified element from the set
removeAll() - removes all the elements from the set
collection to the set
For example,
For example,
import java.util.TreeSet;
import java.util.TreeSet;
class Main {
class Main {
public static void main(String[] args) {
public static void main(String[] args) {
TreeSet<Integer> numbers = new TreeSet<>();
numbers.add(2);
TreeSet<Integer> evenNumbers = new
numbers.add(5);
TreeSet<>();
numbers.add(6);
System.out.println("TreeSet: " + numbers);
// Using the add() method
evenNumbers.add(2);
// Using the remove() method
evenNumbers.add(4);
boolean value1 = numbers.remove(5);
evenNumbers.add(6);
System.out.println("Is 5 removed? " + value1);
System.out.println("TreeSet: " + evenNumbers);
// Using the removeAll() method
TreeSet<Integer> numbers = new TreeSet<>();
boolean value2 = numbers.removeAll(numbers);
numbers.add(1);
System.out.println("Are all elements removed? "
+ value2);
// Using the addAll() method
}
numbers.addAll(evenNumbers);
}
System.out.println("New TreeSet: " + numbers);
}
Output
}
TreeSet: [2, 5, 6]
Is 5 removed? true
Output
Are all elements removed? True
TreeSet: [2, 4, 6]
New TreeSet: [1, 2, 4, 6]
Methods for Navigation
Since the TreeSet class implements NavigableSet, it
Access TreeSet Elements
provides various methods to navigate over the
To access the elements of a tree set, we can use
elements of the tree set.
the iterator() method. In order to use this method, we
must import java.util.Iterator package. For example,
1. first() and last() Methods
first() - returns the first element of the set
import java.util.TreeSet;
last() - returns the last element of the set
import java.util.Iterator;
For example,
class Main {
import java.util.TreeSet;
public static void main(String[] args) {
TreeSet<Integer> numbers = new TreeSet<>();
class Main {
numbers.add(2);
public static void main(String[] args) {
numbers.add(5);
TreeSet<Integer> numbers = new TreeSet<>();
numbers.add(6);
numbers.add(2);
System.out.println("TreeSet: " + numbers);
numbers.add(5);
numbers.add(6);
// Calling iterator() method
System.out.println("TreeSet: " + numbers);
Iterator<Integer> iterate = numbers.iterator();
System.out.print("TreeSet using Iterator: ");
// Using the first() method
// Accessing elements
int first = numbers.first();
while(iterate.hasNext()) {
System.out.println("First Number: " + first);
System.out.print(iterate.next());
System.out.print(", ");
// Using the last() method
}
int last = numbers.last();
}
System.out.println("Last Number: " + last);
}
}
} pollLast() - returns and removes the last element from
the set
Output For example,
TreeSet: [2, 5, 6]
First Number: 2 import java.util.TreeSet;
Last Number: 6
class Main {
2. ceiling(), floor(), higher() and lower() Methods public static void main(String[] args) {
higher(element) - Returns the lowest element among TreeSet<Integer> numbers = new TreeSet<>();
those elements that are greater than the numbers.add(2);
specified element. numbers.add(5);
lower(element) - Returns the greatest element among numbers.add(4);
those elements that are less than the specified element. numbers.add(6);
ceiling(element) - Returns the lowest element among System.out.println("TreeSet: " + numbers);
those elements that are greater than the
specified element. If the element passed exists in a tree // Using pollFirst()
set, it returns the element passed as an argument. System.out.println("Removed First Element: " +
floor(element) - Returns the greatest element among numbers.pollFirst());
those elements that are less than the specified element.
If the element passed exists in a tree set, it returns // Using pollLast()
the element passed as an argument. System.out.println("Removed Last Element: " +
For example, numbers.pollLast());

import java.util.TreeSet; System.out.println("New TreeSet: " + numbers);


}
class Main { }
public static void main(String[] args) {
TreeSet<Integer> numbers = new TreeSet<>(); Output
numbers.add(2); TreeSet: [2, 4, 5, 6]
numbers.add(5); Removed First Element: 2
numbers.add(4); Removed Last Element: 6
numbers.add(6); New TreeSet: [4, 5]
System.out.println("TreeSet: " + numbers);
4. headSet(), tailSet() and subSet() Methods
// Using higher() headSet(element, booleanValue)
System.out.println("Using higher: " + The headSet() method returns all the elements of a tree
numbers.higher(4)); set before the specified element (which is passed as an
argument).
// Using lower() The booleanValue parameter is optional. Its default
System.out.println("Using lower: " + value is false.
numbers.lower(4)); If true is passed as a booleanValue, the method returns
all the elements before the specified element including
// Using ceiling() the specified element.
System.out.println("Using ceiling: " + For example,
numbers.ceiling(4));
import java.util.TreeSet;
// Using floor()
System.out.println("Using floor: " + class Main {
numbers.floor(3)); public static void main(String[] args) {
TreeSet<Integer> numbers = new TreeSet<>();
} numbers.add(2);
} numbers.add(5);
numbers.add(4);
Output numbers.add(6);
TreeSet: [2, 4, 5, 6] System.out.println("TreeSet: " + numbers);
Using higher: 5
Using lower: 2 // Using headSet() with default boolean value
Using ceiling: 4 System.out.println("Using headSet without
Using floor: 2 boolean value: " + numbers.headSet(5));

3. pollfirst() and pollLast() Methods // Using headSet() with specified boolean value
pollFirst() - returns and removes the first element from System.out.println("Using headSet with boolean
the set value: " + numbers.headSet(5, true));
}
} numbers.add(4);
numbers.add(6);
Output System.out.println("TreeSet: " + numbers);
TreeSet: [2, 4, 5, 6]
Using headSet without boolean value: [2, 4] // Using subSet() with default boolean value
Using headSet with boolean value: [2, 4, 5] System.out.println("Using subSet without
boolean value: " + numbers.subSet(4, 6));
tailSet(element, booleanValue)
The tailSet() method returns all the elements of a tree // Using subSet() with specified boolean value
set after the specified element (which is passed as a System.out.println("Using subSet with boolean
parameter) including the specified element. value: " + numbers.subSet(4, false, 6, true));
The booleanValue parameter is optional. Its default }
value is true. }
If false is passed as a booleanValue, the method
returns all the elements after the Output
specified element without including the TreeSet: [2, 4, 5, 6]
specified element. Using subSet without boolean value: [4, 5]
For example, Using subSet with boolean value: [5, 6]

import java.util.TreeSet; Set Operations


The methods of the TreeSet class can also be used to
class Main { perform various set operations.
public static void main(String[] args) { Union of Sets
TreeSet<Integer> numbers = new TreeSet<>(); To perform the union between two sets, we use
numbers.add(2); the addAll() method. For example,
numbers.add(5);
numbers.add(4); import java.util.TreeSet;;
numbers.add(6);
System.out.println("TreeSet: " + numbers); class Main {
public static void main(String[] args) {
// Using tailSet() with default boolean value TreeSet<Integer> evenNumbers = new
System.out.println("Using tailSet without TreeSet<>();
boolean value: " + numbers.tailSet(4)); evenNumbers.add(2);
evenNumbers.add(4);
// Using tailSet() with specified boolean value System.out.println("TreeSet1: " + evenNumbers);
System.out.println("Using tailSet with boolean
value: " + numbers.tailSet(4, false)); TreeSet<Integer> numbers = new TreeSet<>();
} numbers.add(1);
} numbers.add(2);
numbers.add(3);
Output System.out.println("TreeSet2: " + numbers);
TreeSet: [2, 4, 5, 6]
Using tailSet without boolean value: [4, 5, 6] // Union of two sets
Using tailSet with boolean value: [5, 6] numbers.addAll(evenNumbers);
System.out.println("Union is: " + numbers);
subSet(e1, bv1, e2, bv2)
The subSet() method returns all the elements }
between e1 and e2 including e1. }
The bv1 and bv2 are optional parameters. The default
value of bv1 is true, and the default value Output
of bv2 is false. TreeSet1: [2, 4]
If false is passed as bv1, the method returns all the TreeSet2: [1, 2, 3]
elements between e1 and e2 without including e1. Union is: [1, 2, 3, 4]
If true is passed as bv2, the method returns all the
elements between e1 and e2, including e1. Intersection of Sets
For example, To perform the intersection between two sets, we use
the retainAll() method. For example,
import java.util.TreeSet;
import java.util.TreeSet;;
class Main {
public static void main(String[] args) { class Main {
TreeSet<Integer> numbers = new TreeSet<>(); public static void main(String[] args) {
numbers.add(2);
numbers.add(5);
TreeSet<Integer> evenNumbers = new numbers.add(1);
TreeSet<>(); numbers.add(2);
evenNumbers.add(2); numbers.add(3);
evenNumbers.add(4); numbers.add(4);
System.out.println("TreeSet1: " + evenNumbers); System.out.println("TreeSet1: " + numbers);

TreeSet<Integer> numbers = new TreeSet<>(); TreeSet<Integer> primeNumbers = new


numbers.add(1); TreeSet<>();
numbers.add(2); primeNumbers.add(2);
numbers.add(3); primeNumbers.add(3);
System.out.println("TreeSet2: " + numbers); System.out.println("TreeSet2: " +
primeNumbers);
// Intersection of two sets
numbers.retainAll(evenNumbers); // Check if primeNumbers is subset of numbers
System.out.println("Intersection is: " + numbers); boolean result =
} numbers.containsAll(primeNumbers);
} System.out.println("Is TreeSet2 subset of
TreeSet1? " + result);
Output }
TreeSet1: [2, 4] }
TreeSet2: [1, 2, 3]
Intersection is: [2] Output
TreeSet1: [1, 2, 3, 4]
Difference of Sets TreeSet2: [2, 3]
To calculate the difference between the two sets, we Is TreeSet2 subset of TreeSet1? True
can use the removeAll() method. For example,
Other Methods of TreeSet
import java.util.TreeSet;; Method Description
clone() Creates a copy of the
class Main { TreeSet
public static void main(String[] args) { contains() Searches the TreeSet for
TreeSet<Integer> evenNumbers = new the specified element and
TreeSet<>(); returns a boolean result
evenNumbers.add(2); isEmpty() Checks if the TreeSet is
evenNumbers.add(4); empty
System.out.println("TreeSet1: " + evenNumbers); size() Returns the size of the
TreeSet
TreeSet<Integer> numbers = new TreeSet<>(); clear() Removes all the elements
numbers.add(1); from the TreeSet
numbers.add(2);
numbers.add(3); TreeSet Vs. HashSet
numbers.add(4); Both the TreeSet as well as the HashSet implements
System.out.println("TreeSet2: " + numbers); the Set interface. However, there exist some
differences between them.
// Difference between two sets Unlike HashSet, elements in TreeSet are stored in
numbers.removeAll(evenNumbers); some order. It is because TreeSet implements
System.out.println("Difference is: " + numbers); the SortedSet interface as well.
} TreeSet provides some methods for easy navigation.
} For example, first(), last(), headSet(), tailSet(), etc. It is
because TreeSet also implements
Output the NavigableSet interface.
TreeSet1: [2, 4] HashSet is faster than the TreeSet for basic operations
TreeSet2: [1, 2, 3, 4] like add, remove, contains and size.
Difference is: [1, 3]
TreeSet Comparator
Subset of a Set In all the examples above, tree set elements are sorted
To check if a set is a subset of another set or not, we naturally. However, we can also customize the
use the containsAll() method. For example, ordering of elements.
For this, we need to create our own comparator class
import java.util.TreeSet; based on which elements in a tree set are sorted. For
example,
class Main {
public static void main(String[] args) { import java.util.TreeSet;
TreeSet<Integer> numbers = new TreeSet<>();
import java.util.Comparator; 1. Sorting Using sort()
The sort() method provided by the collections
class Main { framework is used to sort elements. For example,
public static void main(String[] args) {
import java.util.ArrayList;
// Creating a tree set with a customized import java.util.Collections;
comparator
TreeSet<String> animals = new TreeSet<>(new class Main {
CustomComparator()); public static void main(String[] args) {

animals.add("Dog"); // Creating an array list


animals.add("Zebra"); ArrayList<Integer> numbers = new
animals.add("Cat"); ArrayList<>();
animals.add("Horse");
System.out.println("TreeSet: " + animals); // Add elements
} numbers.add(4);
numbers.add(2);
// Creating a comparator class numbers.add(3);
public static class CustomComparator implements System.out.println("Unsorted ArrayList: " +
Comparator<String> { numbers);

@Override // Using the sort() method


public int compare(String animal1, String Collections.sort(numbers);
animal2) { System.out.println("Sorted ArrayList: " +
int value = animal1.compareTo(animal2); numbers);
}
// elements are sorted in reverse order }
if (value > 0) {
return -1; Output
} Unsorted ArrayList: [4, 2, 3]
else if (value < 0) { Sorted ArrayList: [2, 3, 4]
return 1;
} Here the sorting occurs in natural order (ascending
else { order). However, we can customize the sorting order
return 0; of the sort() method using the Comparator interface.
}
} 2. Shuffling Using shuffle()
}
} The shuffle() method of the Java collections
framework is used to destroy any kind of order present
Output in the data structure. It does just the opposite of the
TreeSet: [Zebra, Horse, Dog, Cat] sorting. For example,

In the above example, we have created a tree set import java.util.ArrayList;


passing CustomComparator class as an argument. import java.util.Collections;
The CustomComparator class implements
the Comparator interface. class Main {
We then override the compare() method. The method public static void main(String[] args) {
will now sort elements in reverse order.
// Creating an array list
ArrayList<Integer> numbers = new
ArrayList<>();
Java Algorithms
// Add elements
The Java collections framework provides various numbers.add(1);
algorithms that can be used to manipulate elements numbers.add(2);
stored in data structures. numbers.add(3);
Algorithms in Java are static methods that can be used System.out.println("Sorted ArrayList: " +
to perform various operations on collections. numbers);
Since algorithms can be used on various collections,
these are also known as generic algorithms. // Using the shuffle() method
Let's see the implementation of different methods Collections.shuffle(numbers);
available in the collections framework. System.out.println("ArrayList using shuffle: " +
numbers);
System.out.println("ArrayList2 using copy(): " +
} newNumbers);
} }
}
Output
Sorted ArrayList: [1, 2, 3] Output
ArrayList using shuffle: [2, 1, 3] ArrayList1: [1, 2]
Reversed ArrayList1: [2, 1]
When we run the program, the shuffle() method will ArrayList1 Using swap(): [1, 2]
return a random output. ArrayList2 using addALl(): [1, 2]
The shuffling algorithm is mainly used in games where ArrayList1 using fill(): [0, 0]
we want random output. ArrayList2 using copy(): [0, 0]

3. Routine Data Manipulation Note: While performing the copy() method both the
In Java, the collections framework provides different lists should be of the same size.
methods that can be used to manipulate data.
reverse() - reverses the order of elements 4. Searching Using binarySearch()
fill() - replace every element in a collection with the The binarySearch() method of the Java collections
specified value framework searches for the specified element. It
copy() - creates a copy of elements from the specified returns the position of the element in the specified
source to destination collections. For example,
swap() - swaps the position of two elements in a
collection import java.util.Collections;
addAll() - adds all the elements of a collection to other import java.util.ArrayList;
collection
For example, class Main {
public static void main(String[] args) {
import java.util.Collections; // Creating an ArrayList
import java.util.ArrayList; ArrayList<Integer> numbers = new
ArrayList<>();
class Main { numbers.add(1);
public static void main(String[] args) { numbers.add(2);
// Creating an ArrayList numbers.add(3);
ArrayList<Integer> numbers = new
ArrayList<>(); // Using binarySearch()
numbers.add(1); int pos = Collections.binarySearch(numbers, 3);
numbers.add(2); System.out.println("The position of 3 is " + pos);
System.out.println("ArrayList1: " + numbers); }
}
// Using reverse()
Collections.reverse(numbers); Output
System.out.println("Reversed ArrayList1: " + The position of 3 is 2.
numbers);
Note: The collection should be sorted before
// Using swap() performing the binarySearch() method.
Collections.swap(numbers, 0, 1);
System.out.println("ArrayList1 using swap(): " +
numbers); 5. Composition
frequency() - returns the count of the number of times
ArrayList<Integer> newNumbers = new an element is present in the collection
ArrayList<>(); disjoint() - checks if two collections contain some
common element
// Using addAll For example,
newNumbers.addAll(numbers);
System.out.println("ArrayList2 using addAll(): " import java.util.Collections;
+ newNumbers); import java.util.ArrayList;

// Using fill() class Main {


Collections.fill(numbers, 0); public static void main(String[] args) {
System.out.println("ArrayList1 using fill(): " + // Creating an ArrayList
numbers); ArrayList<Integer> numbers = new
ArrayList<>();
// Using copy() numbers.add(1);
Collections.copy(newNumbers, numbers); numbers.add(2);
numbers.add(3); Java Iterator Interface
numbers.add(2);
System.out.println("ArrayList1: " + numbers); The Iterator interface of the Java collections
framework allows us to access elements of a
int count = Collections.frequency(numbers, 2); collection. It has a subinterface ListIterator.
System.out.println("Count of 2: " + count); All the Java collections include an iterator() method.
This method returns an instance of iterator used to
ArrayList<Integer> newNumbers = new iterate over elements of collections.
ArrayList<>();
newNumbers.add(5); Methods of Iterator
newNumbers.add(6); The Iterator interface provides 4 methods that can be
System.out.println("ArrayList2: " + used to perform various operations on elements of
newNumbers); collections.
hasNext() - returns true if there exists an element in
boolean value = Collections.disjoint(numbers, the collection
newNumbers); next() - returns the next element of the collection
System.out.println("Two lists are disjoint: " + remove() - removes the last element returned by
value); the next()
} forEachRemaining() - performs the specified action for
} each remaining element of the collection
Output Example: Implementation of Iterator
ArrayList1: [1, 2, 3, 2] In the example below, we have implemented
Count of 2: 2 the hasNext(), next(), remove() and forEachRemining(
ArrayList2: [5, 6] ) methods of the Iterator interface in an ArrayList.
Two lists are disjoint: true
import java.util.ArrayList;
6. Finding Extreme Values import java.util.Iterator;
The min() and max() methods of the Java collections
framework are used to find the minimum and the class Main {
maximum elements, respectively. For example, public static void main(String[] args) {
// Creating an ArrayList
import java.util.Collections; ArrayList<Integer> numbers = new
import java.util.ArrayList; ArrayList<>();
numbers.add(1);
class Main { numbers.add(3);
public static void main(String[] args) { numbers.add(2);
// Creating an ArrayList System.out.println("ArrayList: " + numbers);
ArrayList<Integer> numbers = new
ArrayList<>(); // Creating an instance of Iterator
numbers.add(1); Iterator<Integer> iterate = numbers.iterator();
numbers.add(2);
numbers.add(3); // Using the next() method
int number = iterate.next();
// Using min() System.out.println("Accessed Element: " +
int min = Collections.min(numbers); number);
System.out.println("Minimum Element: " + min);
// Using the remove() method
// Using max() iterate.remove();
int max = Collections.max(numbers); System.out.println("Removed Element: " +
System.out.println("Maximum Element: " + number);
max);
} System.out.print("Updated ArrayList: ");
}
// Using the hasNext() method
Output while(iterate.hasNext()) {
Minimum Element: 1 // Using the forEachRemaining() method
Maximum Element: 3 iterate.forEachRemaining((value) ->
System.out.print(value + ", "));
}
}
}
Output
ArrayList: [1, 3, 2] // Creating an instance of ListIterator
Acessed Element: 1 ListIterator<Integer> iterate =
Removed Element: 1 numbers.listIterator();
Updated ArrayList: 3, 2,
// Using the next() method
In the above example, notice the statement: int number1 = iterate.next();
System.out.println("Next Element: " + number1);
iterate.forEachRemaining((value) ->
System.put.print(value + ", ")); // Using the nextIndex()
int index1 = iterate.nextIndex();
Here, we have passed the lambda expression as an System.out.println("Position of Next Element: "
argument of the forEachRemaining() method. + index1);
Now the method will print all the remaining elements
of the array list. // Using the hasNext() method
System.out.println("Is there any next element? "
+ iterate.hasNext());
Java ListIterator Interface }
}
The ListIterator interface of the Java collections
framework provides the functionality to access Output
elements of a list. ArrayList: [1, 3, 2]
It is bidirectional. This means it allows us to iterate Next Element: 1
elements of a list in both the direction. Position of Next Element: 1
It extends the Iterator interface. Is there any next element? True

The List interface provides a listIterator() method that Example 2: Implementation of ListIterator
returns an instance of the ListIterator interface. In the example below, we have implemented
the previous() and previousIndex() methods of
Methods of ListIterator the ListIterator interface in an array list.
The ListIterator interface provides methods that can
be used to perform various operations on the elements import java.util.ArrayList;
of a list. import java.util.ListIterator;
hasNext() - returns true if there exists an element in
the list class Main {
next() - returns the next element of the list public static void main(String[] args) {
nextIndex() returns the index of the element that // Creating an ArrayList
the next() method will return ArrayList<Integer> numbers = new
previous() - returns the previous element of the list ArrayList<>();
previousIndex() - returns the index of the element that numbers.add(1);
the previous() method will return numbers.add(3);
remove() - removes the element returned by numbers.add(2);
either next() or previous() System.out.println("ArrayList: " + numbers);
set() - replaces the element returned by
either next() or previous() with the specified element // Creating an instance of ListIterator
ListIterator<Integer> iterate =
Example 1: Implementation of ListIterator numbers.listIterator();
In the example below, we have implemented iterate.next();
the next(), nextIndex() and hasNext() methods of iterate.next();
the ListIterator interface in an array list.
// Using the previous() method
import java.util.ArrayList; int number1 = iterate.previous();
import java.util.ListIterator; System.out.println("Previous Element: " +
number1);
class Main {
public static void main(String[] args) { // Using the previousIndex()
// Creating an ArrayList int index1 = iterate.previousIndex();
ArrayList<Integer> numbers = new System.out.println("Position of the Previous
ArrayList<>(); element: " + index1);
numbers.add(1); }
numbers.add(3); }
numbers.add(2);
System.out.println("ArrayList: " + numbers); Output
ArrayList: [1, 3, 2]
Previous Element: 3 Character Stream
Position of the Previous Element: 0

In the above example, initially, the instance of


the Iterator was before 1. Since there was no element
before 1 so calling the previous() method will throw an Byte Stream
exception. Byte stream is used to read and write a single byte (8
We then used the next() methods 2 times. Now bits) of data.
the Iterator instance will be between 3 and 2. All byte stream classes are derived from base abstract
Hence, the previous() method returns 3. classes called InputStream and OutputStream.

Character Stream
Java I/o Streams Character stream is used to read and write a single
character of data.
All the character stream classes are derived from base
abstract classes Reader and Writer.
Java I/O Streams
In Java, streams are the sequence of data that are read Java InputStream Class
from the source and written to the destination.
An input stream is used to read data from the source. The InputStream class of the java.io package is an
And, an output stream is used to write data to the abstract superclass that represents an input stream of
destination. bytes.
Since InputStream is an abstract class, it is not useful
by itself. However, its subclasses can be used to read
class HelloWorld {
data.
public static void main(String[] args) { Subclasses of InputStream
System.out.println("Hello, World!"); In order to use the functionality of InputStream, we
} can use its subclasses. Some of them are:
} FileInputStream
ByteArrayInputStream
For example, in our first Hello World example, we ObjectInputStream
have used System.out to print a string. Here,
the System.out is a type of output stream.
Similarly, there are input streams to take input.

Java FileInputStream class

We will learn about all these subclasses in the next


tutorial.

Create an InputStream
In order to create an InputStream, we must import
We will learn about input streams and output streams
the java.io.InputStream package first. Once we import
in detail in the later tutorials. the package, here is how we can create the input
stream.

// Creates an InputStream
InputStream object1 = new FileInputStream();
Types of Streams
Depending upon the data a stream holds, it can be Here, we have created an input stream
classified into: using FileInputStream. It is because InputStream is an
Byte Stream abstract class. Hence we cannot create an object
of InputStream.
Available bytes in the file: 39
Methods of InputStream Data read from the file:
The InputStream class provides different methods that This is a line of text inside the file
are implemented by its subclasses. Here are some of
the commonly used methods: In the above example, we have created an input
read() - reads one byte of data from the input stream stream using the FileInputStream class. The input
read(byte[] array) - reads bytes from the stream and stream is linked with the file input.txt.
stores in the specified array
available() - returns the number of bytes available in InputStream input = new
the input stream FileInputStream("input.txt");
mark() - marks the position in the input stream up to
which data has been read To read data from the input.txt file, we have
reset() - returns the control to the point in the stream implemented these two methods.
where the mark was set
markSupported() - checks if input.read(array); // to read data from the input
the mark() and reset() method is supported in the stream
stream input.close(); // to close the input stream
skips() - skips and discards the specified number of
bytes from the input stream
close() - closes the input stream Java OutputStream Class
Example: InputStream Using FileInputStream The OutputStream class of the java.io package is an
Here is how we can implement InputStream using abstract superclass that represents an output stream of
the FileInputStream class. bytes.
Suppose we have a file named input.txt with the Since OutputStream is an abstract class, it is not useful
following content. by itself. However, its subclasses can be used to write
data.
This is a line of text inside the file.
Subclasses of OutputStream
Let's try to read this file using FileInputStream (a In order to use the functionality of OutputStream, we
subclass of InputStream). can use its subclasses. Some of them are:
FileOutputStream
import java.io.FileInputStream; ByteArrayOutputStream
import java.io.InputStream; ObjectOutputStream
class Main {
public static void main(String args[]) { Create an OutputStream
In order to create an OutputStream, we must import
byte[] array = new byte[100]; the java.io.OutputStream package first. Once we
import the package, here is how we can create the
try { output stream.
InputStream input = new
FileInputStream("input.txt"); // Creates an OutputStream
OutputStream object = new FileOutputStream();
System.out.println("Available bytes in the file: " +
input.available()); Here, we have created an object of output stream
using FileOutputStream. It is because OutputStream is
// Read byte from the input stream an abstract class, so we cannot create an object
input.read(array); of OutputStream.
System.out.println("Data read from the file: "); Note: We can also create the output stream from other
subclasses of the OutputStream class.
// Convert byte array into string
String data = new String(array); Methods of OutputStream
System.out.println(data); The OutputStream class provides different methods
that are implemented by its subclasses. Here are some
// Close the input stream of the methods:
input.close(); write() - writes the specified byte to the output stream
} catch (Exception e) { write(byte[] array) - writes the bytes from the
e.getStackTrace(); specified array to the output stream
} flush() - forces to write all data present in output
} stream to the destination
} close() - closes the output stream
Output
Example: OutputStream Using FileOutputStream Java FileInputStream Class
Here is how we can implement OutputStream using
the FileOutputStream class The FileInputStream class of the java.io package can
be used to read data (in bytes) from files.
import java.io.FileOutputStream; It extends the InputStream abstract class.
import java.io.OutputStream;

public class Main {

public static void main(String args[]) {


String data = "This is a line of text inside the
file.";

try { Create a FileInputStream


OutputStream out = new In order to create a file input stream, we must import
FileOutputStream("output.txt"); the java.io.FileInputStream package first. Once we
import the package, here is how we can create a file
// Converts the string into bytes input stream in Java.
byte[] dataBytes = data.getBytes();
1. Using the path to file
// Writes data to the output stream FileInputStream input = new
out.write(dataBytes); FileInputStream(stringPath);
System.out.println("Data is written to the Here, we have created an input stream that will be
file."); linked to the file specified by the path.
// Closes the output stream 2. Using an object of the file
out.close(); FileInputStream input = new FileInputStream(File
} fileObject);
Here, we have created an input stream that will be
catch (Exception e) { linked to the file specified by fileObject.
e.getStackTrace();
} Methods of FileInputStream
} The FileInputStream class provides implementations
} for different methods present in the InputStream class.
read() Method
In the above example, we have created an output read() - reads a single byte from the file
stream using the FileOutputStream class. The output read(byte[] array) - reads the bytes from the file and
stream is now linked with the file output.txt. stores in the specified array
read(byte[] array, int start, int length) - reads the
OutputStream out = new number of bytes equal to length from the file and
FileOutputStream("output.txt"); stores in the specified array starting from the
position start
To write data to the output.txt file, we have
implemented these methods. Suppose we have a file named input.txt with the
following content.
output.write(); // To write data to the file
output.close(); // To close the output stream This is a line of text inside the file.
Let's try to read this file using FileInputStream.
When we run the program, the output.txt file is filled import java.io.FileInputStream;
with the following content. public class Main {
public static void main(String args[]) {
This is a line of text inside the file. try {
FileInputStream input = new
FileInputStream("input.txt");
System.out.println("Data in the file: ");
// Reads the first byte
int i = input.read();
while(i != -1) {
System.out.print((char)i);
// Reads next byte from the file
i = input.read();
}
input.close();
} skip() Method
catch(Exception e) { To discard and skip the specified number of bytes, we
e.getStackTrace(); can use the skip() method. For example,
}
} import java.io.FileInputStream;
} public class Main {
public static void main(String args[]) {
Output try {
Data in the file: // Suppose, the input.txt file contains the
This is a line of text inside the file. following text
// This is a line of text inside the file.
In the above example, we have created a file input FileInputStream input = new
stream named input. The input stream is linked with FileInputStream("input.txt");
the input.txt file. // Skips the 5 bytes
FileInputStream input = new input.skip(5);
FileInputStream("input.txt"); System.out.println("Input stream after skipping 5
To read data from the file, we have used bytes:");
the read() method inside the while loop. // Reads the first byte
int i = input.read();
available() Method while (i != -1) {
To get the number of available bytes, we can use System.out.print((char) i);
the available() method. For example, // Reads next byte from the file
i = input.read();
import java.io.FileInputStream; }
// close() method
public class Main { input.close(); }
public static void main(String args[]) { catch (Exception e) {
try { e.getStackTrace();
// Suppose, the input.txt file contains the } }}
following text
// This is a line of text inside the file. Output
FileInputStream input = new Input Stream after skipping 5 bytes:
FileInputStream("input.txt"); is a line of text inside the file.
In the above example, we have used the skip() method
// Returns the number of available bytes to skip 5 bytes of data from the file input stream.
System.out.println("Available bytes at the Hence, the bytes representing the text "This " is not
beginning: " + input.available()); read from the input stream.
// Reads 3 bytes from the file close() Method
input.read(); To close the file input stream, we can use
input.read(); the close() method. Once the close() method is called,
input.read(); we cannot use the input stream to read data.
// Returns the number of available bytes In all the above examples, we have used
System.out.println("Available bytes at the end: " the close() method to close the file input stream.
+ input.available());
input.close(); Other Methods Of FileInputStream
} Methods Descriptions
catch (Exception e) { finalize() ensures that the close()
e.getStackTrace(); method is called
}}} getChannel() returns the object of
FileChannel associated
Output with the input stream
Available bytes at the beginning: 39 getFD() returns the file descriptor
Available bytes at the end: 36 associated with the input
stream
In the above example, mark() mark the position in input
We first use the available() method to check the stream up to which data
number of available bytes in the file input stream. has been read
We then have used the read() method 3 times to read 3 reset() returns the control to the
bytes from the file input stream. point in the input stream
Now, after reading the bytes we again have checked where the mark was set
the available bytes. This time the available bytes
decreased by 3.
Java FileOutputStream Class try {
FileOutputStream output = new
The FileOutputStream class of the java.io package can FileOutputStream("output.txt");
be used to write data (in bytes) to the files. byte[] array = data.getBytes();
It extends the OutputStream abstract class. // Writes byte to the file
output.write(array);
output.close();
}
catch(Exception e) {
e.getStackTrace();
}}}
In the above example, we have created a file output
stream named output. The file output stream is linked
with the file output.txt.

FileOutputStream output = new


Create a FileOutputStream FileOutputStream("output.txt");
In order to create a file output stream, we must import
the java.io.FileOutputStream package first. Once we To write data to the file, we have used
import the package, here is how we can create a file the write() method.
output stream in Java. Here, when we run the program, the output.txt file is
filled with the following content.
1. Using the path to file This is a line of text inside the file.
// Including the boolean parameter Note: The getBytes() method used in the program
FileOutputStream output = new converts a string into an array of bytes.
FileOutputStream(String path, boolean value); flush() Method
To clear the output stream, we can use
// Not including the boolean parameter the flush() method. This method forces the output
FileOutputStream output = new stream to write all data to the destination. For
FileOutputStream(String path); example,

Here, we have created an output stream that will be import java.io.FileOutputStream;


linked to the file specified by the path. import java.io.IOException;

Also, value is an optional boolean parameter. If it is public class Main {


set to true, the new data will be appended to the end of public static void main(String[] args) throws
the existing data in the file. Otherwise, the new data IOException {
overwrites the existing data in the file. FileOutputStream out = null;
2. Using an object of the file String data = "This is demo of flush method";
FileOutputStream output = new try {
FileOutputStream(File fileObject); out = new FileOutputStream(" flush.txt");
Here, we have created an output stream that will be // Using write() method
linked to the file specified by fileObject. out.write(data.getBytes());
// Using the flush() method
Methods of FileOutputStream out.flush();
The FileOutputStream class provides implementations out.close(); }
for different methods present in catch(Exception e) {
the OutputStream class. e.getStackTrace();
}}}
write() Method
write() - writes the single byte to the file output stream When we run the program, the file flush.txt is filled
write(byte[] array) - writes the bytes from the with the text represented by the string data.
specified array to the output stream
write(byte[] array, int start, int length) - writes the close() Method
number of bytes equal to length to the output stream To close the file output stream, we can use
from an array starting from the position start the close() method. Once the method is called, we
Example: FileOutputStream to write data to a File cannot use the methods of FileOutputStream.
import java.io.FileOutputStream;
Other Methods Of FileOutputStream
public class Main { Methods Descriptions
public static void main(String[] args) { finalize() ensures that the close()
String data = "This is a line of text inside the method is called
file."; getChannel() returns the object of
FileChannel associated byte[] array = {1, 2, 3, 4};
with the output stream try {
getFD() returns the file descriptor ByteArrayInputStream input = new
associated with the output ByteArrayInputStream(array);
stream System.out.print("The bytes read from the input
stream: ");
for(int i= 0; i < array.length; i++) {
Java ByteArrayInputStream Class // Reads the bytes
int data = input.read();
The ByteArrayInputStream class of System.out.print(data + ", "); }
the java.io package can be used to read an array of input.close(); }
input data (in bytes). catch(Exception e) {
It extends the InputStream abstract class. e.getStackTrace();
}}}
Note: In ByteArrayInputStream, the input stream is
created using the array of bytes. It includes an internal Output
array to store data of that particular byte array. The bytes read from the input stream: 1, 2, 3, 4,

Create a ByteArrayInputStream In the above example, we have created a byte array


In order to create a byte array input stream, we must input stream named input.
import the java.io.ByteArrayInputStream package
first. Once we import the package, here is how we can ByteArrayInputStream input = new
create an input stream. ByteArrayInputStream(array);

// Creates a ByteArrayInputStream that reads entire Here, the input stream includes all the data from the
array specified array. To read data from the input stream,
ByteArrayInputStream input = new we have used the read() method.
ByteArrayInputStream(byte[] arr);
available() Method
Here, we have created an input stream that reads To get the number of available bytes in the input
entire data from the arr array. However, we can also stream, we can use the available() method. For
create the input stream that reads only some data from example,
the array.
import java.io.ByteArrayInputStream;
// Creates a ByteArrayInputStream that reads a
portion of array public class Main {
ByteArrayInputStream input = new
ByteArrayInputStream(byte[] arr, int start, int length); public static void main(String args[]) {

Here the input stream reads the number of bytes equal // Creates an array of bytes
to length from the array starting from byte[] array = { 1, 2, 3, 4 };
the start position.
try {
Methods of ByteArrayInputStream ByteArrayInputStream input = new
The ByteArrayInputStream class provides ByteArrayInputStream(array);
implementations for different methods present in
the InputStream class. // Returns the available number of bytes
read() Method System.out.println("Available bytes at the
read() - reads the single byte from the array present in beginning: " + input.available());
the input stream
read(byte[] array) - reads bytes from the input stream // Reads 2 bytes from the input stream
and stores in the specified array input.read();
read(byte[] array, int start, int length) - reads the input.read();
number of bytes equal to length from the stream and
stores in the specified array starting from the // Returns the available number of bytes
position start System.out.println("Available bytes at the end: " +
input.available());
Example: ByteArrayInputStream to read data
input.close();
import java.io.ByteArrayInputStream;
}
public class Main {
catch (Exception e) {
public static void main(String[] args) {
e.getStackTrace();
// Creates an array of byte
} }}
Output methods of this class even after the close() method is
Available bytes at the beginning: 4 called.
Available bytes at the end: 2
Other Methods Of ByteArrayInputStream
In the above example, Methods Descriptions
We have used the available() method to check the finalize() ensures that the close()
number of available bytes in the input stream. method is called
We have then used the read() method 2 times to read 2 mark() marks the position in
bytes from the input stream. input stream up to which
Now, after reading the 2 bytes, we have checked the data has been read
available bytes. This time the available bytes decreased reset() returns the control to the
by 2. point in the input stream
where the mark was set
skip() Method markSupported() checks if the input stream
To discard and skip the specified number of bytes, we supports mark() and
can use the skip() method. For example, reset()

import java.io.ByteArrayInputStream;

public class Main { Java ByteArrayOutputStream Class


public static void main(String args[]) { The ByteArrayOutputStream class of
the java.io package can be used to write an array of
// Create an array of bytes output data (in bytes).
byte[] array = { 1, 2, 3, 4 };
try { It extends the OutputStream abstract class.
ByteArrayInputStream input = new
ByteArrayInputStream(array);

// Using the skip() method


input.skip(2);
System.out.print("Input stream after skipping 2
bytes: ");

int data = input.read(); Note: In ByteArrayOutputStream maintains an


while (data != -1) { internal array of bytes to store the data.
System.out.print(data + ", ");
data = input.read(); Create a ByteArrayOutputStream
} In order to create a byte array output stream, we must
import the java.io.ByteArrayOutputStream package
// close() method first. Once we import the package, here is how we can
input.close(); create an output stream.
}
// Creates a ByteArrayOutputStream with default size
catch (Exception e) { ByteArrayOutputStream out = new
e.getStackTrace(); ByteArrayOutputStream();
}
} Here, we have created an output stream that will write
} data to an array of bytes with default size 32 bytes.
However, we can change the default size of the array.
Output
Input stream after skipping 2 bytes: 3, 4, // Creating a ByteArrayOutputStream with specified
size
In the above example, we have used the skip() method ByteArrayOutputStream out = new
to skip 2 bytes of data from the input stream. ByteArrayOutputStream(int size);
Hence 1 and 2 are not read from the input stream.
Here, the size specifies the length of the array.
close() Method
To close the input stream, we can use Methods of ByteArrayOutputStream
the close() method. The ByteArrayOutputStream class provides the
However, the close() method has no effect implementation of the different methods present in
in ByteArrayInputStream class. We can use the the OutputStream class.
write() Method
write(int byte) - writes the specified byte to the output toString() - returns the entire data of the output stream
stream in string form
write(byte[] array) - writes the bytes from the specified For example,
array to the output stream
write(byte[] arr, int start, int length) - writes the import java.io.ByteArrayOutputStream;
number of bytes equal to length to the output stream
from an array starting from the position start class Main {
writeTo(ByteArrayOutputStream out1) - writes the public static void main(String[] args) {
entire data of the current output stream to the specified String data = "This is data.";
output stream
try {
Example: ByteArrayOutputStream to write data // Creates an output stream
ByteArrayOutputStream out = new
import java.io.ByteArrayOutputStream; ByteArrayOutputStream();

class Main { // Writes data to the output stream


public static void main(String[] args) { out.write(data.getBytes());

String data = "This is a line of text inside the // Returns an array of bytes
string."; byte[] byteData = out.toByteArray();
System.out.print("Data using toByteArray(): ");
try { for(int i=0; i<byteData.length; i++) {
// Creates an output stream System.out.print((char)byteData[i]);
ByteArrayOutputStream out = new }
ByteArrayOutputStream();
byte[] array = data.getBytes(); // Returns a string
String stringData = out.toString();
// Writes data to the output stream System.out.println("\nData using toString(): " +
out.write(array); stringData);

// Retrieves data from the output stream in string out.close();


format }
String streamData = out.toString();
System.out.println("Output stream: " + catch(Exception e) {
streamData); e.getStackTrace();
}
out.close(); }
} }

catch(Exception e) { Output
e.getStackTrace(); Data using toByteArray(): This is data.
} Data using toString(): This is data.
}
} In the above example, we have created an array of
bytes to store the data returned by
Output the toByteArray() method.
Output stream: This is a line of text inside the string. We then have used the for loop to access each byte
from the array. Here, each byte is converted into the
In the above example, we have created a byte array corresponding character using typecasting.
output stream named output.
close() Method
ByteArrayOutputStream output = new To close the output stream, we can use
ByteArrayOutputStream(); the close() method.
However, the close() method has no effect
To write the data to the output stream, we have used in ByteArrayOutputStream class. We can use the
the write() method. methods of this class even after the close() method is
called.
Note: The getBytes() method used in the program
converts a string into an array of bytes. Other Methods of ByteArrayOutputStream
Methods Descriptions
Access Data from ByteArrayOutputStream size() returns the size of the
toByteArray() - returns the array present inside the array in the output stream
output stream flush() clears the output stream
Java ObjectInputStream Class class Main {
public static void main(String[] args) {
The ObjectInputStream class of the java.io package
can be used to read objects that were previously int data1 = 5;
written by ObjectOutputStream. String data2 = "This is programiz";

It extends the InputStream abstract class. try {


FileOutputStream file = new
Working of ObjectInputStream FileOutputStream("file.txt");
The ObjectInputStream is mainly used to read data ObjectOutputStream output = new
written by the ObjectOutputStream. ObjectOutputStream(file);
Basically, the ObjectOutputStream converts Java
objects into corresponding streams. This is known as // Writing to the file using
serialization. Those converted streams can be stored in ObjectOutputStream
files or transferred through networks. output.writeInt(data1);
Now, if we need to read those objects, we will use output.writeObject(data2);
the ObjectInputStream that will convert the streams
back to corresponding objects. This is known as FileInputStream fileStream = new
deserialization. FileInputStream("file.txt");
// Creating an object input stream
Create an ObjectInputStream ObjectInputStream objStream = new
In order to create an object input stream, we must ObjectInputStream(fileStream);
import the java.io.ObjectInputStream package first.
Once we import the package, here is how we can //Using the readInt() method
create an input stream. System.out.println("Integer data :" +
objStream.readInt());
// Creates a file input stream linked with the specified
file // Using the readObject() method
FileInputStream fileStream = new System.out.println("String data: " +
FileInputStream(String file); objStream.readObject());

// Creates an object input stream using the file input output.close();


stream objStream.close();
ObjectInputStream objStream = new }
ObjectInputStream(fileStream); catch (Exception e) {
e.getStackTrace();
In the above example, we have created an object input }
stream named objStream that is linked with the file }
input stream named fileStream. }
Now, the objStream can be used to read objects from
the file.
Output
Methods of ObjectInputStream Integer data: 5
The ObjectInputStream class provides String data: This is programiz
implementations of different methods present in
the InputStream class. In the above example, we have used
the readInt() and readObject() method to read integer
read() Method data and object data from the file.
read() - reads a byte of data from the input stream Here, we have used the ObjectOutputStream to write
readBoolean() - reads data in boolean form data to the file. We then read the data from the file
readChar() - reads data in character form using the ObjectInputStream.
readInt() - reads data in integer form
readObject() - reads the object from the input stream Example 2: Java ObjectInputStream
Let's see another practical example,
Example 1: Java ObjectInputStream import java.io.FileInputStream;
Let's see how we can use the ObjectInputStream class import java.io.FileOutputStream;
to read objects written by import java.io.ObjectInputStream;
the ObjectOutputStream class. import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.io.FileInputStream;
import java.io.FileOutputStream; class Dog implements Serializable {
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream; String name;
String breed;
Note: The Dog class implements
public Dog(String name, String breed) { the Serializable interface. It is because
this.name = name; the ObjectOutputStream only writes the serializable
this.breed = breed; objects to the output stream.
}
} Other Methods Of ObjectInputStream
Methods Descriptions
class Main { available() returns the available
public static void main(String[] args) { number of bytes in the
input stream
// Creates an object of Dog class mark() marks the position in
Dog dog = new Dog("Tyson", "Labrador"); input stream up to which
data has been read
try { reset() returns the control to the
FileOutputStream file = new point in the input stream
FileOutputStream("file.txt"); where the mark was set
skipBytes() skips and discards the
// Creates an ObjectOutputStream specified bytes from the
ObjectOutputStream output = new input stream
ObjectOutputStream(file); close() closes the object input
stream
// Writes objects to the output stream
output.writeObject(dog);

FileInputStream fileStream = new


Java ObjectOutputStream Class
FileInputStream("file.txt"); The ObjectOutputStream class of the java.io package
can be used to write objects that can be read
// Creates an ObjectInputStream by ObjectInputStream.
ObjectInputStream input = new
ObjectInputStream(fileStream); It extends the OutputStream abstract class.

// Reads the objects Working of ObjectOutputStream


Dog newDog = (Dog) input.readObject(); Basically, the ObjectOutputStream encodes Java
objects using the class name and object values. And,
System.out.println("Dog Name: " + hence generates corresponding streams. This process is
newDog.name); known as serialization.
System.out.println("Dog Breed: " + Those converted streams can be stored in files and can
newDog.breed); be transferred among networks.
Note: The ObjectOutputStream class only writes those
output.close(); objects that implement the Serializable interface. This
input.close(); is because objects need to be serialized while writing to
} the stream

catch (Exception e) { Create an ObjectOutputStream


e.getStackTrace(); In order to create an object output stream, we must
} import the java.io.ObjectOutputStream package first.
} Once we import the package, here is how we can
} create an output stream.

// Creates a FileOutputStream where objects from


Output ObjectOutputStream are written
Dog Name: Tyson FileOutputStream fileStream = new
Dog Breed: Labrador FileOutputStream(String file);

In the above example, we have created // Creates the ObjectOutputStream


ObjectOutputStream named output using ObjectOutputStream objStream = new
the FileOutputStream named file ObjectOutputStream(fileStream);
ObjectInputStream named input using In the above example, we have created an object
the FileInputStream named fileStream output stream named objStream that is linked with the
An object dog of the Dog class file output stream named fileStream.
Here, we have then used the object output stream to
write the object to the file. And, the object input
stream to read the object from the file.
Methods of ObjectOutputStream String data: This is programiz
The ObjectOutputStream class provides
implementations for different methods present in In the above example, we have used
the OutputStream class. the readInt() method and readObject() method to read
an integer data and object data from the files.
write() Method Here, we have used the ObjectOutputStream to write
write() - writes a byte of data to the output stream data to the file. We then read the data from the file
writeBoolean() - writes data in boolean form using the ObjectInputStream.
writeChar() - writes data in character form
writeInt() - writes data in integer form Example 2: Java ObjectOutputStream
writeObject() - writes object to the output stream Let's take another example,
import java.io.FileInputStream;
Example 1: Java ObjectOutputStream import java.io.FileOutputStream;
Let's see how we can use ObjectOutputStream to store import java.io.ObjectInputStream;
objects in a file and ObjectInputStream to read those import java.io.ObjectOutputStream;
objects from the files import java.io.Serializable;

import java.io.FileInputStream; class Dog implements Serializable {


import java.io.FileOutputStream;
import java.io.ObjectInputStream; String name;
import java.io.ObjectOutputStream; String breed;

class Main { public Dog(String name, String breed) {


public static void main(String[] args) { this.name = name;
this.breed = breed;
int data1 = 5; }
String data2 = "This is programiz"; }

try { class Main {


public static void main(String[] args) {
FileOutputStream file = new
FileOutputStream("file.txt"); // Creates an object of Dog class
Dog dog1 = new Dog("Tyson", "Labrador");
// Creates an ObjectOutputStream
ObjectOutputStream output = new try {
ObjectOutputStream(file); FileOutputStream fileOut = new
FileOutputStream("file.txt");
// writes objects to output stream
output.writeInt(data1); // Creates an ObjectOutputStream
output.writeObject(data2); ObjectOutputStream objOut = new
ObjectOutputStream(fileOut);
// Reads data using the ObjectInputStream
FileInputStream fileStream = new // Writes objects to the output stream
FileInputStream("file.txt"); objOut.writeObject(dog1);
ObjectInputStream objStream = new
ObjectInputStream(fileStream); // Reads the object
FileInputStream fileIn = new
System.out.println("Integer data :" + FileInputStream("file.txt");
objStream.readInt()); ObjectInputStream objIn = new
System.out.println("String data: " + ObjectInputStream(fileIn);
objStream.readObject());
// Reads the objects
output.close(); Dog newDog = (Dog) objIn.readObject();
objStream.close();
} System.out.println("Dog Name: " +
newDog.name);
catch (Exception e) { System.out.println("Dog Breed: " +
e.getStackTrace(); newDog.breed);
}
} objOut.close();
} objIn.close();
}
Output
Integer data: 5 catch (Exception e) {
e.getStackTrace();
} Create a BufferedInputStream
} In order to create a BufferedInputStream, we must
} import the java.io.BufferedInputStream package first.
Once we import the package here is how we can create
Output the input stream.
Dog Name: Tyson // Creates a FileInputStream
Dog Breed: Labrador FileInputStream file = new FileInputStream(String
path);
In the above example, we have created
ObjectOutputStream named objOut using // Creates a BufferedInputStream
the FileOutputStream named fileOut BufferedInputStream buffer = new
ObjectInputStream named objIn using BufferInputStream(file);
the FileInputStream named fileIn. In the above example, we have created
An object dog1 of the Dog class. a BufferdInputStream named buffer with
Here, we have then used the object output stream to the FileInputStream named file.
write the object to the file. And, the object input Here, the internal buffer has the default size of 8192
stream to read the object from the file. bytes. However, we can specify the size of the internal
Note: The Dog class implements buffer as well.
the Serializable interface. It is because // Creates a BufferedInputStream with specified size
the ObjectOutputStream only writes objects that can internal buffer
be serialized to the output stream. BufferedInputStream buffer = new
BufferInputStream(file, int size);
Other Methods Of ObjectOutputStream The buffer will help to read bytes from the files more
Methods Descriptions quickly.
flush() clears all the data from
the output stream Methods of BufferedInputStream
drain() puts all the buffered data The BufferedInputStream class provides
in the output stream implementations for different methods present in
close() closes the output stream the InputStream class.

read() Method
Java BufferedInputStream Class read() - reads a single byte from the input stream
read(byte[] arr) - reads bytes from the stream and
The BufferedInputStream class of the java.io package stores in the specified array
is used with other input streams to read the data (in read(byte[] arr, int start, int length) - reads the number
bytes) more efficiently. of bytes equal to the length from the stream and stores
in the specified array starting from the position start
It extends the InputStream abstract class. AD
Suppose we have a file named input.txt with the
following content.
This is a line of text inside the file.
Let's try to read the file using BufferedInputStream.

import java.io.BufferedInputStream;
import java.io.FileInputStream;

class Main {
public static void main(String[] args) {
try {

// Creates a FileInputStream
FileInputStream file = new
FileInputStream("input.txt");
Working of BufferedInputStream
The BufferedInputStream maintains an internal buffer // Creates a BufferedInputStream
of 8192 bytes. BufferedInputStream input = new
During the read operation in BufferedInputStream, a BufferedInputStream(file);
chunk of bytes is read from the disk and stored in the
internal buffer. And from the internal buffer bytes are // Reads first byte from file
read individually. int i = input .read();
Hence, the number of communication to the disk is
reduced. This is why reading bytes is faster using while (i != -1) {
the BufferedInputStream. System.out.print((char) i);
System.out.println("Available bytes at the end: "
// Reads next byte from the file + buffer.available());
i = input.read();
} buffer.close();
input.close(); }
}
catch (Exception e) {
catch (Exception e) { e.getStackTrace();
e.getStackTrace(); }
} }
} }
}

Output Output
This is a line of text inside the file. Available bytes at the beginning: 39
In the above example, we have created a buffered Available bytes at the end: 36
input stream named buffer along
with FileInputStream. The input stream is linked with In the above example,
the file input.txt. We first use the available() method to check the
number of available bytes in the input stream.
FileInputStream file = new Then, we have used the read() method 3 times to read
FileInputStream("input.txt"); 3 bytes from the input stream.
BufferedInputStream buffer = new Now, after reading the bytes we again have checked
BufferedInputStream(file); the available bytes. This time the available bytes
decreased by 3.
Here, we have used the read() method to read an array
of bytes from the internal buffer of the buffered reader. skip() Method
To discard and skip the specified number of bytes, we
available() Method can use the skip() method. For example,
To get the number of available bytes in the input
stream, we can use the available() method. For
example, Import java.io.FileInputStream;
import java.io.BufferedInputStream;

Import java.io.FileInputStream; public class Main {


import java.io.BufferedInputStream;
public static void main(String args[]) {
public class Main {
try {
public static void main(String args[]) { // Suppose, the input.txt file contains the
following text
try { // This is a line of text inside the file.
FileInputStream file = new
// Suppose, the input.txt file contains the FileInputStream("input.txt");
following text
// This is a line of text inside the file. // Creates a BufferedInputStream
FileInputStream file = new BufferedInputStream buffer = new
FileInputStream("input.txt"); BufferedInputStream(file);

// Creates a BufferedInputStream // Skips the 5 bytes


BufferedInputStream buffer = new buffer.skip(5);
BufferedInputStream(file); System.out.println("Input stream after skipping 5
bytes:");
// Returns the available number of bytes
System.out.println("Available bytes at the // Reads the first byte from input stream
beginning: " + buffer.available()); int i = buffer.read();
while (i != -1) {
// Reads bytes from the file System.out.print((char) i);
buffer.read();
buffer.read(); // Reads next byte from the input stream
buffer.read(); i = buffer.read();
}
// Returns the available number of bytes
// Closes the input stream
buffer.close(); BufferedOutputStream buffer = new
} BufferOutputStream(file);

catch (Exception e) { In the above example, we have created


e.getStackTrace(); a BufferdOutputStream named buffer with
} the FileOutputStream named file.
} AD
} Here, the internal buffer has the default size of 8192
bytes. However, we can specify the size of the internal
Output buffer as well.
Input stream after skipping 5 bytes: is a line of text
inside the file. // Creates a BufferedOutputStream with specified size
internal buffer
In the above example, we have used the skip() method BufferedOutputStream buffer = new
to skip 5 bytes from the file input stream. Hence, the BufferOutputStream(file, int size);
bytes 'T', 'h', 'i', 's' and ' ' are skipped from the input
stream. The buffer will help to write bytes to files more
quickly.
close() Method
To close the buffered input stream, we can use Methods of BufferedOutputStream
the close() method. Once the close() method is called, The BufferedOutputStream class provides
we cannot use the input stream to read the data. implementations for different methods in
the OutputStream class.
Other Methods Of BufferedInputStream
Methods Descriptions write() Method
mark() mark the position in input write() - writes a single byte to the internal buffer of
stream up to which data the output stream
has been read write(byte[] array) - writes the bytes from the
reset() returns the control to the specified array to the output stream
point in the input stream write(byte[] arr, int start, int length) - writes the
where the mark was set number of bytes equal to length to the output stream
from an array starting from the position start

Java BufferedOutputStream Class Example: BufferedOutputStream to write data to a


File
The BufferedOutputStream class of
the java.io package is used with other output streams import java.io.FileOutputStream;
to write the data (in bytes) more efficiently. import java.io.BufferedOutputStream;

It extends the OutputStream abstract class. public class Main {


public static void main(String[] args) {
Working of BufferedOutputStream
The BufferedOutputStream maintains an String data = "This is a line of text inside the file";
internal buffer of 8192 bytes.
During the write operation, the bytes are written to the try {
internal buffer instead of the disk. Once the buffer is // Creates a FileOutputStream
filled or the stream is closed, the whole buffer is FileOutputStream file = new
written to the disk. FileOutputStream("output.txt");
Hence, the number of communication to the disk is
reduced. This is why writing bytes is faster // Creates a BufferedOutputStream
using BufferedOutputStream. BufferedOutputStream output = new
BufferedOutputStream(file);
Create a BufferedOutputStream
In order to create a BufferedOutputStream, we must byte[] array = data.getBytes();
import the java.io.BufferedOutputStream package
first. Once we import the package here is how we can // Writes data to the output stream
create the output stream. output.write(array);
output.close();
// Creates a FileOutputStream }
FileOutputStream file = new FileOutputStream(String
path); catch (Exception e) {
e.getStackTrace();
// Creates a BufferedOutputStream }
}}
When we run the program, the file flush.txt is filled
In the above example, we have created a buffered with the text represented by the string data.
output stream named output along
with FileOutputStream. The output stream is linked close() Method
with the file output.txt. To close the buffered output stream, we can use
the close() method. Once the method is called, we
FileOutputStream file = new cannot use the output stream to write the data.
FileOutputStream("output.txt");
BufferedOutputStream output = new
BufferedOutputStream(file); Java PrintStream Class
To write data to the file, we have used The PrintStream class of the java.io package can be
the write() method. used to write output data in commonly readable form
Here when we run the program, the output.txt file is (text) instead of bytes.
filled with the following content.
This is a line of text inside the file. It extends the abstract class OutputStream.

Note: The getBytes() method used in the program Working of PrintStream


converts a string into an array of bytes. Unlike other output streams, the PrintStream converts
the primitive data (integer, character) into the text
flush() Method format instead of bytes. It then writes that formatted
To clear the internal buffer, we can use data to the output stream.
the flush() method. This method forces the output And also, the PrintStream class does not throw any
stream to write all data present in the buffer to the input/output exception. Instead, we need to use
destination file. For example, the checkError() method to find any error in it.
Note: The PrintStream class also has a feature of auto
import java.io.FileOutputStream; flushing. This means it forces the output stream to
import java.io.BufferedOutputStream; write all the data to the destination under one of the
following conditions:
public class Main { if newline character \n is written in the print stream
public static void main(String[] args) { if the println() method is invoked
if an array of bytes is written in the print stream
String data = "This is a demo of the flush
method"; Create a PrintStream
In order to create a PrintStream, we must import
try { the java.io.PrintStream package first. Once we import
// Creates a FileOutputStream the package here is how we can create the print
FileOutputStream file = new stream.
FileOutputStream(" flush.txt");
1. Using other output streams
// Creates a BufferedOutputStream
BufferedOutputStream buffer = new // Creates a FileOutputStream
BufferedOutputStream(file); FileOutputStream file = new FileOutputStream(String
file);
// Writes data to the output stream
buffer.write(data.getBytes()); // Creates a PrintStream
PrintStream output = new PrintStream(file,
// Flushes data to the destination autoFlush);
buffer.flush();
System.out.println("Data is flushed to the Here,
file."); we have created a print stream that will write
buffer.close(); formatted data to the file represented
} by FileOutputStream
the autoFlush is an optional boolean parameter that
catch(Exception e) { specifies whether to perform auto flushing or not
e.getStackTrace();
} 2. Using filename
} // Creates a PrintStream
} PrintStream output = new PrintStream(String file,
boolean autoFlush);
Output Here,
Data is flushed to the file. we have created a print stream that will write
formatted data to the specified file
autoFlush is an optional boolean parameter that e.getStackTrace();
specifies whether to perform autoflush or not }
Note: In both the case, the PrintStream write data to }
the file using some default character encoding. }
However, we can specify the character encoding In the above example, we have created a print stream
(UTF8 or UTF16) as well. named output. The print stream is linked with
// Creates a PrintStream using some character the output.txt file.
encoding PrintStream output = new PrintStream("output.txt");
PrintStream output = new PrintStream(String file, To print data to the file, we have used
boolean autoFlush, Charset cs); the print() method.
Here, we have used the Charset class to specify the Here, when we run the program, the output.txt file is
character encoding. filled with the following content.
This is a text inside the file.
Methods of PrintStream
The PrintStream class provides various methods that printf() Method
allow us to print data to the output. The printf() method can be used to print the
formatted string. It includes 2 parameters: formatted
print() Method string and arguments. For example,
print() - prints the specified data to the output stream printf("I am %d years old", 25);
println() - prints the data to the output stream along Here,
with a new line character at the end I am %d years old is a formatted string
%d is integer data in the formatted string
Example: print() method with System class 25 is an argument
class Main { The formatted string includes both text and data. And,
public static void main(String[] args) { the arguments replace the data inside the formatted
string.
String data = "Hello World."; Hence the %d is replaced by 25.
System.out.print(data); Example: printf() method using PrintStream
} import java.io.PrintStream;
}
class Main {
Output public static void main(String[] args) {
Hello World.
In the above example, we have not created a print try {
stream. However, we can use the print() method of PrintStream output = new
the PrintStream class. PrintStream("output.txt");
You might be wondering how is this possible. Well, let
me explain what is happening here. int age = 25;
Notice the line,
System.out.print(data); output.printf("I am %d years old.", age);
Here, output.close();
System is a final class that is responsible to perform }
standard input/output operation catch(Exception e) {
out is a class variable of PrintStream type declared e.getStackTrace();
in System class }
Now since out is of PrintStream type, we can use it to }
call all the methods of PrintStream class. }

Example: print() method with PrintStream class In the above example, we have created a print stream
import java.io.PrintStream; named output. The print stream is linked with the
file output.txt.
class Main { PrintStream output = new PrintStream("output.txt");
public static void main(String[] args) { To print the formatted text to the file, we have used
the printf() method.
String data = "This is a text inside the file."; Here, when we run the program, the output.txt file is
filled with the following content.
try { I am 25 years old.
PrintStream output = new
PrintStream("output.txt"); Other Methods Of PrintStream
Methods Descriptions
output.print(data); close() closes the print stream
output.close(); checkError() checks if there is an error
} in the stream and returns
catch(Exception e) {
a boolean result try {
append() appends the specified data
to the stream // trying to create a file based on the object
boolean value = file.createNewFile();
if (value) {
System.out.println("The new file is created.");
Java Reader/Writer }
else {
System.out.println("The file already exists.");
}
Java File Class }
catch(Exception e) {
e.getStackTrace();
The File class of the java.io package is used to perform
}
various operations on files and directories.
}
There is another package named java.nio that can be
}
used to work with files. However, in this tutorial, we
In the above example, we have created a file object
will focus on the java.io package.
named file. The file object is linked with the specified
file path.
File and Directory
File file = new File("newFile.txt");
A file is a named location that can be used to store
Here, we have used the file object to create the new
related information. For example,
file with the specified path.
main.java is a Java file that contains information
If newFile.txt doesn't exist in the current location, the
about the Java program.
file is created and this message is shown.
A directory is a collection of files and subdirectories. A
The new file is created.
directory inside a directory is known as subdirectory.
However, if newFile.txt already exists, we will see this
message.
Create a Java File Object The file already exists.
To create an object of File, we need to import
the java.io.File package first. Once we import the
package, here is how we can create objects of file. Java read files
// creates an object of File using the path To read data from the file, we can use subclasses of
File file = new File(String pathName); either InputStream or Reader.
Here, we have created a file object named file. The
object can be used to work with files and directories. Example: Read a file using FileReader
Suppose we have a file named input.txt with the
Note: In Java, creating a file object does not mean following content.
creating a file. Instead, a file object is an abstract This is a line of text inside the file.
representation of the file or directory pathname Now let's try to read the file using Java FileReader.
(specified in the parenthesis). // importing the FileReader class
import java.io.FileReader;
Java File Operation Methods
Operation Method Package class Main {
To create file createNewFile() java.io.File public static void main(String[] args) {
To read file read() java.io.FileReader
To write file write() java.io.FileWriter char[] array = new char[100];
To delete file delete() java.io.File try {
// Creates a reader using the FileReader
Java create files FileReader input = new FileReader("input.txt");
To create a new file, we can use
the createNewFile() method. It returns // Reads characters
true if a new file is created. input.read(array);
false if the file already exists in the specified location. System.out.println("Data in the file:");
System.out.println(array);
Example: Create a new File
// importing the File class // Closes the reader
import java.io.File; input.close();
}
class Main { catch(Exception e) {
public static void main(String[] args) { e.getStackTrace();
}
// create a file object for the current location }
File file = new File("newFile.txt"); }
Output
Data in the file: // creates a file object
This is a line of text inside the file. File file = new File("file.txt");
In the above example, we have used created an object
of FileReader named input. It is now linked with // deletes the file
the input.txt file. boolean value = file.delete();
FileReader input = new FileReader("input.txt"); if(value) {
To read the data from the input.txt file, we have used System.out.println("The File is deleted.");
the read() method of FileReader. }
else {
Java write to files System.out.println("The File is not deleted.");
To write data to the file, we can use subclasses of }
either OutputStream or Writer. }
}
Example: Write to file using FileWriter
// importing the FileWriter class Output
import java.io.FileWriter; The File is deleted.

class Main { In the above example, we have created an object of


public static void main(String args[]) { File named file. The file now holds the information
about the specified file.
String data = "This is the data in the output file"; File file = new File("file.txt");
try { Here we have used the delete() method to delete the
// Creates a Writer using FileWriter file specified by the object.
FileWriter output = new FileWriter("output.txt");

// Writes string to the file Java Reader Class


output.write(data);
System.out.println("Data is written to the file.");
The Reader class of the java.io package is an abstract
superclass that represents a stream of characters.
// Closes the writer
output.close(); Since Reader is an abstract class, it is not useful by
} itself. However, its subclasses can be used to read data.
catch (Exception e) {
e.getStackTrace(); Subclasses of Reader
} In order to use the functionality of Reader, we can use
} its subclasses. Some of them are:
} BufferedReader
InputStreamReader
Output FileReader
Data is written to the file. StringReader
In the above example, we have created a writer using
the FileWriter class. The writer is linked with
the output.txt file.
FileWriter output = new FileWriter("output.txt");
To write data to the file, we have used
the write() method.
Here when we run the program, the output.txt file is
filled with the following content.
This is the data in the output file.
Java delete files
We can use the delete() method of the File class to
delete the specified file or directory. It returns
true if the file is deleted. Subclasses of Reader
false if the file does not exist. We will learn about all these subclasses in the next
tutorial.
Note: We can only delete empty directories.
Example: Delete a file Create a Reader
import java.io.File; In order to create a Reader, we must import
the java.io.Reader package first. Once we import the
class Main { package, here is how we can create the reader.
public static void main(String[] args) {
// Creates a Reader }
Reader input = new FileReader();
Output
Here, we have created a reader using Is there data in the stream? true
the FileReader class. It is because Reader is an abstract Data in the stream:
class. Hence we cannot create an object of Reader. This is a line of text inside the file.
Note: We can also create readers from other
subclasses of Reader. In the above example, we have created a reader using
the FileReader class. The reader is linked with the
Methods of Reader file input.txt.
The Reader class provides different methods that are
implemented by its subclasses. Here are some of the Reader input = new FileReader("input.txt");
commonly used methods:
ready() - checks if the reader is ready to be read To read data from the input.txt file, we have
read(char[] array) - reads the characters from the implemented these methods.
stream and stores in the specified array
read(char[] array, int start, int length) - reads the input.read(); // to read data from the reader
number of characters equal to length from the stream input.close(); // to close the reader
and stores in the specified array starting from the start
mark() - marks the position in the stream up to which
data has been read
reset() - returns the control to the point in the stream Java Writer Class
where the mark is set
skip() - discards the specified number of characters The Writer class of the java.io package is an abstract
from the stream superclass that represents a stream of characters.

Example: Reader Using FileReader Since Writer is an abstract class, it is not useful by
Here is how we can implement Reader using itself. However, its subclasses can be used to write
the FileReader class. data.
Suppose we have a file named input.txt with the
following content. Subclasses of Writer
This is a line of text inside the file. In order to use the functionality of the Writer, we can
Let's try to read this file using FileReader (a subclass use its subclasses. Some of them are:
of Reader). BufferedWriter
Import java.io.Reader; OutputStreamWriter
import java.io.FileReader; FileWriter
StringWriter
class Main {
public static void main(String[] args) { Create a Writer
In order to create a Writer, we must import
// Creates an array of character the java.io.Writer package first. Once we import the
char[] array = new char[100]; package, here is how we can create the writer.

try { // Creates a Writer


// Creates a reader using the FileReader Writer output = new FileWriter();
Reader input = new FileReader("input.txt");
Here, we have created a writer named output using
// Checks if reader is ready the FileWriter class. It is because the Writer is an
System.out.println("Is there data in the stream? abstract class. Hence we cannot create an object
" + input.ready()); of Writer.

// Reads characters Note: We can also create writers from other subclasses
input.read(array); of the Writer class.
System.out.println("Data in the stream:");
System.out.println(array); Methods of Writer
The Writer class provides different methods that are
// Closes the reader implemented by its subclasses. Here are some of the
input.close(); methods:
} write(char[] array) - writes the characters from the
specified array to the output stream
catch(Exception e) { write(String data) - writes the specified string to the
e.getStackTrace(); writer
} append(char c) - inserts the specified character to the
} current writer
flush() - forces to write all the data present in the writer For example, some characters required 2 bytes to be
to the corresponding destination stored in the storage. To read such data we can use the
close() - closes the writer input stream reader that reads the 2 bytes together and
converts into the corresponding character.
Example: Writer Using FileWriter
Here is how we can implement the Writer using Create an InputStreamReader
the FileWriter class. In order to create an InputStreamReader, we must
import the java.io.InputStreamReader package first.
import java.io.FileWriter; Once we import the package here is how we can create
import java.io.Writer; the input stream reader.
// Creates an InputStream
public class Main { FileInputStream file = new FileInputStream(String
path);
public static void main(String args[]) {
// Creates an InputStreamReader
String data = "This is the data in the output file"; InputStreamReader input = new
InputStreamReader(file);
try { In the above example, we have created
// Creates a Writer using FileWriter an InputStreamReader named input along with
Writer output = new FileWriter("output.txt"); the FileInputStream named file.
Here, the data in the file are stored using some default
character encoding.
// Writes string to the file AD
output.write(data); However, we can specify the type of character
encoding (UTF8 or UTF16) in the file as well.
// Closes the writer // Creates an InputStreamReader specifying the
output.close(); character encoding
} InputStreamReader input = new
InputStreamReader(file, Charset cs);
catch (Exception e) { Here, we have used the Charset class to specify the
e.getStackTrace(); character encoding in the file.
}
} Methods of InputStreamReader
} The InputStreamReader class provides
implementations for different methods present in
In the above example, we have created a writer using the Reader class.
the FileWriter class. The writer is linked with the
file output.txt. read() Method
Writer output = new FileWriter("output.txt"); read() - reads a single character from the reader
read(char[] array) - reads the characters from the
To write data to the output.txt file, we have reader and stores in the specified array
implemented these methods. read(char[] array, int start, int length) - reads the
output.write(); // To write data to the file number of characters equal to length from the reader
output.close(); // To close the writer and stores in the specified array starting from the start
For example, suppose we have a file
When we run the program, the output.txt file is filled named input.txt with the following content.
with the following content.
This is a line of text inside the file.
This is a line of text inside the file.
Let's try to read this file using InputStreamReader.

Java InputStreamReader Class import java.io.InputStreamReader;


import java.io.FileInputStream;
The InputStreamReader class of the java.io package
can be used to convert data in bytes into data in class Main {
characters. public static void main(String[] args) {

It extends the abstract class Reader. // Creates an array of character


char[] array = new char[100];
The InputStreamReader class works with other input
streams. It is also known as a bridge between byte try {
streams and character streams. This is because // Creates a FileInputStream
the InputStreamReader reads bytes from the input FileInputStream file = new
stream as characters. FileInputStream("input.txt");
System.out.println("Character encoding of input1:
// Creates an InputStreamReader " + input1.getEncoding());
InputStreamReader input = new System.out.println("Character encoding of input2:
InputStreamReader(file); " + input2.getEncoding());

// Reads characters from the file // Closes the reader


input.read(array); input1.close();
System.out.println("Data in the stream:"); input2.close();
System.out.println(array); }

// Closes the reader catch(Exception e) {


input.close(); e.getStackTrace();
} }
}
catch(Exception e) { }
e.getStackTrace();
} Output
} The character encoding of input1: Cp1252
} The character encoding of input2: UTF8

Output In the above example, we have created 2 input stream


Data in the stream: reader named input1 and input2.
This is a line of text inside the file. input1 does not specify the character encoding. Hence
the getEncoding() method returns the canonical name
In the above example, we have created an input of the default character encoding.
stream reader using the file input stream. The input input2 specifies the character encoding, UTF8. Hence
stream reader is linked with the file input.txt. the getEncoding() method returns the specified
FileInputStream file = new character encoding.
FileInputStream("input.txt");
InputStreamReader input = new Note: We have used the Charset.forName() method to
InputStreamReader(file); specify the type of character encoding.
To read characters from the file, we have used
the read() method. close() Method
To close the input stream reader, we can use
getEncoding() Method the close() method. Once the close() method is called,
The getEncoding() method can be used to get the type we cannot use the reader to read the data.
of encoding that is used to store data in the input
stream. For example, Other Methods of InputStreamReader
Method Description
import java.io.InputStreamReader; ready() checks if the stream is
import java.nio.charset.Charset; ready to be read
import java.io.FileInputStream; mark() mark the position in
stream up to which data
class Main { has been read
public static void main(String[] args) { reset() returns the control to the
point in the stream where
try { the mark was set
// Creates a FileInputStream
FileInputStream file = new
FileInputStream("input.txt");
Java OutputStreamWriter Class
// Creates an InputStreamReader with default The OutputStreamWriter class of the java.io package
encoding can be used to convert data in character form into data
InputStreamReader input1 = new in bytes form.
InputStreamReader(file);
It extends the abstract class Writer.
// Creates an InputStreamReader specifying the
encoding The OutputStreamWriter class works with other
InputStreamReader input2 = new output streams. It is also known as a bridge between
InputStreamReader(file, Charset.forName("UTF8")); byte streams and character streams. This is because
the OutputStreamWriter converts its characters into
// Returns the character encoding of the input bytes.
stream For example, some characters require 2 bytes to be
stored in the storage. To write such data we can use
the output stream writer that converts the character OutputStreamWriter output = new
into corresponding bytes and stores the bytes together. OutputStreamWriter(file);

Create an OutputStreamWriter // Writes string to the file


In order to create an OutputStreamWriter, we must output.write(data);
import the java.io.OutputStreamWriter package first.
Once we import the package here is how we can create // Closes the writer
the output stream writer. output.close();
}
// Creates an OutputStream
FileOutputStream file = new FileOutputStream(String catch (Exception e) {
path); e.getStackTrace();
}
// Creates an OutputStreamWriter }
OutputStreamWriter output = new }
OutputStreamWriter(file);
In the above example, we have created an output
In the above example, we have created stream reader using the file output stream. The output
an OutputStreamWriter named output along with stream reader is linked with the output.txt file.
the FileOutputStream named file.
AD FileOutputStream file = new
Here, we are using the default character encoding to FileOutputStream("output.txt");
write characters to the output stream. OutputStreamWriter output = new
However, we can specify the type of character OutputStreamWriter(file);
encoding (UTF8 or UTF16) to be used to write data.
To write data to the file, we have used
// Creates an OutputStreamWriter specifying the the write() method.
character encoding Here, when we run the program, the output.txt file is
OutputStreamWriter output = new filled with the following content.
OutputStreamWriter(file, Charset cs); This is a line of text inside the file.

Here, we have used the Charset class to specify the getEncoding() Method
type of character encoding. The getEncoding() method can be used to get the type
of encoding that is used to write data to the output
Methods of OutputStreamWriter stream. For example,
The OutputStreamWriter class provides
implementations for different methods present in import java.io.OutputStreamWriter;
the Writer class. import java.nio.charset.Charset;
import java.io.FileOutputStream;
write() Method
write() - writes a single character to the writer class Main {
write(char[] array) - writes the characters from the public static void main(String[] args) {
specified array to the writer
write(String data) - writes the specified string to the try {
writer // Creates an output stream
FileOutputStream file = new
Example: OutputStreamWriter to write data to a FileOutputStream("output.txt");
File
// Creates an output stream reader with default
import java.io.FileOutputStream; encoding
import java.io.OutputStreamWriter; OutputStreamWriter output1 = new
OutputStreamWriter(file);
public class Main {
// Creates an output stream reader specifying the
public static void main(String args[]) { encoding
OutputStreamWriter output2 = new
String data = "This is a line of text inside the file."; OutputStreamWriter(file, Charset.forName("UTF8"));

try { // Returns the character encoding of the output


// Creates a FileOutputStream stream
FileOutputStream file = new System.out.println("Character encoding of
FileOutputStream("output.txt"); output1: " + output1.getEncoding());
System.out.println("Character encoding of
// Creates an OutputStreamWriter output2: " + output2.getEncoding());
FileReader extends InputStreamReader
// Closes the reader
output1.close(); Create a FileReader
output2.close(); In order to create a file reader, we must import
} the java.io.FileReader package first. Once we import
the package, here is how we can create the file reader.
catch(Exception e) {
e.getStackTrace(); 1. Using the name of the file
}
} FileReader input = new FileReader(String name);
}
Here, we have created a file reader that will be linked
Output to the file specified by the name.
The character encoding of output1: Cp1252
The character encoding of output2: UTF8 2. Using an object of the file

In the above example, we have created 2 output FileReader input = new FileReader(File fileObj);
stream writer named output1 and output2.
output1 does not specify the character encoding. Here, we have created a file reader that will be linked
Hence the getEncoding() method returns the default to the file specified by the object of the file.
character encoding.
output2 specifies the character encoding, UTF8. In the above example, the data in the file are stored
Hence the getEncoding() method returns the specified using some default character encoding.
character encoding. However, since Java 11 we can specify the type of
character encoding (UTF-8 or UTF-16) in the file as
Note: We have used the Charset.forName() method to well.
specify the type of character encoding.
FileReader input = new FileReader(String file,
close() Method Charset cs);
To close the output stream writer, we can use
the close() method. Once the close() method is called, Here, we have used the Charset class to specify the
we cannot use the writer to write the data. character encoding of the file reader.

Other methods of OutputStreamWriter Methods of FileReader


The FileReader class provides implementations for
Method Description different methods present in the Reader class.

flush() forces to write all the data present in the read() Method
writer to the corresponding destination read() - reads a single character from the reader
read(char[] array) - reads the characters from the
append() inserts the specified character to the reader and stores in the specified array
current writer read(char[] array, int start, int length) - reads the
number of characters equal to length from the reader
and stores in the specified array starting from the
position start
Java FileReader Class For example, suppose we have a file
named input.txt with the following content.
The FileReader class of the java.io package can be
used to read data (in characters) from files. This is a line of text inside the file.

It extends the InputSreamReader class. Let's try to read the file using FileReader.

import java.io.FileReader;

class Main {
public static void main(String[] args) {

// Creates an array of character


char[] array = new char[100];

try {
// Creates a reader using the FileReader
FileReader input = new FileReader("input.txt");
// Reads characters
input.read(array); Output
System.out.println("Data in the file: "); The character encoding of input1: Cp1252
System.out.println(array); The character encoding of input2: UTF8

// Closes the reader In the above example, we have created 2 file reader
input.close(); named input1 and input2.
} input1 does not specify the character encoding. Hence
the getEncoding() method returns the default character
catch(Exception e) { encoding.
e.getStackTrace(); input2 specifies the character encoding, UTF8. Hence
} the getEncoding() method returns the specified
} character encoding.
} Note: We have used the Charset.forName() method to
specify the type of character encoding.
Output
Data in the file: close() Method
This is a line of text inside the file. To close the file reader, we can use the close() method.
Once the close() method is called, we cannot use the
In the above example, we have created a file reader reader to read the data.
named input. The file reader is linked with the
file input.txt. Other Methods of FileReader
Method Description
FileInputStream input = new ready() checks if the file reader is ready to be read
FileInputStream("input.txt"); mark() mark the position in file reader up to
which data has been read
To read data from the file, we have used reset() returns the control to the point in the
the read() method. reader where the mark was set
Note: The file input.txt should be present in the
current working directory.
Java FileWriter Class
getEncoding() Method
The getEncoding() method can be used to get the type The FileWriter class of the java.io package can be used
of encoding that is used to store data in the file. For to write data (in characters) to files.
example,
It extends the OutputStreamWriter class.
import java.io.FileReader;
import java.nio.charset.Charset;

class Main {
public static void main(String[] args) {

try {
// Creates a FileReader with default encoding
FileReader input1 = new FileReader("input.txt");

// Creates a FileReader specifying the encoding


FileReader input2 = new FileReader("input.txt",
Charset.forName("UTF8"));

// Returns the character encoding of the file reader Before you learn more about FileWriter, make sure to
System.out.println("Character encoding of input1: know about Java File.
" + input1.getEncoding());
System.out.println("Character encoding of input2: Create a FileWriter
" + input2.getEncoding()); In order to create a file writer, we must import
the Java.io.FileWriter package first. Once we import
// Closes the reader the package, here is how we can create the file writer.
input1.close();
input2.close(); 1. Using the name of the file
} FileWriter output = new FileWriter(String name);
catch(Exception e) { Here, we have created a file writer that will be linked
e.getStackTrace(); to the file specified by the name.
}}}
This is a line of text inside the file.
2. Using an object of the file
FileWriter input = new FileWriter(File fileObj); getEncoding() Method
The getEncoding() method can be used to get the type
Here, we have created a file writer that will be linked of encoding that is used to write data. For example,
to the file specified by the object of the file.
import java.io.FileWriter;
In the above example, the data are stored using some import java.nio.charset.Charset;
default character encoding.
However, since Java 11 we can specify the type of class Main {
character encoding (UTF8 or UTF16) as well. public static void main(String[] args) {
FileWriter input = new FileWriter(String file, Charset
cs); String file = "output.txt";

Here, we have used the Charset class to specify the try {


character encoding of the file writer. // Creates a FileReader with default encoding
FileWriter output1 = new FileWriter(file);
Methods of FileWriter
The FileWriter class provides implementations for // Creates a FileReader specifying the encoding
different methods present in the Writer class. FileWriter output2 = new FileWriter(file,
write() Method Charset.forName("UTF8"));
write() - writes a single character to the writer
write(char[] array) - writes the characters from the // Returns the character encoding of the reader
specified array to the writer System.out.println("Character encoding of
write(String data) - writes the specified string to the output1: " + output1.getEncoding());
writer System.out.println("Character encoding of
output2: " + output2.getEncoding());
Example: FileWriter to write data to a File
import java.io.FileWriter; // Closes the reader
output1.close();
public class Main { output2.close();
}
public static void main(String args[]) {
catch(Exception e) {
String data = "This is the data in the output file"; e.getStackTrace();}}}

try { Output
// Creates a FileWriter The character encoding of output1: Cp1252
FileWriter output = new FileWriter("output.txt"); The character encoding of output2: UTF8

// Writes the string to the file In the above example, we have created 2 file writer
output.write(data); named output1 and output2.
output1 does not specify the character encoding.
// Closes the writer Hence the getEncoding() method returns the default
output.close(); character encoding.
} output2 specifies the character encoding, UTF8.
Hence the getEncoding() method returns the specified
catch (Exception e) { character encoding.
e.getStackTrace(); Note: We have used the Charset.forName() method to
} specify the type of character encoding.
}
} close() Method
To close the file writer, we can use the close() method.
In the above example, we have created a file writer Once the close() method is called, we cannot use the
named output. The output reader is linked with writer to write the data.
the output.txt file.
Other methods of FileWriter
FileWriter output = new FileWriter("output.txt"); Method Description
flush() forces to write all the data present in the
To write data to the file, we have used writer to the corresponding destination
the write() method. append() inserts the specified character to the
Here when we run the program, the output.txt file is current writer
filled with the following content.
Java BufferedReader
read() Method
The BufferedReader class of the java.io package can read() - reads a single character from the internal
be used with other readers to read data (in characters) buffer of the reader
more efficiently. read(char[] array) - reads the characters from the
reader and stores in the specified array
It extends the abstract class Reader. read(char[] array, int start, int length) - reads the
number of characters equal to length from the reader
and stores in the specified array starting from the
position start
For example, suppose we have a file
named input.txt with the following content.

This is a line of text inside the file.

Let's try to read the file using BufferedReader.

import java.io.FileReader;
import java.io.BufferedReader;

Java BufferedReader class Main {


public static void main(String[] args) {
Working of BufferedReader
The BufferedReader maintains an internal buffer of // Creates an array of character
8192 characters. char[] array = new char[100];
During the read operation in BufferedReader, a chunk
of characters is read from the disk and stored in the try {
internal buffer. And from the internal buffer characters // Creates a FileReader
are read individually. FileReader file = new FileReader("input.txt");
Hence, the number of communication to the disk is
reduced. This is why reading characters is faster // Creates a BufferedReader
using BufferedReader. BufferedReader input = new BufferedReader(file);

Create a BufferedReader // Reads characters


In order to create a BufferedReader, we must import input.read(array);
the java.io.BuferedReader package first. Once we System.out.println("Data in the file: ");
import the package, here is how we can create the System.out.println(array);
reader.
// Closes the reader
// Creates a FileReader input.close();
FileReader file = new FileReader(String file); }

// Creates a BufferedReader catch(Exception e) {


BufferedReader buffer = new BufferedReader(file); e.getStackTrace();
}
In the above example, we have created }
a BufferedReader named buffer with }
the FileReader named file.
Here, the internal buffer of the BufferedReader has the Output
default size of 8192 characters. However, we can Data in the file:
specify the size of the internal buffer as well. This is a line of text inside the file.

// Creates a BufferdReader with specified size internal In the above example, we have created a buffered
buffer reader named input. The buffered reader is linked with
BufferedReader buffer = new BufferedReader(file, int the input.txt file.
size); FileReader file = new FileReader("input.txt");
BufferedReader input = new BufferedReader(file);
The buffer will help to read characters from the files
more quickly. Here, we have used the read() method to read an array
of characters from the internal buffer of the buffered
Methods of BufferedReader reader.
The BufferedReader class provides implementations
for different methods present in Reader.
skip() Method data has been read
To discard and skip the specified number of reset() returns the control to the point in the
characters, we can use the skip() method. For reader where the mark was set
example,

Java BufferedWriter Class


import java.io.FileReader;
import java.io.BufferedReader; The BufferedWriter class of the java.io package can be
used with other writers to write data (in characters)
public class Main { more efficiently.

public static void main(String args[]) { It extends the abstract class Writer.

// Creates an array of characters Working of BufferedWriter


char[] array = new char[100]; The BufferedWriter maintains an internal buffer of
8192 characters.
try { During the write operation, the characters are written
// Suppose, the input.txt file contains the to the internal buffer instead of the disk. Once the
following text buffer is filled or the writer is closed, the whole
// This is a line of text inside the file. characters in the buffer are written to the disk.
FileReader file = new FileReader("input.txt"); Hence, the number of communication to the disk is
reduced. This is why writing characters is faster
// Creates a BufferedReader using BufferedWriter.
BufferedReader input = new BufferedReader(file);
Create a BufferedWriter
// Skips the 5 characters In order to create a BufferedWriter, we must import
input.skip(5); the java.io.BufferedWriter package first. Once we
import the package here is how we can create the
// Reads the characters buffered writer.
input.read(array);
// Creates a FileWriter
System.out.println("Data after skipping 5 FileWriter file = new FileWriter(String name);
characters:");
System.out.println(array); // Creates a BufferedWriter
BufferedWriter buffer = new BufferedWriter(file);
// closes the reader
input.close(); In the above example, we have created
} a BufferedWriter named buffer with
the FileWriter named file.
catch (Exception e) { AD
e.getStackTrace(); Here, the internal buffer of the BufferedWriter has the
} default size of 8192 characters. However, we can
} specify the size of the internal buffer as well.
}
// Creates a BufferedWriter with specified size
Output internal buffer
Data after skipping 5 characters: BufferedWriter buffer = new BufferedWriter(file, int
is a line of text inside the file. size);

In the above example, we have used the skip() method The buffer will help to write characters to the files
to skip 5 characters from the file reader. Hence, the more efficiently.
characters 'T', 'h', 'i', 's' and ' ' are skipped from the
original file. Methods of BufferedWriter
The BufferedWriter class provides implementations
close() Method for different methods present in Writer.
To close the buffered reader, we can use
the close() method. Once the close() method is called, write() Method
we cannot use the reader to read the data. write() - writes a single character to the internal buffer
of the writer
Other Methods of BufferedReader write(char[] array) - writes the characters from the
Method Description specified array to the writer
ready() checks if the file reader is ready to be read write(String data) - writes the specified string to the
mark() mark the position in reader up to which writer
Example: BufferedWriter to write data to a File
import java.io.FileWriter; // Flushes data to the destination
import java.io.BufferedWriter; output.flush();
System.out.println("Data is flushed to the file.");
public class Main {
output.close();
public static void main(String args[]) { }

String data = "This is the data in the output file"; catch(Exception e) {


e.getStackTrace();
try { }
// Creates a FileWriter }
FileWriter file = new FileWriter("output.txt"); }
Output
// Creates a BufferedWriter Data is flushed to the file.
BufferedWriter output = new BufferedWriter(file); When we run the program, the file output.txt is filled
with the text represented by the string data.
// Writes the string to the file
output.write(data); close() Method
To close the buffered writer, we can use
// Closes the writer the close() method. Once the close() method is called,
output.close(); we cannot use the writer to write the data.
}
Other Methods of BufferedWriter
catch (Exception e) { Method Description
e.getStackTrace(); newLine() inserts a new line to the writer
} append() inserts the specified character to the
} current writer
}
In the above example, we have created a buffered
writer named output along with FileWriter. The
Java StringReader Class
buffered writer is linked with the output.txt file.
FileWriter file = new FileWriter("output.txt");
The StringReader class of the java.io package can be
BufferedWriter output = new BufferedWriter(file);
used to read data (in characters) from strings.
To write data to the file, we have used
the write() method. It extends the abstract class Reader.
Here when we run the program, the output.txt file is
filled with the following content.
This is a line of text inside the file.

flush() Method
To clear the internal buffer, we can use
the flush() method. This method forces the writer to
write all data present in the buffer to the destination
file.
For example, suppose we have an empty file
named output.txt.
import java.io.FileWriter;
import java.io.BufferedWriter;
Note: In StringReader, the specified string acts as a
public class Main { source from where characters are read individually.
public static void main(String[] args) {
Create a StringReader
String data = "This is a demo of the flush method"; In order to create a StringReader, we must import
the java.io.StringReader package first. Once we import
try { the package here is how we can create the string
// Creates a FileWriter reader.
FileWriter file = new FileWriter(" flush.txt");
// Creates a StringReader
// Creates a BufferedWriter StringReader input = new StringReader(String data);
BufferedWriter output = new BufferedWriter(file);
Here, we have created a StringReader that reads
// Writes data to the file characters from the specified string named data.
output.write(data);
Methods of StringReader String data = "This is the text read from
The StringReader class provides implementations for StringReader";
different methods present in the Reader class. System.out.println("Original data: " + data);
read() Method
read() - reads a single character from the string reader // Create a character array
read(char[] array) - reads the characters from the char[] array = new char[100];
reader and stores in the specified array
read(char[] array, int start, int length) - reads the try {
number of characters equal to length from the reader // Create a StringReader
and stores in the specified array starting from the StringReader input = new StringReader(data);
position start
// Use the skip() method
Example: Java StringReader input.skip(5);
import java.io.StringReader;
//Use the read method
public class Main { input.read(array);
public static void main(String[] args) { System.out.println("Data after skipping 5
characters:");
String data = "This is the text read from System.out.println(array);
StringReader.";
input.close();
// Create a character array }
char[] array = new char[100];
catch(Exception e) {
try { e.getStackTrace();
// Create a StringReader }
StringReader input = new StringReader(data); }
}
//Use the read method
input.read(array); Output
System.out.println("Data read from the string:"); Original data: This is the text read from the
System.out.println(array); StringReader
Data after skipping 5 characters:
input.close(); is the text read from the StringReader
} In the above example, we have used the skip() method
catch(Exception e) { to skip 5 characters from the string reader. Hence, the
e.getStackTrace(); characters 'T', 'h', 'i', 's' and ' ' are skipped from the
} original string reader.
}
} close() Method
To close the string reader, we can use
Output the close() method. Once the close() method is called,
Data read from the string: we cannot use the reader to read data from the string.
This is the text read from StringReader.
In the above example, we have created a string reader Other Methods of StringReader
named input. The string reader is linked to the Method Description
string data. ready() checks if the string reader is ready to be
String data = "This is a text in the string."; read
StringReader input = new StringReader(data); mark() marks the position in reader up to
which data has been read
To read data from the string, we have used reset() returns the control to the point in the
the read() method. reader where the mark was set
Here, the method reads an array of characters from the
reader and stores in the specified array.
Java StringWriter Class
skip() Method
To discard and skip the specified number of The StringWriter class of the java.io package can be
characters, we can use the skip() method. For used to write data (in characters) to the string buffer.
example,
import java.io.StringReader; It extends the abstract class Writer.
public class Main {
public static void main(String[] args) {
// Prints the string writer
System.out.println("Data in the StringWriter: " +
output);

output.close();
}

catch(Exception e) {
e.getStackTrace();
}
}
}
Note: In Java, string buffer is considered as a mutable
string. That is, we can modify the string buffer. To Output
convert from string buffer to string, we can use Data in the StringWriter: This is the text in the string.
the toString() method.
In the above example, we have created a string writer
Create a StringWriter named output.
In order to create a StringWriter, we must import
the java.io.StringWriter package first. Once we import StringWriter output = new StringWriter();
the package here is how we can create the string
writer. We then use the write() method to write the string data
to the string buffer.
// Creates a StringWriter
StringWriter output = new StringWriter(); Note: We have used the toString() method to get the
output data from string buffer in string form.
Here, we have created the string writer with default
string buffer capacity. However, we can specify the Access Data from StringBuffer
string buffer capacity as well. getBuffer() - returns the data present in the string
// Creates a StringWriter with specified string buffer buffer
capacity toString() - returns the data present in the string buffer
StringWriter output = new StringWriter(int size); as a string
For example,
Here, the size specifies the capacity of the string buffer.
import java.io.StringWriter;
Methods of StringWriter
The StringWriter class provides implementations for public class Main {
different methods present in the Writer class. public static void main(String[] args) {

write() Method String data = "This is the original data";


write() - writes a single character to the string writer
write(char[] array) - writes the characters from the try {
specified array to the writer // Create a StringWriter with default string buffer
write(String data) - writes the specified string to the capacity
writer StringWriter output = new StringWriter();

Example: Java StringWriter // Writes data to the string buffer


output.write(data);
import java.io.StringWriter;
// Returns the string buffer
public class Main { StringBuffer stringBuffer = output.getBuffer();
public static void main(String[] args) { System.out.println("StringBuffer: " + stringBuffer);

String data = "This is the text in the string."; // Returns the string buffer in string form
String string = output.toString();
try { System.out.println("String: " + string);
// Create a StringWriter with default string buffer
capacity output.close();
StringWriter output = new StringWriter(); }

// Writes data to the string buffer catch(Exception e) {


output.write(data); e.getStackTrace();
}
}
}
1. Using other writers
Output
StringBuffer: This is the original data // Creates a FileWriter
String: This is the original data FileWriter file = new FileWriter("output.txt");

Here we have used the getBuffer() method to get the // Creates a PrintWriter
data present in the string buffer. And also the PrintWriter output = new PrintWriter(file, autoFlush);
method toString() returns the data present in the string
buffer as a string. Here,
we have created a print writer that will write data to
close() Method the file represented by the FileWriter
To close the string writer, we can use autoFlush is an optional parameter that specifies
the close() method. whether to perform auto flushing or not
However, the close() method has no effect in
the StringWriter class. We can use the methods of this 2. Using other output streams
class even after the close() method is called.
// Creates a FileOutputStream
Other methods of StringWriter FileOutputStream file = new
FileOutputStream("output.txt");
Method Description
flush() forces to write all the data present in the // Creates a PrintWriter
writer to the string buffer PrintWriter output = new PrintWriter(file, autoFlush);
append() inserts the specified character to the
current writer Here,
we have created a print writer that will write data to
the file represented by the FileOutputStream
Java PrintWriter Class the autoFlush is an optional parameter that specifies
whether to perform auto flushing or not
The PrintWriter class of the java.io package can be
used to write output data in a commonly readable 3. Using filename
form (text).
// Creates a PrintWriter
It extends the abstract class Writer. PrintWriter output = new PrintWriter(String file,
boolean autoFlush);

Here,
we have created a print writer that will write data to
the specified file
the autoFlush is an optional boolean parameter that
specifies whether to perform auto flushing or nor
Note: In all the above cases, the PrintWriter writes
data to the file using some default character encoding.
However, we can specify the character encoding
(UTF8 or UTF16) as well.

// Creates a PrintWriter using some character


encoding
Working of PrintWriter
PrintWriter output = new PrintWriter(String file,
Unlike other writers, PrintWriter converts
boolean autoFlush, Charset cs);
the primitive data(int, float, char, etc.) into the text
format. It then writes that formatted data to the writer.
Here, we have used the Charset class to specify the
Also, the PrintWriter class does not throw any
character encoding.
input/output exception. Instead, we need to use
the checkError() method to find any error in it.
Methods of PrintWriter
Note: The PrintWriter class also has a feature of auto
The PrintWriter class provides various methods that
flushing. This means it forces the writer to write all
allow us to print data to the output.
data to the destination if one of
the println() or printf() methods is called.
print() Method
print() - prints the specified data to the writer
Create a PrintWriter
println() - prints the data to the writer along with a
In order to create a print writer, we must import
new line character at the end
the java.io.PrintWriter package first. Once we import
For example,
the package here is how we can create the print writer.
import java.io.PrintWriter; }
catch(Exception e) {
class Main { e.getStackTrace();
public static void main(String[] args) { }
}
String data = "This is a text inside the file."; }

try { In the above example, we have created a print writer


PrintWriter output = new named output. The print writer is linked with the
PrintWriter("output.txt"); file output.txt.

output.print(data); PrintWriter output = new PrintWriter("output.txt");


output.close();
} To print the formatted text to the file, we have used
catch(Exception e) { the printf() method.
e.getStackTrace(); Here when we run the program, the output.txt file is
} filled with the following content.
}
} I am 25 years old.

In the above example, we have created a print writer Other Methods Of PrintWriter
named output. This print writer is linked with the Method Description
file output.txt. close() closes the print writer
checkError() checks if there is an error
PrintWriter output = new PrintWriter("output.txt"); in the writer and returns a
boolean result
To print data to the file, we have used append() appends the specified data
the print() method. to the writer
Here when we run the program, the output.txt file is
filled with the following content.

This is a text inside the file. Additional Topics


printf() Method
The printf() method can be used to print the formatted
string. It includes 2 parameters: formatted string and
arguments. For example,
Java Keywords and Identifiers
Java Keywords
printf("I am %d years old", 25);
Keywords are predefined, reserved words used in Java
Here,
programming that have special meanings to the
I am %d years old is a formatted string
compiler. For example:
%d is integer data in the formatted string
int score;
25 is an argument
Here, int is a keyword. It indicates that the
The formatted string includes both text and data. And,
variable score is of integer type (32-bit signed two's
the arguments replace the data inside the formatted
complement integer).
string.
You cannot use keywords like int, for, class, etc as
Hence the %d is replaced by 25.
variable name (or identifiers) as they are part of the
Java programming language syntax. Here's the
Example: printf() Method using PrintWriter complete list of all keywords in Java programming.
import java.io.PrintWriter;
Java Keywords List
class Main { abstract assert boolea break byte
public static void main(String[] args) { n
case catch char class const
try { continue default do double else
PrintWriter output = new enum extends final finally float
PrintWriter("output.txt"); for goto if implemen impor
ts t
int age = 25; instance int interfac long native
of e
output.printf("I am %d years old.", age); new package private protected public
output.close();
return short static strictfp super
Java Operator Precedence
switch synchroniz this throw throw
Operators Precedence
ed s
postfix increment and ++ --
transient try void volatile while
decrement
prefix increment and ++ -- + - ~ !
decrement, and unary
Java identifiers
multiplicative */%
Identifiers are the name given to variables, classes,
additive +-
methods, etc. Consider the above code;
int score; shift << >> >>>
Here, score is a variable (an identifier). You cannot relational < > <= >= instanceof
use keywords as variable names. It's because keywords equality == !=
have predefined meanings. For example, bitwise AND &
int float; bitwise exclusive OR ^
The above code is wrong. It's because float is a bitwise inclusive OR |
keyword and cannot be used as a variable name. logical AND &&
logical OR ||
Rules for Naming an Identifier ternary ?:
- Identifiers cannot be a keyword. assignment = += -= *= /= %=
- Identifiers are case-sensitive. &= ^= |= <<= >>=
- It can have a sequence of letters and >>>=
digits. However, it must begin with a >>>=
letter, $ or _. The first letter of an
identifier cannot be a digit. Example: Operator Precedence
- It's a convention to start an identifier class Precedence {
with a letter rather and $ or _. public static void main(String[] args) {
- Whitespaces are not allowed.
- Similarly, you cannot use symbols int a = 10, b = 5, c = 1, result;
such as @, #, and so on. result = a-++c-++b;

Here are some valid identifiers: System.out.println(result);


- Score }
- Level }
- highestScore
- number1 Output:
- convertToString 2

Here are some invalid identifiers: The operator precedence of prefix ++ is higher than
- class that of - subtraction operator. Hence,
- float result = a-++c-++b;
- 1number
- highest Score is equivalent to
- @pple result = a-(++c)-(++b);

When dealing with multiple operators and operands in


a single expression, you can use parentheses like in the
Java Operator Precedence above example for clarity. The expression inside the
parentheses is evaluated first.
Now, take a look at the statement below:

int myInt = 12 - 4 * 2; Associativity of Operators in Java


What will be the value of myInt? Will it be (12 - 4)*2, If an expression has two operators with similar
that is, 16? Or it will be 12 - (4 * 2), that is, 4? precedence, the expression is evaluated according to
When two operators share a common operand, 4 in its associativity (either left to right, or right to left).
this case, the operator with the highest precedence is Let's take an example.
operated first. a = b = c;
In Java, the precedence of * is higher than that of -. Here, the value of c is assigned to variable b. Then the
Hence, the multiplication is performed before value of b is assigned of variable a. Why? It's because
subtraction, and the value of myInt will be 4. the associativity of = operator is from right to left.
The table below shows the associativity of Java
Operator Precedence Table operators along with their associativity.
The table below lists the precedence of operators in
Java; higher it appears in the table, the higher its Java Operator Precedence and Associativity
precedence. Operators Precedence Associativity
postfix ++ -- left to right 0 0 0
increment and 0 1 1
decrement 1 0 1
prefix increment ++ -- + - ~ ! right to left 1 1 1
and decrement,
and unary The above table is known as the "Truth Table" for the
multiplicative */% left to right bitwise OR operator.
additive +- left to right Let's look at the bitwise OR operation of two integers
shift << >> >>> left to right 12 and 25.
relational < > <= >= left to right
instanceof 12 = 00001100 (In Binary)
equality == != left to right 25 = 00011001 (In Binary)
bitwise AND & left to right
bitwise ^ left to right Bitwise OR Operation of 12 and 25
exclusive OR 00001100
bitwise inclusive | left to right | 00011001
OR ____________
logical AND && left to right 00011101 = 29 (In Decimal)
logical OR || left to right
ternary ?: right to left Example 1: Bitwise OR
assignment = += -= *= /= right to left
%= class Main {
public static void main(String[] args) {
&= ^= |= <<=
>>= >>>= int number1 = 12, number2 = 25, result;

>>= >>>= // bitwise OR between 12 and 25


result = number1 | number2;
System.out.println(result); // prints 29
You don't need to memorize everything here. Most of }
the time, the precedence and associativity of operators }
makes sense in itself. You can always come back to
this article for reference when in doubt. Also, you can 2. Java Bitwise AND Operator
use parenthesis if you think it makes your code easier The bitwise AND & operator returns 1 if and only if
to understand. both the operands are 1. Otherwise, it returns 0.
The following table demonstrates the working of the
bitwise AND operator. Let a and b be two operands
that can only take binary values i.e. 1 and 0.
Java Bitwise and Shift Operators a b a&b
In Java, bitwise operators perform operations on 0 0 0
integer data at the individual bit-level. Here, the 0 1 0
integer data includes byte, short, int, and long types of 1 0 0
data. 1 1 1

There are 7 operators to perform bit-level operations in Let's take a look at the bitwise AND operation of two
Java. integers 12 and 25.

Operator Description 12 = 00001100 (In Binary)


| Bitwise OR 25 = 00011001 (In Binary)
& Bitwise AND
^ Bitwise XOR // Bitwise AND Operation of 12 and 25
~ Bitwise Complement 00001100
<< Left Shift & 00011001
>> Signed Right Shift ____________
>>> Unsigned Right Shift 00001000 = 8 (In Decimal)

1. Java Bitwise OR Operator


The bitwise OR | operator returns 1 if at least one of Example 2: Bitwise AND
the operands is 1. Otherwise, it returns 0. class Main {
The following truth table demonstrates the working of public static void main(String[] args) {
the bitwise OR operator. Let a and b be two operands
that can only take binary values i.e. 1 or 0. int number1 = 12, number2 = 25, result;
a b a|b
// bitwise AND between 12 and 25 Consider an integer 35. As per the rule, the bitwise
result = number1 & number2; complement of 35 should be -(35 + 1) = -36. Now let's
System.out.println(result); // prints 8 see if we get the correct answer or not.
}
} 35 = 00100011 (In Binary)

3. Java Bitwise XOR Operator // using bitwise complement operator


The bitwise XOR ^ operator returns 1 if and only if ~ 00100011
one of the operands is 1. However, if both the __________
operands are 0 or if both are 1, then the result is 0. 11011100
The following truth table demonstrates the working of
the bitwise XOR operator. Let a and b be two In the above example, we get that the bitwise
operands that can only take binary values i.e. 1 or 0. complement of 00100011 (35) is 11011100. Here, if we
convert the result into decimal we get 220.
a b a^b However, it is important to note that we cannot
0 0 0 directly convert the result into decimal and get the
0 1 1 desired output. This is because the binary
1 0 1 result 11011100 is also equivalent to -36.
1 1 0 To understand this we first need to calculate the binary
output of -36.
Let's look at the bitwise XOR operation of two
integers 12 and 25. 2's Complement
12 = 00001100 (In Binary) In binary arithmetic, we can calculate the binary
25 = 00011001 (In Binary) negative of an integer using 2's complement.
1's complement changes 0 to 1 and 1 to 0. And, if we
// Bitwise XOR Operation of 12 and 25 add 1 to the result of the 1's complement, we get the
00001100 2's complement of the original number. For example,
^ 00011001
____________ // compute the 2's complement of 36
00010101 = 21 (In Decimal) 36 = 00100100 (In Binary)

Example 4: Bitwise XOR 1's complement = 11011011


class Main {
public static void main(String[] args) { 2's complement:
11011011
int number1 = 12, number2 = 25, result; + 1
_________
// bitwise XOR between 12 and 25 11011100
result = number1 ^ number2;
System.out.println(result); // prints 21 Here, we can see the 2's complement of 36 (i.e. -36)
} is 11011100. This value is equivalent to the bitwise
} complement of 35.
Hence, we can say that the bitwise complement
4. Java Bitwise Complement Operator of 35 is -(35 + 1) = -36.
The bitwise complement operator is a unary operator
(works with only one operand). It is denoted by ~. Example 3: Bitwise Complement
AD
It changes binary digits 1 to 0 and 0 to 1. class Main {
public static void main(String[] args) {

int number = 35, result;

// bitwise complement of 35
result = ~number;
System.out.println(result); // prints -36
}
}

Java Bitwise Java Shift Operators


Complement Operator There are three types of shift operators in Java:
It is important to note that the bitwise complement of Signed Left Shift (<<)
any integer N is equal to - (N + 1). For example, Signed Right Shift (>>)
Unsigned Right Shift (>>>)
5. Java Left Shift Operator +1
The left shift operator shifts all bits towards the left by _______
a certain number of specified bits. It is denoted by <<. 1000

Signed bit = 1

// perform 2 bit right shift


8 >> 2:
1000 >> 2 = 1110 (equivalent to -2)

Here, we have used the signed bit 1 to fill the leftmost


Java 1 bit Left Shift Operator bits.
As we can see from the image above, we have a 4-digit
number. When we perform a 1 bit left shift operation Example 6: Signed Right Shift Operator
on it, each individual bit is shifted to the left by 1 bit.
As a result, the left-most bit (most-significant) is class Main {
discarded and the right-most position(least-significant) public static void main(String[] args) {
remains vacant. This vacancy is filled with 0s.
int number1 = 8;
Example 5: Left Shift Operators int number2 = -8;

class Main { // 2 bit signed right shift


System.out.println(number1 >> 2); // prints 2
public static void main(String[] args) { System.out.println(number2 >> 2); // prints -2
}
int number = 2; }

7. Java Unsigned Right Shift Operator


// 2 bit left shift operation Java also provides an unsigned right shift. It is denoted
int result = number << 2; by >>>.
System.out.println(result); // prints 8 Here, the vacant leftmost position is filled
} with 0 instead of the sign bit. For example,
} // unsigned right shift of 8
8 = 1000

5. Java Signed Right Shift Operator 8 >>> 2 = 0010


The signed right shift operator shifts all bits towards
the right by a certain number of specified bits. It is // unsigned right shift of -8
denoted by >>. -8 = 1000 (see calculation above)
When we shift any number to the right, the least
significant bits (rightmost) are discarded and the most -8 >>> 2 = 0010
significant position (leftmost) is filled with the sign bit.
For example, Example 7: UnSigned Right Shift

// right shift of 8 class Main {


8 = 1000 (In Binary) public static void main(String[] args) {

// perform 2 bit right shift int number1 = 8;


8 >> 2: int number2 = -8;
1000 >> 2 = 0010 (equivalent to 2)
// 2 bit signed right shift
Here, we are performing the right shift of 8 (i.e. sign is System.out.println(number1 >>> 2); // prints 2
positive). Hence, there no sign bit. So the leftmost bits System.out.println(number2 >>> 2); // prints
are filled with 0 (represents positive sign). 1073741822
// right shift of -8 }
8 = 1000 (In Binary) }

1's complement = 0111 As we can see the signed and unsigned right shift
operator returns different results for negative bits.
2's complement:

0111 Java Scanner Class


The Scanner class of the java.util package is used to
read input data from different sources like input Java Scanner Methods to Take Input
streams, files, etc. Let's take an example. The Scanner class provides various methods that allow
us to read inputs of different types.

Example 1: Read a Line of Text Using Scanner Method Description


import java.util.Scanner; nextInt() reads an int value from
the user
class Main { nextFloat() reads a float value form
public static void main(String[] args) { the user
nextBoolean() reads a boolean value
// creates an object of Scanner from the user
Scanner input = new Scanner(System.in); nextLine() reads a line of text from
the user
System.out.print("Enter your name: "); next() reads a word from the
user
// takes input from the keyboard nextByte() reads a byte value from
String name = input.nextLine(); the user
nextDouble() reads a double value from
// prints the name the user
System.out.println("My name is " + name); nextShort() reads a short value from
the user
// closes the scanner
nextLong() reads a long value from
input.close();
the user
}
}
Example 2: Java Scanner nextInt()
Output
Enter your name: Kelvin
import java.util.Scanner;
My name is Kelvin
class Main {
In the above example, notice the line
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
Here, we have created
// creates a Scanner object
an object of Scanner named input.
Scanner input = new Scanner(System.in);
The System.in parameter is used to take input from
the standard input. It works just like taking inputs
System.out.println("Enter an integer: ");
from the keyboard.
We have then used the nextLine() method of
// reads an int value
the Scanner class to read a line of text from the user.
int data1 = input.nextInt();
Now that you have some idea about Scanner, let's
explore more about it.
System.out.println("Using nextInt(): " + data1);
Import Scanner Class
input.close();
As we can see from the above example, we need to
}
import the java.util.Scanner package before we can
}
use the Scanner class.
import java.util.Scanner;
Output
Enter an integer:
Create a Scanner Object in Java
22
Once we import the package, here is how we can
Using nextInt(): 22
create Scanner objects.
// read input from the input stream
In the above example, we have used
Scanner sc1 = new Scanner(InputStream input);
the nextInt() method to read an integer value.
// read input from files
Example 3: Java Scanner nextDouble()
Scanner sc2 = new Scanner(File file);
import java.util.Scanner;
// read input from a string
class Main {
Scanner sc3 = new Scanner(String str);
public static void main(String[] args) {
Here, we have created objects of the Scanner class that
// creates an object of Scanner
will read input from InputStream, File,
Scanner input = new Scanner(System.in);
and String respectively.
System.out.print("Enter Double value: ");
input.close();
// reads the double value }
double value = input.nextDouble(); }
System.out.println("Using nextDouble(): " + value);
Output
input.close(); Enter your name: Jonny Walker
} Using nextLine(): Jonny Walker
}
In the first example, we have used
Output the nextLine() method to read a string from the user.
Enter Double value: 33.33 Unlike next(), the nextLine() method reads the entire
Using nextDouble(): 33.33 line of input including spaces. The method is
terminated when it encounters a next line
In the above example, we have used character, \n.
the nextDouble() method to read a floating-point
value. Java Scanner with BigInteger and BigDecimal
Java scanner can also be used to read the big integer
Example 4: Java Scanner next() and big decimal numbers.
nextBigInteger() - reads the big integer value from the
user
import java.util.Scanner; nextBigDecimal() - reads the big decimal value from
the user
class Main {
public static void main(String[] args) { Example 4: Read BigInteger and BigDecimal

// creates an object of Scanner import java.math.BigDecimal;


Scanner input = new Scanner(System.in); import java.math.BigInteger;
System.out.print("Enter your name: "); import java.util.Scanner;

// reads the entire word class Main {


String value = input.next(); public static void main(String[] args) {
System.out.println("Using next(): " + value);
// creates an object of Scanner
input.close(); Scanner input = new Scanner(System.in);
} System.out.print("Enter a big integer: ");
}
// reads the big integer
Output BigInteger value1 = input.nextBigInteger();
Enter your name: Jonny Walker System.out.println("Using nextBigInteger(): " +
Using next(): Jonny value1);

In the above example, we have used the next() method System.out.print("Enter a big decimal: ");
to read a string from the user.
Here, we have provided the full name. However, // reads the big decimal
the next() method only reads the first name. BigDecimal value2 = input.nextBigDecimal();
This is because the next() method reads input up to System.out.println("Using nextBigDecimal(): " +
the whitespace character. Once the whitespace is value2);
encountered, it returns the string (excluding the
whitespace). input.close();
}
Example 5: Java Scanner nextLine() }
import java.util.Scanner;
Output
class Main { Enter a big integer: 987654321
public static void main(String[] args) { Using nextBigInteger(): 987654321
Enter a big decimal: 9.55555
// creates an object of Scanner Using nextBigDecimal(): 9.55555
Scanner input = new Scanner(System.in);
System.out.print("Enter your name: "); In the above example, we have used
the java.math.BigInteger and java.math.BigDecimal p
// reads the entire line ackage to
String value = input.nextLine(); read BigInteger and BigDecimal respectively.
System.out.println("Using nextLine(): " + value);
Working of Java Scanner Narrowing Type Casting
The Scanner class reads an entire line and divides the In Narrowing Type Casting, we manually convert one
line into tokens. Tokens are small elements that have data type into another using the parenthesis.
some meaning to the Java compiler. For example, Example: Converting double into an int
Suppose there is an input string:
He is 22 class Main {
In this case, the scanner object will read the entire line public static void main(String[] args) {
and divides the string into tokens: "He", "is" and "22". // create double type variable
The object then iterates over each token and reads double num = 10.99;
each token using its different methods. System.out.println("The double value: " + num);

Note: By default, whitespace is used to divide tokens. // convert into int type
int data = (int)num;
System.out.println("The integer value: " + data);
Java Type Casting }
}
Type Casting
The process of converting the value of one data type Output
(int, float, double, etc.) to another data type is known The double value: 10.99
as typecasting. The integer value: 10
In Java, there are 13 types of type conversion.
However, in this tutorial, we will only focus on the In the above example, we are assigning
major 2 types. the double type variable named num to an int type
1. Widening Type Casting variable named data.
2. Narrowing Type Casting Notice the line,
int data = (int)num;
Widening Type Casting Here, the int keyword inside the parenthesis indicates
In Widening Type Casting, Java automatically that that the num variable is converted into
converts one data type to another data type. the int type.
In the case of Narrowing Type Casting, the higher
Example: Converting int to double data types (having larger size) are converted into lower
data types (having smaller size). Hence there is the loss
class Main { of data. This is why this type of conversion does not
public static void main(String[] args) { happen automatically.
// create int type variable
int num = 10; Note: This is also known as Explicit Type Casting.
System.out.println("The integer value: " + num);
Let's see some of the examples of other type
// convert into double type conversions in Java.
double data = num;
System.out.println("The double value: " + data); Example 1: Type conversion from int to String
}
} class Main {
public static void main(String[] args) {
Output // create int type variable
The integer value: 10 int num = 10;
The double value: 10.0 System.out.println("The integer value is: " + num);

In the above example, we are assigning the int type // converts int to string type
variable named num to a double type variable String data = String.valueOf(num);
named data. System.out.println("The string value is: " + data);
Here, the Java first converts the int type data into }
the double type. And then assign it to }
the double variable.
Output
In the case of Widening Type Casting, the lower data The integer value is: 10
type (having smaller size) is converted into the higher The string value is: 10
data type (having larger size). Hence there is no loss in
data. This is why this type of conversion happens In the above program, notice the line
automatically. String data = String.valueOf(num);
Here, we have used the valueOf() method of the Java
Note: This is also known as Implicit Type Casting. String class to convert the int type variable into a
string.
Example 2: Type conversion from String to int System.out.println("An object of Integer is
created.");
class Main { }
public static void main(String[] args) {
// create string type variable if(bObj instanceof Double) {
String data = "10"; System.out.println("An object of Double is
System.out.println("The string value is: " + data); created.");
}
// convert string variable to int }
int num = Integer.parseInt(data); }
System.out.println("The integer value is: " + num);
} Output
} An object of Integer is created.

Output An object of Double is created.


The string value is: 10 In the above example, we have used
The integer value is: 10 the valueOf() method to convert the primitive types
In the above example, notice the line into objects.
int num = Integer.parseInt(data); Here, we have used the instanceof operator to check
Here, we have used the parseInt() method of the whether the generated objects are
Java Integer class to convert a string type variable into of Integer or Double type or not.
an int variable. However, the Java compiler can directly convert the
primitive types into corresponding objects. For
Note: If the string variable cannot be converted into example,
the integer variable then an exception int a = 5;
named NumberFormatException occurs. // converts into object
Integer aObj = a;
Java Wrapper Class
double b = 5.6;
The wrapper classes in Java are used to // converts into object
convert primitive types (int, char, float, etc) into Double bObj = b;
corresponding objects.
This process is known as auto-boxing.
Each of the 8 primitive types has corresponding
wrapper classes. Note: We can also convert primitive types into
wrapper objects using Wrapper class constructors. But
Primitive Type Wrapper Class the use of constructors is discarded after Java 9.
byte Byte
boolean Boolean Wrapper Objects into Primitive Types
char Character To convert objects into the primitive types, we can use
double Double the corresponding value methods
float Float (intValue(), doubleValue(), etc) present in each
wrapper class.
int Integer
long Long
Example 2: Wrapper Objects into Primitive Types
short Short
class Main {
public static void main(String[] args) {
Convert Primitive Type to Wrapper Objects
We can also use the valueOf() method to convert // creates objects of wrapper class
primitive types into corresponding objects. Integer aObj = Integer.valueOf(23);
Double bObj = Double.valueOf(5.55);
Example 1: Primitive Types to Wrapper Objects
class Main { // converts into primitive types
public static void main(String[] args) { int a = aObj.intValue();
double b = bObj.doubleValue();
// create primitive types
int a = 5; System.out.println("The value of a: " + a);
double b = 5.65; System.out.println("The value of b: " + b);
}
//converts into wrapper objects }
Integer aObj = Integer.valueOf(a);
Double bObj = Double.valueOf(b); Output
The value of a: 23
if(aObj instanceof Integer) { The value of b: 5.55
Example 1: Java Autoboxing
In the above example, we have used
the intValue() and doubleValue() method to convert
the Integer and Double objects into corresponding import java.util.ArrayList;
primitive types.
However, the Java compiler can automatically convert class Main {
objects into corresponding primitive types. For public static void main(String[] args) {
example,
Integer aObj = Integer.valueOf(2); ArrayList<Integer> list = new ArrayList<>();
// converts into int type
int a = aObj; //autoboxing
list.add(5);
Double bObj = Double.valueOf(5.55); list.add(6);
// converts into double type
double b = bObj; System.out.println("ArrayList: " + list);
}
This process is known as unboxing. }

Advantages of Wrapper Classes Output


In Java, sometimes we might need to use objects ArrayList: [5, 6]
instead of primitive data types. For example, while
working with collections. In the above example, we have created an array list of
// error Integer type. Hence the array list can only hold objects
ArrayList<int> list = new ArrayList<>(); of Integer type.
Notice the line,
// runs perfectly list.add(5);
ArrayList<Integer> list = new ArrayList<>(); Here, we are passing primitive type value. However,
due to autoboxing, the primitive value is automatically
In such cases, wrapper classes help us to use primitive converted into an Integer object and stored in the array
data types as objects. list.
We can store the null value in wrapper objects. For
example, Java Unboxing - Wrapper Objects to Primitive
Types
// generates an error
int a = null; In unboxing, the Java compiler automatically converts
wrapper class objects into their corresponding
// runs perfectly primitive types. For example,
Integer a = null; // autoboxing
Integer aObj = 56;
Note: Primitive types are more efficient than
corresponding objects. Hence, when efficiency is the // unboxing
requirement, it is always recommended primitive int a = aObj;
types.
Like autoboxing, unboxing can also be used with Java
collections.

Example 2: Java Unboxing


Java autoboxing and unboxing import java.util.ArrayList;

Java Autoboxing - Primitive Type to Wrapper class Main {


Object public static void main(String[] args) {

In autoboxing, the Java compiler automatically ArrayList<Integer> list = new ArrayList<>();


converts primitive types into their
corresponding wrapper class objects. For example, //autoboxing
int a = 56; list.add(5);
list.add(6);
// autoboxing
Integer aObj = a; System.out.println("ArrayList: " + list);

Autoboxing has a great advantage while working with // unboxing


Java collections. int a = list.get(0);
System.out.println("Value at index 0: " + a);
}
} System.out.println("I just implemented the
Runnable Functional Interface.");
Output }
ArrayList: [5, 6] }).start();
Value at index 0: 5 }
}
In the above example, notice the line,
int a = list.get(0); Output:
Here, the get() method returns the object at index 0. I just implemented the Runnable Functional Interface.
However, due to unboxing, the object is automatically
converted into the primitive type int and assigned to Here, we can pass an anonymous class to a method.
the variable a. This helps to write programs with fewer codes in Java
7. However, the syntax was still difficult and a lot of
extra lines of code were required.
Java Lambda Expressions Java 8 extended the power of a SAMs by going a step
further. Since we know that a functional interface has
The lambda expression was introduced first time in just one method, there should be no need to define the
Java 8. Its main objective to increase the expressive name of that method when passing it as an argument.
power of the language. Lambda expression allows us to do exactly that.

But, before getting into lambdas, we first need to Introduction to lambda expressions
understand functional interfaces. Lambda expression is, essentially, an anonymous or
unnamed method. The lambda expression does not
What is Functional Interface? execute on its own. Instead, it is used to implement a
If a Java interface contains one and only one abstract method defined by a functional interface.
method then it is termed as functional interface. This
only one method specifies the intended purpose of the How to define lambda expression in Java?
interface. Here is how we can define lambda expression in Java.
For example, the Runnable interface from (parameter list) -> lambda body
package java.lang; is a functional interface because it The new operator (->) used is known as an arrow
constitutes only one method i.e. run(). operator or a lambda operator. The syntax might not
be clear at the moment. Let's explore some examples,
Example 1: Define a Functional Interface in java Suppose, we have a method like this:
import java.lang.FunctionalInterface; double getPiValue() {
@FunctionalInterface return 3.1415;
public interface MyInterface{ }
// the single abstract method We can write this method using lambda expression as:
double getValue(); () -> 3.1415
} Here, the method does not have any parameters.
In the above example, the interface MyInterface has Hence, the left side of the operator includes an empty
only one abstract method getValue(). Hence, it is a parameter. The right side is the lambda body that
functional interface. specifies the action of the lambda expression. In this
Here, we have used the case, it returns the value 3.1415.
annotation @FunctionalInterface. The annotation
forces the Java compiler to indicate that the interface Types of Lambda Body
is a functional interface. Hence, does not allow to have In Java, the lambda body is of two types.
more than one abstract method. However, it is not 1. A body with a single expression
compulsory though. () -> System.out.println("Lambdas are great");
In Java 7, functional interfaces were considered
as Single Abstract Methods or SAM type. SAMs were This type of lambda body is known as the expression
commonly implemented with Anonymous Classes in body.
Java 7.
2. A body that consists of a block of code.
Example 2: Implement SAM with anonymous () -> {
classes in java double pi = 3.1415;
return pi;
public class FunctionInterfaceTest { };
public static void main(String[] args) { This type of the lambda body is known as a block
body. The block body allows the lambda body to
// anonymous class include multiple statements. These statements are
new Thread(new Runnable() { enclosed inside the braces and you have to add a semi-
@Override colon after the braces.
public void run() {
Note: For the block body, you can have a return Lambda Expressions with parameters
statement if the body returns a value. However, the Till now we have created lambda expressions without
expression body does not require a return statement. any parameters. However, similar to methods, lambda
expressions can also have parameters. For example,
Example 3: Lambda Expression (n) -> (n%2)==0
Let's write a Java program that returns the value of Pi Here, the variable n inside the parenthesis is a
using the lambda expression. parameter passed to the lambda expression. The
As mentioned earlier, a lambda expression is not lambda body takes the parameter and checks if it is
executed on its own. Rather, it forms the even or odd.
implementation of the abstract method defined by the
functional interface. Example 4: Using lambda expression with
So, we need to define a functional interface first. parameters
import java.lang.FunctionalInterface; @FunctionalInterface
interface MyInterface {
// this is functional interface
@FunctionalInterface // abstract method
interface MyInterface{ String reverse(String n);
}
// abstract method
double getPiValue(); public class Main {
}
public static void main( String[] args ) {
public class Main {
// declare a reference to MyInterface
public static void main( String[] args ) { // assign a lambda expression to the reference
MyInterface ref = (str) -> {
// declare a reference to MyInterface
MyInterface ref; String result = "";
for (int i = str.length()-1; i >= 0 ; i--)
// lambda expression result += str.charAt(i);
ref = () -> 3.1415; return result;
};
System.out.println("Value of Pi = " +
ref.getPiValue()); // call the method of the interface
} System.out.println("Lambda reversed = " +
} ref.reverse("Lambda"));
}
Output:
Value of Pi = 3.1415 }

In the above example, Output:


We have created a functional interface Lambda reversed = adbmaL
named MyInterface. It contains a single abstract
method named getPiValue() Generic Functional Interface
Inside the Main class, we have declared a reference Till now we have used the functional interface that
to MyInterface. Note that we can declare a reference accepts only one type of value. For example,
of an interface but we cannot instantiate an interface.
That is, @FunctionalInterface
interface MyInterface {
// it will throw an error String reverseString(String n);
MyInterface ref = new myInterface(); }

// it is valid The above functional interface only accepts String and


MyInterface ref; returns String. However, we can make the functional
interface generic, so that any data type is accepted.
We then assigned a lambda expression to the
reference. Example 5: Generic Functional Interface and
ref = () -> 3.1415; Lambda Expressions
Finally, we call the method getPiValue() using the
reference interface. When // GenericInterface.java
@FunctionalInterface
System.out.println("Value of Pi = " + interface GenericInterface<T> {
ref.getPiValue());
// generic method
T func(T t); For this, we can perform bulk operations in the stream
} by the combination of Stream API and Lambda
expression.
// GenericLambda.java Example 6: Demonstration of using lambdas with
public class Main { the Stream API

public static void main( String[] args ) { import java.util.ArrayList;


import java.util.List;
// declare a reference to GenericInterface
// the GenericInterface operates on String data public class StreamMain {
// assign a lambda expression to it
GenericInterface<String> reverse = (str) -> { // create an object of list using ArrayList
static List<String> places = new ArrayList<>();
String result = "";
for (int i = str.length()-1; i >= 0 ; i--) // preparing our data
result += str.charAt(i); public static List getPlaces(){
return result;
}; // add places and country to the list
places.add("Nepal, Kathmandu");
System.out.println("Lambda reversed = " + places.add("Nepal, Pokhara");
reverse.func("Lambda")); places.add("India, Delhi");
places.add("USA, New York");
// declare another reference to GenericInterface places.add("Africa, Nigeria");
// the GenericInterface operates on Integer data
// assign a lambda expression to it return places;
GenericInterface<Integer> factorial = (n) -> { }

int result = 1; public static void main( String[] args ) {


for (int i = 1; i <= n; i++)
result = i * result; List<String> myPlaces = getPlaces();
return result; System.out.println("Places from Nepal:");
};
// Filter places from Nepal
System.out.println("factorial of 5 = " + myPlaces.stream()
factorial.func(5)); .filter((p) -> p.startsWith("Nepal"))
} .map((p) -> p.toUpperCase())
} .sorted()
.forEach((p) -> System.out.println(p));
Output: }
Lambda reversed = adbmaL
factorial of 5 = 120 }

In the above example, we have created a generic Output:


functional interface named GenericInterface. It Places from Nepal:
contains a generic method named func(). NEPAL, KATHMANDU
Here, inside the Main class, NEPAL, POKHARA
GenericInterface<String> reverse - creates a reference
to the interface. The interface now operates In the above example, notice the statement
on String type of data. myPlaces.stream()
GenericInterface<Integer> factorial - creates a .filter((p) -> p.startsWith("Nepal"))
reference to the interface. The interface, in this case, .map((p) -> p.toUpperCase())
operates on the Integer type of data. .sorted()
.forEach((p) -> System.out.println(p));
Lambda Expression and Stream API
The new java.util.stream package has been added to Here, we are using the methods
JDK8, which allows Java developers to perform like filter(), map() and forEach() of the Stream API.
operations like search, filter, map, reduce, or These methods can take a lambda expression as input.
manipulate collections like Lists. We can also define our own expressions based on the
For example, we have a stream of data (in our case, syntax we learned above. This allows us to reduce the
a List of String) where each string is a combination of lines of code drastically as we saw in the above
the country name and place of the country. Now, we example.
can process this stream of data and retrieve only the
places from Nepal.
Java Generics Here, T used inside the angle bracket <> indicates
the type parameter. Inside the Main class, we have
Java Generics allows us to create a single created two objects of GenericsClass
class, interface, and method that can be used with intObj - Here, the type parameter T is replaced
different types of data (objects). by Integer. Now, the GenericsClass works with integer
data.
This helps us to reuse our code. stringObj - Here, the type parameter T is replaced
by String. Now, the GenericsClass works
Note: Generics does not work with primitive with string data.
types (int, float, char, etc).
Java Generics Method
Java Generics Class Similar to the generics class, we can also create a
We can create a class that can be used with any type of method that can be used with any type of data. Such a
data. Such a class is known as Generics Class. class is known as Generics Method.
Here's is how we can create a generics class in Java: Here's is how we can create a generics method in Java:

Example: Create a Generics Class Example: Create a Generics Method


class Main { class Main {
public static void main(String[] args) { public static void main(String[] args) {

// initialize generic class // initialize the class with Integer data


// with Integer data DemoClass demo = new DemoClass();
GenericsClass<Integer> intObj = new
GenericsClass<>(5); // generics method working with String
System.out.println("Generic Class returns: " + demo.<String>genericsMethod("Java
intObj.getData()); Programming");

// initialize generic class // generics method working with integer


// with String data demo.<Integer>genericsMethod(25);
GenericsClass<String> stringObj = new }
GenericsClass<>("Java Programming"); }
System.out.println("Generic Class returns: " +
stringObj.getData()); class DemoClass {
}
} // creae a generics method
public <T> void genericsMethod(T data) {
// create a generics class System.out.println("Generics Method:");
class GenericsClass<T> { System.out.println("Data Passed: " + data);
}
// variable of T type }
private T data;
Output
public GenericsClass(T data) { Generics Method:
this.data = data; Data Passed: Java Programming
} Generics Method:
Data Passed: 25
// method that return T type variable
public T getData() { In the above example, we have created a generic
return this.data; method named genericsMethod.
} public <T> void genericMethod(T data) {...}
}
Here, the type parameter <T> is inserted after the
Output modifier public and before the return type void.
Generic Class returns: 5 We can call the generics method by placing the actual
Generic Class returns: Java Programming type <String> and <Integer> inside the bracket before
the method name.
In the above example, we have created a generic class demo.<String>genericMethod("Java Programming");
named GenericsClass. This class can be used to work
with any type of data. demo.<Integer>genericMethod(25);
class GenericsClass<T> {...}
Note: We can call the generics method without
including the type parameter. For example,
demo.genericsMethod("Java Programming");
In this case, the compiler can match the type Here, we have created a generics method. This same
parameter based on the value passed to the method. method can be used to perform operations on integer
data, string data, and so on.
Bounded Types
In general, the type parameter can accept any data 2. Compile-time Type Checking
types (except primitive types). The type parameter of generics provides information
However, if we want to use generics for some specific about the type of data used in the generics code. For
types (such as accept data of number types) only, then example,
we can use bounded types.
In the case of bound types, we use // using Generics
the extends keyword. For example, GenericsClass<Integer> list = new
GenericsClass<>();
<T extends A>
Here, we know that GenericsClass is working
This means T can only accept data that are subtypes with Integer data only.
of A. Now, if we try to pass data other than Integer to this
class, the program will generate an error at compile
Example: Bounded Types time.
class GenericsClass <T extends Number> {
3. Used with Collections
public void display() { The collections framework uses the concept of
System.out.println("This is a bounded type generics generics in Java. For example,
class."); // creating a string type ArrayList
} ArrayList<String> list1 = new ArrayList<>();
}
// creating a integer type ArrayList
class Main { ArrayList<Integer> list2 = new ArrayList<>();
public static void main(String[] args) {
In the above example, we have used the
// create an object of GenericsClass same ArrayList class to work with different types of
GenericsClass<String> obj = new data.
GenericsClass<>(); Similar to ArrayList, other collections
} (LinkedList, Queue, Maps, and so on) are also generic
} in Java.

In the above example, we have created a class named


GenericsClass. Notice the expression, notice the Nested Loop in Java
expression
<T extends Number> If a loop exists inside the body of another loop, it's
Here, GenericsClass is created with bounded type. called a nested loop. Here's an example of the
This means GenericsClass can only work with data nested for loop.
types that are children of Number (Integer, Double,
and so on).
However, we have created an object of the generics // outer loop
class with String. In this case, we will get the following for (int i = 1; i <= 5; ++i) {
error. // codes

GenericsClass<String> obj = new GenericsClass<>(); // inner loop


^ for(int j = 1; j <=2; ++j) {
reason: inference variable T has incompatible // codes
bounds }
equality constraints: String ..
lower bounds: Number }
where T is a type-variable:
T extends Number declared in class GenericsClass Here, we are using a for loop inside another for loop.
We can use the nested loop to iterate through each day
Advantages of Java Generics of a week for 3 weeks.
In this case, we can create a loop to iterate three times
1. Code Reusability (3 weeks). And, inside the loop, we can create another
With the help of generics in Java, we can write code loop to iterate 7 times (7 days).
that will work with different types of data. For
example, Example 1: Java Nested for Loop
public <T> void genericsMethod(T data) {...} class Main {
public static void main(String[] args) { Day: 2
Day: 3
int weeks = 3; .... .. ....
int days = 7; Week: 2
Day: 1
// outer loop prints weeks Day: 2
for (int i = 1; i <= weeks; ++i) { Day: 3
System.out.println("Week: " + i); .... .. ....
.... .. ....
// inner loop prints days
for (int j = 1; j <= days; ++j) { Here you can see that the output of both Example
System.out.println(" Day: " + j); 1 and Example 2 is the same.
}
} Example 3: Java nested loops to create a pattern
} We can use the nested loop in Java to create patterns
} like full pyramid, half pyramid, inverted pyramid, and
so on.
Output Here is a program to create a half pyramid pattern
Week: 1 using nested loops.
Day: 1 class Main {
Day: 2 public static void main(String[] args) {
Day: 3
..... .. .... int rows = 5;
Week: 2
Day: 1 // outer loop
Day: 2 for (int i = 1; i <= rows; ++i) {
Day: 3
.... .. .... // inner loop to print the numbers
.... .. .... for (int j = 1; j <= i; ++j) {
System.out.print(j + " ");
In the above example, the outer loop iterates 3 times }
and prints 3 weeks. And, the inner loop iterates 7 System.out.println("");
times and prints the 7 days. }
We can also create nested loops with while and }
do...while in a similar way. }

Note: It is possible to use one type of loop inside the Output


body of another loop. For example, we can put 1
a for loop inside the while loop. 12
123
Example 2: Java for loop inside the while loop 1234
class Main { 12345
public static void main(String[] args) {
break and continue Inside Nested Loops
int weeks = 3; When we use a break statement inside the inner loop,
int days = 7; it terminates the inner loop but not the outer loop. For
int i = 1; example,

// outer loop class Main {


while (i <= weeks) { public static void main(String[] args) {
System.out.println("Week: " + i);
int weeks = 3;
// inner loop int days = 7;
for (int j = 1; j <= days; ++j) {
System.out.println(" Days: " + j); // outer loop
} for(int i = 1; i <= weeks; ++i) {
++i; System.out.println("Week: " + i);
}
} // inner loop
} for(int j = 1; j <= days; ++j) {

Output: // break inside the inner loop


Week: 1 if(i == 2) {
Day: 1 break;
}
System.out.println(" Days: " + j); In the above example, we have used the continue
} statement inside the inner for loop. Notice the code,
} if(j % 2 != 0) {
} continue;
} }

Output Here, the continue statement is executed when the


Week: 1 value of j is odd. Hence, the program only prints those
Day: 1 days that are even.
Day: 2 We can see the continue statement has affected only
.... .. .... the inner loop. The outer loop is working without any
Week: 2 problem.
Week: 3
Day: 1
Day: 2 Java Command-Line Arguments
.... .. ....
.... .. .... The command-line arguments in Java allow us to pass
arguments during the execution of the program.
In the above example, we have used the break
statement inside the inner for loop. Here, the program As the name suggests arguments are passed through
skips the loop when i is 2. the command line.
Hence, days for week 2 are not printed. However, the
outer loop that prints week is unaffected. Example: Command-Line Arguments
class Main {
Similarly, when we use a continue statement inside public static void main(String[] args) {
the inner loop, it skips the current iteration of the inner System.out.println("Command-Line arguments
loop only. The outer loop is unaffected. For example, are");
class Main {
public static void main(String[] args) { // loop through all arguments
for(String str: args) {
int weeks = 3; System.out.println(str);
int days = 7; }
}
// outer loop }
for(int i = 1; i <= weeks; ++i) {
System.out.println("Week: " + i); Let's try to run this program using the command line.

// inner loop 1. To compile the code


for(int j = 1; j <= days; ++j) { javac Main.java

// continue inside the inner loop 2. To run the code


if(j % 2 != 0) { java Main
continue; Now suppose we want to pass some arguments while
} running the program, we can pass the arguments after
System.out.println(" Days: " + j); the class name. For example,
} java Main apple ball cat
}
} Here apple, ball, and cat are arguments passed to the
} program through the command line. Now, we will get
the following output.
Output Command-Line arguments are
Week: 1 Apple
Days: 2 Ball
Days: 4 Cat
Days: 6
Week: 2 In the above program, the main() method includes
Days: 2 an array of string named args as its parameter.
Days: 4 public static void main(String[] args) {...}
Days: 6
Week: 3 The String array stores all the arguments passed
Days: 2 through the command line.
Days: 4
Days: 6
Note: Arguments are always stored as strings and
always separated by white-space.

Passing Numeric Command-Line Arguments


The main() method of every Java program only
accepts string arguments. Hence it is not possible to
pass numeric arguments through the command line.
However, we can later convert string arguments into
numeric values.

Example: Numeric Command-Line Arguments


class Main {
public static void main(String[] args) {

for(String str: args) {


// convert into integer type
int argument = Integer.parseInt(str);
System.out.println("Argument in integer form: " +
argument);
}

}
}

Let's try to run the program through the command


line.
// compile the code
javac Main.java

// run the code


java Main 11 23

Here 11 and 23 are command-line arguments. Now,


we will get the following output.
Arguments in integer form
11
23

In the above example, notice the line


int argument = Intege.parseInt(str);

Here, the parseInt() method of the Integer class


converts the string argument into an integer.
Similarly, we can use
the parseDouble() and parseFloat() method to convert
the string into double and float respectively.

Note: If the arguments cannot be converted into the


specified numeric value then an exception
named NumberFormatException occurs.

You might also like