Java Zero To Hero
Java Zero To Hero
JAVA
ZERO TO HERO
From Novice to Java Virtuoso - Unleash
Your Inner Hero!
MD KASHIF ALI
Copyrights
Title: Java Zero to Hero by JavaScaler
Author: Md Kashif Ali
Copyright © 2023 by Md Kashif Ali
All rights reserved.
No part of this eBook may be reproduced, distributed, or transmitted in any form or
by any means, including photocopying, recording, or other electronic or mechanical
methods, without the prior written permission of the copyright holder, except in the
case of brief quotations embodied in critical reviews and certain other
noncommercial uses permitted by copyright law.
Disclaimer:
The information presented in this eBook is based on the author's experience and
research at the time of writing. While every effort has been made to ensure the
accuracy of the information, technology and best practices evolve, and some
information may become outdated or subject to change. Readers are advised to
verify the information and use their discretion when applying it to their specific
circumstances. The author and JavaScaler disclaim any liability for any direct,
indirect, incidental, consequential, or special damages arising out of or in any way
connected with the use of this eBook or the information presented herein.
Please note that this eBook is not intended to replace professional advice. Readers
should consult with qualified experts or professionals in the relevant fields for
specific advice or guidance.
By reading and using this eBook, you agree to abide by the terms and conditions
mentioned herein. Unauthorized use or distribution of this eBook may be subject to
Copyrights 1
legal action.
Thank you for respecting the intellectual property rights and supporting the author
and JavaScaler's efforts to provide valuable educational content.
Copyrights 2
Table of Contents
Java Basics
● What is Java
● History of Java
● Features of Java
● C++ vs Java
● Hello Java Program
● Program Internal
● How to set a path?
● JDK, JRE and JVM
● JVM: Java Virtual Machine
● Java Variables
● Java Data Types
● Unicode System
● Operators
● Keywords
Control Statements
● Java Control Statements
● Java If-else
● Java Switch
● Java For Loop
● Java While Loop
● Java Do While Loop
● Java Break
● Java Continue
● Java Comments
Java Inheritance
● Inheritance(IS-A)
● Aggregation(HAS-A)
Java Polymorphism
● Method Overloading
● Method Overriding
● Covariant Return Type
● super keyword
● Instance Initializer block
● final keyword
● Runtime Polymorphism
● Dynamic Binding
● instanceof operator
Java Abstraction
● Abstract class
● Interface
● Abstract vs Interface
Java Encapsulation
● Package
● Access ModifiersEncapsulation
Java Array
● Java Array
● What is String
● Immutable String
● String Comparison
● String Concatenation
● Substring
● Methods of String class
● StringBuffer class
● StringBuilder class
● String vs StringBuffer
● StringBuffer vs Builder
● Creating Immutable classtoString methodStringTokenizer class
Java Regex
● Matcher class
● Pattern class
● Example of Java Regular Expressions
● Java regex API
Exception Handling
● Java Exceptions
● Java Try-catch block
● Java Multiple Catch Block
● Java Nested try
● Java Finally Block
● Java Throw Keyword
● Java Exception Propagation
● Java Throws Keyword
● Java Throw vs Throws
● Final vs Finally vs Finalize
● Exception Handling with Method Overriding
● Java Custom Exceptions
Java Synchronisation
● Synchronisation in java
● Synchronised block
● static synchronisation
● Deadlock in Java
● Inter-thread Comm
● Interrupting Thread
● Reentrant Monitor
Java I/O
● Java Input/Output
● FileOutputStream
● FileInputStream
● BufferedOutputStream
● BufferedInputStream
● SequenceInputStream
● ByteArrayOutputStream
● ByteArrayInputStream
● DataOutputStream
● DataInputStream
● Java FilterOutputStream
● Java FilterInputStream
● Java ObjectStream
● Java ObjectStreamField
● Console
● FilePermission
● Writer
● Reader
● FileWriter
● FileReader
● BufferedWriter
● BufferedReader
● CharArrayReader
● CharArrayWriter
● PrintStream
● PrintWriter
● OutputStreamWriter
● InputStreamReader
● PushbackInputStream
● PushbackReader
● StringWriter
● StringReader
● PipedWriter
● PipedReader
● FilterWriter
● FilterReader
● File
● FileDescriptor
● RandomAccessFile
● java.util.Scanner
Java Serialization
● Java Serialization
● Java transient keyword
Java Networking
● Networking Concepts
● Socket Programming
● URL class
● URLConnection class
● HttpURLConnection
● InetAddress class
● DatagramSocket class
Java Collections
● Collection Framework
● Java ArrayList
● Java LinkedList
● ArrayList vs LinkedList
● Java List Interface
● Java HashSet
● Java LinkedHashSet
● Java TreeSet
● Queue & PriorityQueue
● Deque & ArrayDeque
● Java Map Interface
● Java HashMap
● Working of HashMap
● Java LinkedHashMap
● Java TreeMap
● Java Hashtable
● HashMap vs Hashtable
● Java EnumSet
● Java EnumMap
● Collections class
● Sorting Collections
● Comparable interface
● Comparator interface
● Comparable vs Comparator
● Properties class
● ArrayList vs Vector
● Java Vector
● Java Stack
● Java Collection Interface
● Java Iterator Interface
● Java Deque Interface
● Java ConcurrentHashMap
● Java ConcurrentLinkedQueue
Java Zero to Hero
Java Basics
What is Java?
Java is a high-level, object-oriented programming language that is designed to be
portable, secure, and robust. It was developed by James Gosling and his team at
Sun Microsystems (later acquired by Oracle Corporation) and first released in 1995.
Java is known for its "write once, run anywhere" (WORA) principle, which means that
Java code can be written once and executed on any platform that has a Java Virtual
Machine (JVM) installed, without the need for recompilation. This platform
independence is achieved by using the Java bytecode format, which is an
intermediate representation of the code that is platform-neutral.
Java is widely used for building various types of applications, including web
applications, desktop applications, mobile apps, enterprise systems, and more. It
has become one of the most popular programming languages due to its versatility,
ease of use, and robustness.
History of Java
1991: The development of Java began under the name "Oak" at Sun
Microsystems by James Gosling and his team. The initial focus was on creating
a programming language for consumer electronic devices.
1995: The first public release of Java (JDK 1.0) was made on May 23, 1995. It
included the core features of the Java language and the Java applet technology,
which allowed small Java programs to be embedded into web pages.
1996: JDK 1.1 was released, introducing new features and improvements to the
language and the standard library.
1998: JDK 1.2 (Java 2) was released, bringing significant updates to the
language and the platform, including the introduction of the Swing GUI toolkit
and the Collections Framework.
2004: JDK 1.5 (Java 5) was released, introducing several important language
features like generics, enhanced for loop, autoboxing, and annotations.
2017: JDK 9 introduced modularity with the Java Platform Module System
(JPMS).
2020: JDK 14, 15, 16, and 17 were released successively, each bringing new
features and improvements to the language and platform.
Features of Java
7. Rich Standard Library: Java comes with a vast standard library that provides a
wide range of functionalities, making development faster and more efficient.
C++ and Java are both widely used programming languages, but they have some
fundamental differences:
Syntax: C++ uses a more complex syntax compared to Java. Java was
designed to have a simpler and more user-friendly syntax.
Standard Library: Java has a more extensive and consistent standard library
compared to C++, which can sometimes have a more fragmented ecosystem
due to various libraries and implementations.
Explanation:
We define a class named HelloWorld . In Java, all code must be inside classes.
The public keyword indicates that the class is accessible from other classes.
The static keyword is used to define a static method that belongs to the class
itself, not to any specific instance of the class.
The void keyword indicates that the main method does not return any value.
mainis the entry point of the program. It is the method that will be executed
when we run the program.
The Java compiler ( javac ) translates the human-readable Java source code
into platform-independent bytecode. The bytecode is stored in .class files.
The Java Virtual Machine (JVM) is responsible for executing Java bytecode.
When you run a Java program, the JVM loads the necessary classes and
starts executing the main method of the specified class (the entry point of
the program).
3. Java Bytecode:
The bytecode consists of instructions that the JVM can understand and
execute.
It is important to note that understanding the internal details of the Java program,
such as bytecode, is not usually required for typical Java programming tasks.
However, having a basic understanding of these concepts can be helpful when
dealing with advanced topics or troubleshooting performance issues.
Setting Path:
Setting the path in Java is essential to make the Java Development Kit (JDK) tools,
including the Java compiler ( javac ) and Java runtime ( java ), accessible from any
directory on your computer. The path allows the operating system to find these tools
when you run Java commands from the command prompt or terminal.
Here's how to set the path in Windows and Unix-based systems (Linux and macOS):
Windows:
Files\\Java\\jdk_version .
5. Under "System Variables," find the "Path" variable, and click "Edit."
6. Click "New" and add the path to the JDK's "bin" directory (e.g., C:\\Program
Files\\Java\\jdk_version\\bin ).
3. Edit the .bashrc or .bash_profile file in your home directory using a text editor
(e.g., nano , vi , or gedit ).
export PATH="/usr/lib/jvm/jdk_version/bin:$PATH"
After setting the path, you can verify that it worked by opening a new terminal or
command prompt and running java -version and javac -version commands. They
should display the version information of your installed JDK.
Java Variables:
In Java, variables are used to store data values that can be manipulated within a
program. Before using a variable, it needs to be declared with a specific data type.
Java supports the following variable types:
1. Primitive Data Types: These are basic data types built into the language.
Characters: char .
Boolean: boolean .
Unicode System:
For example, you can declare a Unicode character in Java like this:
The escape sequence \\u is used to indicate a Unicode character, followed by the
four-digit hexadecimal representation of the Unicode code point.
Operators:
Java supports various types of operators, which are used to perform operations on
variables and values. Here are some common operators in Java:
(division), % (modulus).
Assignment Operators: = , += , = , = , /= , %= .
(bitwise NOT).
Keywords:
Keywords in Java are reserved words that have predefined meanings and cannot be
used as identifiers (e.g., variable names, class names). They are an integral part of
the language and serve specific purposes. Some examples of Java keywords
include:
abstract, boolean, break, byte, case, catch, class, continue, default, do, double,
else, extends, final, finally, float, for, if, implements, import, instanceof,
int, interface, long, new, package, private, protected, public, return, short,
static, super, switch, this, throw, throws, try, void, while
These keywords are used for various purposes, such as defining classes, control
flow, variable declaration, method definition, and more. It's essential to be familiar
Java If-else:
The if-else statement is used to execute a block of code conditionally. If the given
condition is true, the code inside the if block is executed; otherwise, the code
inside the else block (if provided) is executed.
if (num > 0) {
System.out.println("The number is positive.");
} else {
System.out.println("The number is non-positive.");
}
Java Switch:
The switch statement is used to perform different actions based on the value of a
variable or an expression. It provides an alternative to using multiple if-else
statements.
int dayOfWeek = 3;
switch (dayOfWeek) {
case 1:
System.out.println("Monday");
break;
case 2:
System.out.println("Tuesday");
break;
case 3:
System.out.println("Wednesday");
break;
default:
System.out.println("Invalid day");
}
int count = 1;
The do-while loop is similar to the while loop, but it ensures that the block of code is
executed at least once before checking the condition.
int x = 1;
do {
System.out.println("Value of x: " + x);
x++;
} while (x <= 5);
Java Break:
The break statement is used to terminate the loop or switch statement prematurely,
based on a condition.
Java Continue:
Java Comments:
Single-line comments start with // and continue until the end of the line:
Multi-line comments start with /* and end with / , allowing multiple lines to be
commented at once:
/*
This is a multi-line comment.
It spans across multiple lines.
*/
Javadoc comments are used for generating documentation. They start with /**
and end with / . Javadoc comments are placed before classes, methods, or
fields and can include additional tags for documentation generation:
/**
* This method calculates the sum of two numbers.
* @param a The first number.
* @param b The second number.
* @return The sum of a and b.
*/
public int sum(int a, int b) {
return a + b;
}
Using comments effectively helps improve code readability and makes it easier for
other developers to understand your code.
The Object class provides several important methods that are inherited by all
classes, such as equals() , hashCode() , toString() , getClass() , and more. These
methods can be overridden in user-defined classes to provide custom behavior.
Naming Convention:
In Java, following a consistent and standard naming convention is crucial for code
readability and maintainability. Here are some common Java naming conventions:
1. Class Names: Start with an uppercase letter, and use camel case (capitalize the
first letter of each word) for multiple words. Example: MyClass , CarModel .
2. Variable Names: Start with a lowercase letter, and use camel case for multiple
words. Example: age , firstName .
3. Constant Names: Use uppercase letters and separate words with underscores.
Example: MAX_VALUE , PI .
4. Method Names: Start with a lowercase letter, and use camel case for multiple
words. Example: calculateArea , getName .
void startEngine() {
// Code to start the car's engine
}
}
Here, Car is a class, and brand , model , and startEngine() are its members. When
you create an object of the Car class, it represents a specific car with its own brand
and model.
Method:
A method in Java is a block of code that defines the behavior of an object. It is
defined within a class and can be invoked on objects of that class. Methods are used
In this example, add() is a method of the Calculator class that takes two integer
parameters and returns their sum.
Constructor:
// Constructor
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
In this example, the Person class has a constructor that takes the name and age as
parameters and initializes the corresponding attributes.
static Keyword:
The static keyword is used to declare members (variables and methods) that
belong to the class itself, rather than to individual objects. They are shared by all
objects of the class and can be accessed directly using the class name, without
creating an instance of the class.
this Keyword:
The this keyword in Java is a reference to the current instance of the class. It is
used to distinguish between instance variables and parameters with the same name,
and to access instance variables and methods within the class.
In this example, this.name refers to the instance variable name , while name refers to
the method parameter name .
Java Inheritance:
Inheritance is one of the fundamental concepts of object-oriented programming
(OOP) that allows one class (subclass or derived class) to inherit the properties and
behaviors of another class (superclass or base class). The subclass can extend the
functionality of the superclass by adding new attributes and methods or by overriding
existing ones.
In Java, inheritance is achieved using the extends keyword.
IS-A Relationship (Inheritance):
class Animal {
void makeSound() {
System.out.println("Animal makes a sound.");
}
}
In this example, Dog is a subclass of Animal . So, a Dog IS-A Animal . When we
create a Dog object, it can call methods defined in both Dog and Animal .
Java Aggregation:
Aggregation represents a HAS-A relationship between classes, where one class
contains another class as part of its structure. It is a form of association that implies
a relationship between a whole and its parts.
In Java, aggregation is achieved by creating a class with a reference to another
class.
Consider the following example:
class Address {
String street;
String city;
class Person {
String name;
Address address;
In this example, Person has a HAS-A relationship with Address , as Person contains
an Address object as one of its attributes.
Java Polymorphism:
Polymorphism is a key concept in object-oriented programming (OOP) that allows
objects of different classes to be treated as objects of a common superclass. It
provides a way to perform a single action in different ways based on the context.
There are two main types of polymorphism in Java: compile-time polymorphism and
runtime polymorphism.
Method Overloading:
Method overloading is an example of compile-time (static) polymorphism. It allows a
class to have multiple methods with the same name but different parameters. The
compiler determines which method to call based on the number or types of
arguments passed.
class MathUtils {
int add(int a, int b) {
return a + b;
}
In this example, the add() method is overloaded with two different parameter types
(integers and doubles).
Method Overriding:
In this example, the Dog class overrides the makeSound() method of the Animal class
to provide a specific implementation for dogs.
Covariant Return Type:
class Animal {
Animal getAnimal() {
return this;
}
}
In this example, the getAnimal() method in the Dog class returns a Dog object, which
is a subclass of the Animal class's return type.
super Keyword:
The super keyword is used to refer to the superclass's members (fields, methods,
and constructors) from the subclass. It is often used to call the superclass's
constructor or to access overridden methods or fields.
class Animal {
String name;
Animal(String name) {
In this example, the super(name) call in the Dog constructor is used to invoke the
Animal class's constructor with the name parameter.
Instance Initializer Block:
The instance initializer block is a block of code that is executed whenever an
instance of the class is created, before the constructor is called. It is defined within
curly braces without any method name.
class MyClass {
{
// Instance initializer block
System.out.println("Instance initializer block is executed.");
}
MyClass() {
System.out.println("Constructor is called.");
}
}
When you create an object of the MyClass , the instance initializer block is executed
before the constructor.
final Keyword:
The final keyword is used to declare that a variable, method, or class cannot be
changed or overridden after its initialization or definition.
Final Variable: Once initialized, the value of a final variable cannot be modified.
Runtime Polymorphism:
Runtime polymorphism is also known as dynamic polymorphism or late binding. It
occurs when the method to be executed is determined at runtime based on the
actual type of the object, not at compile time.
In Java, method overriding is an example of runtime polymorphism, where the
decision about which method to call is made during runtime.
Dynamic Binding:
Dynamic binding is the process of linking a method call to its method definition
during runtime. It allows Java to support runtime polymorphism and method
overriding.
class Animal { }
In this example, animal instanceof Dog checks whether the animal object is an
instance of the Dog class or any of its subclasses. Since animal is an instance of
Dog , the output will be "The animal is a Dog."
Java Abstraction:
Abstraction is one of the core principles of object-oriented programming (OOP) and
refers to the process of hiding the implementation details of an object and exposing
only the relevant features or behaviors to the outside world. It allows us to focus on
what an object does rather than how it does it. Abstraction is achieved in Java
through abstract classes and interfaces.
Abstract Class:
An abstract class is a class that cannot be instantiated directly and is intended to be
subclassed. It serves as a blueprint for other classes and can contain abstract
methods (methods without a body) that must be implemented by its subclasses. An
abstract class can also have concrete methods with an implementation.
In this example, Shape is an abstract class that has an abstract method draw() and a
concrete method moveTo() . Classes that inherit from Shape must provide an
implementation for the draw() method.
Interface:
An interface in Java is a blueprint of a class that defines a contract for the classes
that implement it. It contains only abstract methods and constants (implicitly public ,
static , and final ). Interfaces are used to achieve multiple inheritance in Java.
In this example, Drawable is an interface that has an abstract method draw() and two
constants MAX_WIDTH and MAX_HEIGHT . A class can implement multiple interfaces and
provide implementations for all the methods defined in those interfaces.
2. Methods: An abstract class can have both abstract and concrete methods, while
an interface can only have abstract methods. In Java 8 and later, interfaces can
have default methods (with an implementation) and static methods.
4. Fields: Abstract classes can have instance variables, which can be inherited by
their subclasses. Interfaces can only have public , static , and final variables
(constants).
6. Purpose: Abstract classes are used to provide a common base for related
classes and can contain shared behavior. Interfaces are used to define a
contract for unrelated classes to implement.
When you want to provide a common base class with some shared
implementation for related classes.
When you need to create a class hierarchy, and there is a "is-a" relationship
between classes.
When you want to achieve multiple inheritance (a class can implement multiple
interfaces but extend only one class).
In summary, both abstract classes and interfaces are used for abstraction in Java,
but they serve different purposes and have different capabilities. Choosing between
an abstract class and an interface depends on the specific design requirements and
the relationship between the classes involved.
Java Encapsulation:
Encapsulation is one of the four fundamental principles of object-oriented
programming (OOP) and is closely related to the concept of data hiding. It refers to
the bundling of data (attributes) and methods that operate on that data within a
single unit (i.e., a class). The data is hidden or made private within the class, and
access to the data is controlled through public methods, providing a layer of
abstraction.
The main goals of encapsulation are to:
1. Hide the internal details of how an object's data is represented and manipulated.
3. Provide controlled access to the data through getter and setter methods.
Package:
A package in Java is a mechanism to organize related classes and interfaces into a
single unit. It helps in avoiding naming conflicts and provides a namespace for the
classes. Packages allow you to group classes that have similar functionality or are
part of the same module or application.
To declare a class inside a package, use the package keyword followed by the
package name at the beginning of the source file:
package com.example.myapp;
Access Modifiers:
1. public: Members with the public modifier are accessible from any class in any
package.
2. protected: Members with the protected modifier are accessible within the same
package and also by subclasses (even if they are in a different package).
4. private: Members with the private modifier are accessible only within the same
class.
package com.example.myapp;
void defaultMethod() {
// Method implementation
}
Encapsulation (Continued):
Encapsulation is achieved in Java by using access modifiers to control the access to
the attributes (data) and methods of a class. By making the attributes private and
In this example, the name and age attributes are made private, and public getter and
setter methods ( getName() , setName() , getAge() , setAge() ) are provided to access
and modify these attributes. The setter method for age includes a validation check to
ensure that the age is non-negative.
Java Array:
An array in Java is a collection of elements of the same data type that are stored in
contiguous memory locations. Arrays provide a way to store multiple values under a
single variable name, making it easier to manage and access data. Each element in
an array is identified by its index, starting from 0.
Multidimensional Array:
A multidimensional array in Java is an array of arrays. It can have multiple
dimensions, such as 2D or 3D arrays.
Output:
Element at index 0: 10
Element at index 1: 20
Element at index 2: 30
Element at index 3: 40
Element at index 4: 50
1. Declaration: The syntax for declaring an array involves specifying the data type
of the elements followed by square brackets [] and the array name.
int[] numbers;
1. Instantiation: To create an array and allocate memory for its elements, use the
new keyword followed by the data type and the number of elements in square
brackets.
1. Initialization: After creating the array, you can initialize its elements with specific
values using the array index.
numbers[0] = 10;
numbers[1] = 20;
numbers[2] = 30;
numbers[3] = 40;
numbers[4] = 50;
Alternatively, you can declare, instantiate, and initialize an array in a single line:
This is a shorthand way of creating an array and assigning values to its elements in
one step. The size of the array is automatically determined based on the number of
values provided.
2. Object Cloning:
Object cloning in Java is the process of creating a copy of an object. The Cloneable
interface, available in the java.lang package, is used to indicate that a class
supports cloning. The clone() method is used to create a shallow copy of the object.
Example:
@Override
public String toString() {
return "Student: " + name;
}
}
3. Math class:
The Math class in Java is part of the java.lang package and provides several static
methods for common mathematical operations. It includes methods for basic
arithmetic operations (e.g., add , subtract , multiply , divide ) as well as methods for
more complex mathematical functions (e.g., sqrt , pow , sin , cos , log , etc.). The
methods of the Math class are static, meaning they can be accessed directly using
the class name, without the need to create an instance of the class.
Example:
4. Wrapper Class:
In Java, a wrapper class is used to convert a primitive data type into an object. Each
primitive data type (e.g., int , double , boolean , etc.) has a corresponding wrapper
class (e.g., Integer , Double , Boolean , etc.). Wrapper classes are useful when you
need to use primitive data types in situations that require objects, such as using
collections or generics.
Example:
);
System.out.println("Unboxed Values:");
System.out.println("Unboxed Int Value: " + unboxedIntValue);
System.out.println("Unboxed Double Value: " + unboxedDoubleValue);
System.out.println("Unboxed Boolean Value: " + unboxedBooleanValue);
}
}
5. Java Recursion:
Example:
6. Call By Value:
Java uses call by value to pass arguments to methods. When you pass a primitive
data type (e.g., int , double , char , etc.) to a method, a copy of the value is passed,
and changes made to the parameter inside the method have no effect on the original
variable outside the method. Similarly, when you pass an object to a method, the
reference to the object is passed by value, not the actual object. Therefore, the
method can modify the object's properties, but it cannot change the reference itself.
Example:
class Student {
String name;
7. strictfp keyword:
The strictfp keyword is used to enforce strict floating-point precision in Java. When
a class or method is declared with the strictfp keyword, all floating-point
calculations within that class or method are performed using strict floating-point rules
defined by the IEEE 754 standard. This ensures consistent results across different
platforms and architectures.
Example:
8. javadoc tool:
The javadoc tool is a utility in Java used to generate HTML documentation from Java
source code. It parses the source code, extracts the comments written in the
Javadoc format, and generates API documentation in HTML format. Javadoc
comments start with /** and can include additional tags to provide information
about classes, methods, and fields.
Example:
class Car {
String brand;
String model;
// Constructor
public Car(String brand, String model) {
// Method
public void start() {
System.out.println("Starting the car...");
}
}
car1.start();
car2.start();
}
}
Example:
class Animal {
public void makeSound() {
System.out.println("Animal makes a sound");
}
}
// Method overloading
public void makeSound(String soundType) {
System.out.println("Dog " + soundType);
}
}
// Method overloading
Dog myDog = new Dog();
myDog.makeSound(); // Output: Dog barks
myDog.makeSound("howls"); // Output: Dog howls
}
}
In this example, the Animal class has a makeSound() method that is overridden in the
Dog class. The Dog class also has an overloaded makeSound() method that takes a
Java String
In Java, string is basically an object that represents sequence of char values.
An array of characters works same as Java string.
CharSequence Interface:
2. By new keyword: You can also create a String object using the new keyword.
This creates a new String object in the heap memory, even if a similar string
already exists in the string pool.
// By new keyword
String str2 = new String("Java is fun!");
The String class in Java provides various methods to manipulate and work with
strings. Here are some common methods of the String class:
// Concatenate strings
String concatStr = str.concat(" Welcome");
System.out.println("Concatenated string: " + concatStr);
These are just some of the many methods provided by the String class. The String
class offers a wide range of methods to handle string manipulation, searching, and
formatting in Java.
Immutable String:
In Java, a String object is immutable, which means once it is created, its content
cannot be changed. When you modify a String , a new String object is created with
the modified content. The immutability of strings ensures their safety in
multithreaded environments and allows for efficient string manipulation because the
same string can be shared by multiple references without fear of modification.
Example:
String Comparison:
In Java, you can compare strings using the equals() method to check if the content
of two strings is the same. For reference-based comparison, you can use the ==
operator, but it only checks if the two string references point to the same memory
location, not the content.
Example:
String Concatenation:
String concatenation in Java can be performed using the + operator or the concat()
method of the String class. When concatenating multiple strings using the +
Example:
// Using + operator
String concatenatedStr1 = str1 + str2;
Substring:
The substring() method in Java is used to extract a portion of a string. It takes two
parameters: the starting index (inclusive) and the ending index (exclusive) of the
substring to be extracted.
Example:
The String class in Java provides many useful methods for string manipulation and
analysis. Some common methods are length() , charAt() , equals() ,
equalsIgnoreCase() , startsWith() , endsWith() , contains() , indexOf() , lastIndexOf() ,
StringBuffer class:
// Append strings
sb.append(", Java!");
System.out.println("Appended string: " + sb); // Output: Hello, Java!
StringBuilder class:
// Append strings
sb.append(", Java!");
System.out.println("Appended string: " + sb); // Output: Hello, Java!
String : String objects are immutable. Once created, their content cannot be
changed. Every string modification results in a new String object, which may
lead to unnecessary memory usage and reduced performance when dealing
with frequent modifications.
2. Declare all fields as final and initialize them either in the constructor or at the
time of declaration.
3. Provide only getter methods to access the fields. Do not provide setter methods.
4. Make sure to not allow any modification of the fields once the object is created.
Example:
lexicographically.
Example:
1. concat(String str) : Concatenates the specified str to the end of the current
string.
Example:
Example:
1. endsWith(String suffix) : Checks if the current string ends with the specified
suffix .
Example:
Example:
Example:
Example:
1. getBytes(): Converts the string into a byte array using the platform's default
charset encoding.
Example:
1. getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) : Copies characters
from the string into the dst array.
Example:
1. indexOf(int ch) : Returns the index of the first occurrence of the specified
character ch within the string.
Example:
1. indexOf(int ch, int fromIndex) : Returns the index of the first occurrence of the
specified character ch within the string, starting the search from the specified
fromIndex .
Example:
1. indexOf(String str) : Returns the index of the first occurrence of the specified
substring str within the string.
Example:
1. indexOf(String str, int fromIndex) : Returns the index of the first occurrence of the
specified substring str within the string, starting the search from the specified
fromIndex .
Example:
1. intern(): Returns the canonical representation of the string, i.e., the unique
instance of the string in the string pool.
Example:
Example:
1. lastIndexOf(int ch) : Returns the index of the last occurrence of the specified
character ch within the string.
Example:
1. lastIndexOf(int ch, int fromIndex) : Returns the index of the last occurrence of the
specified character ch within the string, searching backward from the specified
fromIndex .
Example:
Example:
1. lastIndexOf(String str, int fromIndex) : Returns the index of the last occurrence of
the specified substring str within the string, searching backward from the
specified fromIndex .
Example:
Example:
Example:
Example:
Example:
1. split(String regex) : Splits the string into an array of substrings based on the
provided regex .
Example:
1. startsWith(String prefix) : Checks if the string starts with the specified prefix .
Example:
Example:
Example:
Example:
Example:
Example:
Example:
1. trim(): Removes leading and trailing whitespaces from the string and returns a
new string.
Example:
Example:
Example:
Example:
Example:
float pi = 3.14159f;
String result = String.valueOf(pi); // Returns "3.14159"
Example:
Java Regex:
Java Regular Expressions, also known as Java Regex, are used to match patterns
in strings. They are a powerful tool for text processing and pattern matching. Java
provides built-in support for regular expressions through two main classes: Pattern
and Matcher .
Matcher class:
The Matcher class is used to search for patterns defined by a Pattern object within a
given input string. It provides methods to perform various operations on the matched
patterns, such as finding all occurrences, replacing, and extracting groups.
Pattern class:
The Pattern class is used to compile a regular expression into a pattern that can be
used by the Matcher class for matching against input strings. It provides methods to
create and manipulate regular expression patterns.
import java.util.regex.*;
// Create a Matcher object to search for the pattern in the input string
Matcher matcher = pattern.matcher(input);
import java.util.regex.*;
// Create a Matcher object to search for the pattern in the input string
Matcher matcher = pattern.matcher(input);
Output:
Regex Quantifiers:
Quantifiers in regular expressions allow you to specify how many times a character
or group should occur. They modify the behavior of character classes and
metacharacters.
import java.util.regex.*;
// Create a Matcher object to search for the pattern in the input string
Matcher matcher = pattern.matcher(input);
Output:
Found: bbbbb
import java.util.regex.*;
// Define the regular expression pattern to find words that start with 'c' or
'm'
String regex = "\\\\b(c|m)\\\\w+\\\\b";
// Create a Matcher object to search for the pattern in the input string
Matcher matcher = pattern.matcher(input);
Output:
Found: cat
Found: mat
Example:
try {
int result = num1 / num2; // This will throw an ArithmeticException
System.out.println("Result: " + result);
} catch (ArithmeticException e) {
System.out.println("Exception caught: " + e.getMessage());
}
Output:
Output:
Exception caught: 5
Program continues after exception handling.
In this example, we try to access the 6th element of an array with only 3 elements,
causing an ArrayIndexOutOfBoundsException . The exception is caught and handled
within the catch block.
Example:
In this example, we try to call the length() method on a null string, leading to a
NullPointerException . We have multiple catch blocks to handle different exceptions.
Example:
try {
int result = num1 / num2; // This will throw an ArithmeticException
System.out.println("Result: " + result);
} catch (ArithmeticException e) {
System.out.println("Inner Exception caught: " + e.getMessage());
}
Output:
handles an ArithmeticException .
Example:
import java.io.*;
try {
br = new BufferedReader(new FileReader("input.txt"));
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (FileNotFoundException e) {
System.out.println("File not found: " + e.getMessage());
} catch (IOException e) {
System.out.println("IOException: " + e.getMessage());
} finally {
try {
if (br != null)
br.close(); // Close the BufferedReader in the finally block
} catch (IOException e) {
System.out.println("Error closing BufferedReader: " + e.getMessage());
}
}
}
}
In this example, we read data from a file using a BufferedReader . We close the
in the finally block to ensure that it gets closed regardless of
BufferedReader
Example:
Output:
In this example, we explicitly throw an ArithmeticException when the age is less than
18.
Example:
Output:
main()` method.
Example:
Output:
In this example, the method() throws an Exception , which is handled in the main()
throws is used in a method signature to indicate that the method may throw one
or more exceptions.
Example:
class Parent {
void method() throws Exception {
System.out.println("Parent's method");
}
}
Output:
In this example, the Child class overrides the method() from its Parent class. The
Child class chooses to throw an ArithmeticException in the overridden method.
When the method is called through the reference of the Parent class but pointing to
a Child object, the Child class's method is executed.
exceptional situations in your application and provide meaningful error messages for
better debugging and error reporting.
Output:
Example:
class Outer {
private int outerField = 10;
void display() {
System.out.println("Outer Field: " + outerField);
System.out.println("Inner Field: " + innerField);
Output:
Outer Field: 10
Inner Field: 20
In this example, we have an outer class Outer with a member inner class Inner . We
create an instance of the outer class and then use it to create an instance of the
inner class. The inner class can access both the outerField and innerField
variables.
Example:
interface Greeting {
void greet();
}
Output:
Example:
void display() {
// Local Inner class
class Inner {
void innerMethod() {
System.out.println("Outer Field from Inner: " + outerField);
}
}
Output:
innerMethod() of the inner class accesses the outerField of the enclosing class.
Example:
class Outer {
private static int outerStaticField = 50;
Output:
In this example, we have an outer class Outer with a static nested class
StaticNested . We access the outerStaticField from the static nested class.
Nested Interface:
A Nested Interface is an interface declared within another class or interface. It is
implicitly static and accessible within the enclosing class or interface. It is used for
logical grouping of related interfaces.
Example:
class Outer {
interface NestedInterface {
void display();
}
}
Output:
Java Multithreading
1. Multithreading: Multithreading is a programming concept that allows multiple
threads to execute independently within a single Java program. It enables
efficient utilization of CPU resources and helps in building responsive and
concurrent applications.
2. Life Cycle of a Thread: The life cycle of a thread in Java consists of several
states:
Runnable: The thread is ready to run and waiting for CPU time.
4. Thread Scheduler: The thread scheduler is responsible for assigning CPU time
to threads based on their priorities and states.
5. Sleeping a Thread: The sleep() method is used to make a thread pause its
execution for a specified amount of time.
try {
Thread.sleep(1000); // Sleep for 1 second.
} catch (InterruptedException e) {
e.printStackTrace();
}
6. Starting a Thread Twice: It's not possible to start a thread twice. Once a thread
has been started and executed or terminated, it cannot be started again. If you
try to start a thread again, it will throw an IllegalThreadStateException .
7. Calling the run() Method: You should never directly call the run() method to
start a new thread. Instead, use the start() method. Calling run() directly will
run the code in the current thread, not in a new thread.
8. Joining a Thread: The join() method allows one thread to wait for the
completion of another thread.
9. Naming a Thread: You can set a name for a thread using the setName() method.
This helps in identifying threads easily during debugging.
10. Thread Priority: Threads can have different priorities, such as MIN_PRIORITY ,
NORM_PRIORITY , and MAX_PRIORITY . Higher priority threads get more CPU time.
11. Daemon Thread: A daemon thread is a thread that runs in the background and
does not prevent the JVM from exiting when the main thread finishes. You can
set a thread as a daemon thread using setDaemon(true) .
13. Thread Group: A thread group is a way to group multiple threads together for
better management. However, it's not commonly used, and modern Java
applications tend to use thread pools instead.
14. Shutdown Hook: A shutdown hook is a piece of code that is executed when the
JVM is about to shut down. It's useful for performing cleanup tasks before the
application exits.
16. Garbage Collection: Garbage collection is a process in Java where the JVM
automatically reclaims memory occupied by objects that are no longer in use. It
helps in managing memory efficiently.
17. Runtime Class: The Runtime class in Java provides access to the Java runtime
system, and it allows you to interact with the environment in which the
application is running. It also provides methods for executing system commands
and managing the JVM.
Here's a code example demonstrating the creation and execution of threads, setting
thread name, priority, and using sleep:
thread1.setName("Thread-1");
thread2.setName("Thread-2");
thread1.setPriority(Thread.MAX_PRIORITY);
thread2.setPriority(Thread.MIN_PRIORITY);
thread1.start();
thread2.start();
}
}
In this example, two threads are created using the MyThread class (extending
Thread ). The threads will execute their tasks concurrently, and Thread.sleep(1000) will
make each thread sleep for 1 second between each count. The threads are given
Java Synchronization:
1. Synchronization in Java: Synchronization is a technique used to control access
to shared resources in a multi-threaded environment. When multiple threads try
to access shared resources concurrently, synchronization ensures that only one
thread can access the critical section (the synchronized block) at a time. This
prevents race conditions and maintains data consistency.
2. Synchronized Block: In Java, you can use the synchronized keyword to create a
synchronized block. A synchronized block allows you to specify a block of code
that should be executed by only one thread at a time. The block is synchronized
on a specified object, ensuring that only one thread at a time can enter that block
for that particular object.
Example:
class SharedResource {
public void synchronizedMethod() {
// This synchronized method can be accessed by only one thread at a time.
// Critical section code
}
Example:
class SharedResource {
public static synchronized void staticSyncMethod() {
// Static synchronized method can be accessed by only one thread at a time.
// Critical section code
}
1. Deadlock in Java: Deadlock occurs when two or more threads are unable to
proceed because each of them is waiting for a resource that is held by another
thread. It leads to a circular waiting scenario, causing the threads to get stuck
indefinitely. Deadlocks are undesirable and can lead to application hang-ups.
Example of Deadlock:
class SharedResource {
public synchronized void method1(SharedResource resource) {
// This method acquires a lock on this object (current instance of SharedResou
rce).
// It will now try to call method2 on the 'resource' object.
resource.method2(this);
}
class SharedResource {
public synchronized void produce() {
while (queueIsFull()) {
try {
// Wait until the queue is not full
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// Produce an item and add it to the queue
addToQueue();
// Notify waiting consumer threads that a new item is available in the queue
notifyAll();
}
Example:
Example:
class SharedResource {
public synchronized void method1() {
System.out.println("Inside method1");
method2();
}
In this example, method1 and method2 are synchronized methods. When method1 is
called, it acquires the lock on the resource object. Within method1 , it calls method2 ,
which is also synchronized. The thread can successfully enter method2 even though
it already holds the lock for the resource object, thanks to reentrant synchronization.
Java I/O
Java I/O (Input/Output):
Java I/O deals with reading data from input sources and writing data to output
destinations. It involves classes and methods to perform various I/O operations,
such as reading and writing files, streams, and objects.
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
3. SequenceInputStream:
SequenceInputStreamis used to concatenate multiple input streams into a single
stream, reading from them one by one.
import java.io.*;
int data;
while ((data = sis.read()) != -1) {
System.out.print((char) data);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
import java.io.ByteArrayOutputStream;
import java.io.IOException;
Example - Writing and reading primitive data types using DataOutputStream and
DataInputStream:
import java.io.*;
filter or modify the data while reading from or writing to streams. The concrete
implementations, such as BufferedOutputStream , DataOutputStream , and
ObjectOutputStream , extend FilterOutputStream .
import java.io.*;
import java.io.*;
oos.writeObject(person1);
oos.writeObject(person2);
System.out.println("Objects written to the file successfully!");
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Read objects:");
System.out.println(person1);
System.out.println(person2);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
Java I/O provides powerful mechanisms to handle various types of data and formats,
making it a crucial part of developing applications that interact with external
resources such as files, streams, and serialized objects.
1. Console:
The Console class in Java provides a simple way to interact with the console or
command-line interface. It allows reading input and printing output directly to the
console.
Example:
if (console != null) {
String input = console.readLine("Enter your name: ");
console.printf("Hello, %s!%n", input);
} else {
System.out.println("Console not available.");
}
}
}
1. FilePermission:
The FilePermission class in Java is used to represent the access rights to files
and directories. It is a part of the security framework to control what resources a
codebase can access.
Example:
import java.io.FilePermission;
import java.security.Permission;
1. Writer:
The Writer class is an abstract base class for writing characters to an output
stream. It provides various methods to write character data to a destination, like
a file or a network socket.
Example:
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
1. Reader:
The Reader class is an abstract base class for reading character data from an
input stream. It provides various methods to read characters from a source, such
as a file or a network socket.
Example:
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
1. FileWriter:
The FileWriter class is a subclass of Writer that writes characters to a file.
Example:
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
1. FileReader:
The FileReader class is a subclass of Reader that reads characters from a file.
Example:
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
1. BufferedWriter:
The BufferedWriter class is a subclass of Writer that adds buffering to improve
performance when writing large amounts of character data.
Example:
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
Example:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
1. CharArrayReader:
The CharArrayReader class is a subclass of Reader that reads characters from an
array of characters.
Example:
import java.io.CharArrayReader;
import java.io.IOException;
import java.io.Reader;
Example:
import java.io.CharArrayWriter;
import java.io.IOException;
import java.io.Writer;
1. PrintStream:
The PrintStream class provides convenient methods to print various data types
to an output stream, such as the console or a file.
Example:
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
1. PrintWriter:
The PrintWriter class is a subclass of Writer that provides convenient methods
to write various data types to an output stream.
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
.println("Bye!");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
1. OutputStreamWriter:
The OutputStreamWriter class is a subclass of Writer that bridges character
streams to byte streams. It converts character data into bytes using a specified
character encoding.
Example:
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
1. InputStreamReader:
The InputStreamReader class is a subclass of Reader that bridges byte streams to
character streams. It converts bytes from a byte stream into characters using a
specified character encoding.
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
1. PushbackInputStream:
The PushbackInputStream class is a subclass of FilterInputStream that allows
pushing back bytes into the stream, enabling one-byte "unreading."
Example:
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PushbackInputStream;
int dataByte;
while ((dataByte = pushbackInputStream.read()) != -1) {
if (dataByte == ',') {
pushbackInputStream.unread('!');
}
System.out.print((char) dataByte);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Example:
import java.io.CharArrayReader;
import java.io.IOException;
import java.io.PushbackReader;
import java.io.Reader;
int dataChar;
while ((dataChar = pushbackReader.read()) != -1) {
if (dataChar == ',') {
pushbackReader.unread('!');
}
System.out.print((char) dataChar);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
1. StringWriter:
The StringWriter class is a subclass of Writer that writes character data to an
internal string buffer.
Example:
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
1. StringReader:
The StringReader class is a subclass of Reader that reads characters from a
string.
Example:
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
1. PipedWriter:
The PipedWriter class is used to write data to a PipedReader , which can be read
by another thread.
Example:
import java.io.IOException;
import java.io.PipedReader;
import java.io.PipedWriter;
import java.io.Reader;
import java.io.Writer;
pipedWriter.write("Hello, PipedWriter!");
pipedWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
1. PipedReader:
The PipedReader class is used to read data from a PipedWriter , which is written
by another thread.
Example:
import java.io.IOException;
import java.io.PipedReader;
import java.io.PipedWriter;
import java.io.Reader;
import java.io.Writer;
int data;
while ((data = pipedReader.read()) != -1) {
System.out.print((char) data);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Example:
import java.io.FileWriter;
import java.io.FilterWriter;
import java.io.IOException;
import java.io.Writer;
1. FilterReader:
The FilterReader class is an abstract subclass of Reader that provides a base
class for filtering character input streams.
Example:
import java.io.CharArrayReader;
import java.io.FilterReader;
import java.io.IOException;
import java.io.Reader;
1. File:
The File class represents a file or directory pathname in the filesystem. It can
be used to manipulate files and directories, create new ones, and retrieve file
information.
Example:
import java.io.File;
1. FileDescriptor:
The FileDescriptor class represents an opaque handle to an open file, device, or
socket. It is used to manipulate low-level file operations.
Example:
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
1. RandomAccessFile:
The RandomAccessFile class allows random access to files. It provides methods to
read and write at a specific position within the file.
Example:
1. java.util.Scanner:
The Scanner class is used to parse primitive types and strings from a stream. It
provides methods to read input from various sources like files, strings, and the
console.
Example:
import java.util.Scanner;
These examples cover a wide range of I/O classes in Java, including reading and
writing to files, parsing input, filtering streams, and bridging between character and
byte streams. Remember that proper exception handling and resource management
Java Networking:
Java Networking provides classes and APIs to enable network communication in
Java applications. It allows Java programs to interact with remote systems, access
resources over the internet, and perform various networking tasks.
Networking Concepts:
Socket Programming:
Socket programming in Java allows applications to communicate over the network
using sockets. There are two types of sockets:
1. ServerSocket: It listens for incoming requests from clients and creates a new
socket for each client to handle the communication.
Server (ServerSocket):
import java.io.*;
import java.net.*;
Client (Socket):
import java.io.*;
import java.net.*;
URL class:
The URL class in Java represents a Uniform Resource Locator, which is a reference
to a web resource on the internet. It provides methods to parse, access, and
manipulate various components of a URL, such as the protocol, host, port, path,
query, and fragment.
Example:
import java.net.*;
URLConnection class:
The URLConnection class is an abstract class that represents a connection to a URL. It
provides methods to establish a connection, retrieve data from the URL, and
manage headers and cookies.
Example:
import java.io.*;
import java.net.*;
HttpURLConnection:
HttpURLConnection is a subclass of URLConnection specifically designed for handling
HTTP requests and responses. It provides methods to set request properties, send
data to the server, and read responses from the server.
Example:
import java.io.*;
import java.net.*;
connection.setRequestMethod("GET");
connection.setRequestProperty("Content-Type", "application/json");
InetAddress class:
Example:
import java.net.*;
DatagramSocket class:
The DatagramSocket class represents a UDP (User Datagram Protocol) socket for
sending and receiving datagrams. It provides methods to send and receive packets
of data without establishing a connection with the recipient.
Example:
import java.io.*;
import java.net.*;
These are some of the fundamental concepts and classes in Java Networking. By
utilizing these classes, Java applications can effectively communicate over the
network, retrieve resources from remote servers, and perform various networking
tasks.
1. Collection Interface: The root of the collection hierarchy. It defines the most
general methods applicable to all collections, such as add , remove , contains ,
etc.
2. Map Interface: It's not a child of Collection but also part of Collections
Framework. Maps store key-value pairs.
Collection Interface
It provides the standard functionality that every collection will have, like adding and
removing elements.
import java.util.*;
Iterator Interface
The Iterator interface provides a way to iterate through the collection, using methods
like next() , hasNext() , and remove() .
Here's an example of using an Iterator to loop through a collection:
import java.util.*;
while (iterator.hasNext()) {
String fruit = iterator.next();
System.out.println(fruit);
}
In this example, the iterator() method returns an Iterator, and you can then use
hasNext() to check if there are more elements, and next() to get the next element.
Overall, the Java Collections Framework offers a wide range of functionalities for
dealing with collections of objects, whether you need lists, sets, maps, or other
structures. It provides a unified architecture for representing and manipulating
collections, enabling them to be manipulated independently of the details of their
representation.
Collection Framework
The Collection Framework is the foundation of the Java Collections Framework and
consists of several interfaces and classes. It organizes collections into four major
interfaces: List, Set, Queue, and Map.
4. Map: A collection that stores key-value pairs and does not allow duplicate keys.
It is implemented by classes like HashMap , LinkedHashMap , and TreeMap .
Java ArrayList
ArrayList is a dynamic array implementation of the List interface. It allows you to
store elements in an ordered manner with dynamic resizing. When elements are
added to an ArrayList , it automatically grows to accommodate more elements.
import java.util.ArrayList;
Java LinkedList
LinkedList is another implementation of the List interface, but it differs from
ArrayList in terms of its underlying data structure. A LinkedList is composed of
nodes, where each node contains the data and a reference to the next node.
Example of creating a LinkedList :
import java.util.LinkedList;
LinkedList: Provides fast insertion and deletion in the middle of the list.
However, accessing elements by index is slower compared to ArrayList .
Choosing between ArrayList and LinkedList depends on the specific use case and
the type of operations you perform frequently.
import java.util.List;
import java.util.ArrayList;
Java HashSet
HashSet is an implementation of the Set interface that uses a hash table for storage.
It does not allow duplicate elements and does not guarantee the insertion order.
import java.util.HashSet;
Java LinkedHashSet
is an implementation of the Set interface that maintains the insertion
LinkedHashSet
order of elements, like a LinkedList . It uses a hash table with a linked list to achieve
this behavior.
import java.util.LinkedHashSet;
Java TreeSet
TreeSet is an implementation of the Set interface that stores elements in a sorted
order. It uses a red-black tree data structure for this purpose.
Example of using TreeSet :
import java.util.TreeSet;
import java.util.Deque;
import java.util.ArrayDeque;
Last("Bob");
deque.addLast("Charlie");
The Map interface includes methods such as put , get , remove , containsKey , and
containsValue .
Java HashMap
HashMap is one of the most commonly used implementations of the Map interface. It
uses a hash table to store key-value pairs. The keys are hashed to provide efficient
access to values. It allows null as both key and value, and it does not guarantee
the order of the elements.
Example of using HashMap :
import java.util.HashMap;
import java.util.Map;
System.out.println(ages.get("Bob")); // Output: 25
}
}
Working of HashMap
The working of a HashMap is based on the concept of hashing. When you put a key-
value pair into a HashMap , the key's hashCode() method is used to calculate a hash
value, which is then used to determine the bucket in which the key-value pair is
stored.
If multiple keys have the same hash value (collision), they are stored as a linked list
in the same bucket. In case the number of collisions becomes significant, the linked
list is converted into a balanced tree for better performance.
When you retrieve a value using a key from a HashMap , it calculates the hash value
for the key again and uses it to look up the corresponding bucket. If the key is found
Java LinkedHashMap
LinkedHashMap is an implementation of the Map interface that maintains the insertion
order of the keys. It is similar to HashMap , but it also maintains a doubly-linked list to
keep track of the order in which elements were added.
import java.util.LinkedHashMap;
import java.util.Map;
Java TreeMap
TreeMap is another implementation of the Map interface that stores key-value pairs in
a sorted order based on the natural ordering of the keys or a custom comparator. It
uses a red-black tree data structure for this purpose.
import java.util.TreeMap;
import java.util.Map;
Java Hashtable
import java.util.Hashtable;
import java.util.Map;
Null Keys and Values: HashMap allows null keys and null values, whereas
Hashtable does not allow either null keys or null values.
Iterating Order: HashMap does not guarantee the order of elements, whereas
Hashtable returns elements in the order they were inserted.
Legacy: Hashtable is part of the older Java Collections Framework and was
present before the introduction of the Map interface in Java 1.2. It is
recommended to use HashMap over Hashtable in modern Java applications unless
thread safety is explicitly required.
In summary, both HashMap and Hashtable are implementations of the Map interface,
but HashMap is the preferred choice for most use cases in modern Java applications
Java EnumSet
EnumSet is a specialized collection class in Java that is designed to work with enums.
It is part of the java.util package and is used to represent a set of elements of a
specific enumeration type. EnumSet is highly efficient and optimized for enums,
offering better performance than other general-purpose set implementations.
Example of using EnumSet :
import java.util.EnumSet;
enum Days {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
Java EnumMap
EnumMap is another specialized collection class that is designed to work with enums.
It implements the Map interface and is used to represent a map with enum keys and
associated values. Like EnumSet , EnumMap is optimized for enums, offering high
performance and memory efficiency.
import java.util.EnumMap;
import java.util.Map;
enum Days {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
Collections class
The Collections class in Java is a utility class in the java.util package that provides
various static methods to work with collections. It contains methods for performing
common operations on collections such as sorting, searching, shuffling, and creating
unmodifiable collections.
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
Collections.sort(fruits);
Sorting Collections
As shown in the previous example, the Collections class provides a method sort()
to sort elements in a collection. The sort() method uses the natural ordering of
elements (if they implement the Comparable interface) or a custom Comparator to
determine the sorting order.
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
Comparable interface
The Comparable interface in Java is used to define the natural ordering of objects. If a
class implements the Comparable interface, it must override the compareTo() method,
which defines how the object should be compared with another object of the same
type.
Example of implementing the Comparable interface:
@Override
public int compareTo(Student other) {
return this.name.compareTo(other.name);
}
}
Comparator interface
The Comparator interface in Java is used to define custom comparison logic for
objects that do not implement the Comparable interface or when you need an
alternative sorting order. A Comparator object can be passed to sorting methods like
Collections.sort() to determine the sorting order.
Comparable: It defines the natural ordering of objects within the class itself. The
compareTo() method is implemented in the class whose objects need to be
sorted.
When you want to define a default or natural ordering for objects of a class.
The class is not modifiable, or you want to define a single, consistent sorting
order for the class.
When you need to define multiple sorting orders for objects of a class.
When you want to sort objects based on different criteria, depending on the
context.
The class you are sorting is not modifiable, and you cannot implement
Comparable in it.
In summary, Comparable is used when you want to define the natural ordering of
objects within the class itself, while Comparator is used when you need to define
external comparison logic or multiple sorting orders for objects of a class.
Properties class
The Properties class in Java is a subclass of Hashtable that represents a persistent
set of properties in key-value pairs. It is often used to manage configuration settings
in Java applications. The keys and values in a Properties object are both strings.
import java.util.Properties;
Legacy: Vector is part of the older Java Collections Framework and was
present before the introduction of the List interface in Java 1.2. ArrayList is the
preferred choice in modern Java applications unless thread safety is explicitly
required.
Java Vector
is a class in Java that is part of the legacy Java Collections Framework. It
Vector
implements the List interface and is similar to ArrayList , but with the added feature
of being synchronized, which makes it thread-safe.
Example of using Vector :
import java.util.Vector;
Java Stack
Stack is a class in Java that represents a last-in-first-out (LIFO) stack of objects. It
extends the Vector class and provides additional methods like push() to add
elements to the stack and pop() to remove elements from the top of the stack.
Example of using Stack :
import java.util.Stack;
The Collection interface includes common methods like add , remove , contains ,
size , isEmpty , and iterator .
import java.util.Collection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.Deque;
import java.util.ArrayDeque;
Java ConcurrentHashMap
ConcurrentHashMap is a class in Java that is part of the Java Concurrency Utilities. It is
a highly efficient and thread-safe version of a HashMap . It allows multiple threads to
read and write concurrently without external synchronization, while still maintaining
data consistency.
import java.util.concurrent.ConcurrentHashMap;
System.out.println(ages.get("Charlie")); // Output: 35
}
}
Java ConcurrentLinkedQueue
ConcurrentLinkedQueue is a class in Java that is part of the Java Concurrency Utilities.
It is a thread-safe implementation of the Queue interface, suitable for concurrent use
by multiple threads.
Example of using ConcurrentLinkedQueue :
import java.util.concurrent.ConcurrentLinkedQueue;
In summary, these classes and interfaces in the Java Collections Framework provide
a powerful and flexible way to work with collections and handle various concurrency
scenarios. Whether you need a synchronized list, a thread-safe map, or a concurrent
queue, the Java Collections Framework has appropriate classes to suit your needs.