OOPS USING JAVA Unit-4
OOPS USING JAVA Unit-4
Collection in Java:-
What are Collections in Java?
Collections in Java are classes and interfaces that help you manage and manipulate groups of
objects. They are part of the Java Collections Framework (JCF), which provides a
standardized way to work with collections.
1. **Interfaces:** Collections in Java are represented by interfaces like `List`, `Set`, and
`Map`. These interfaces define how elements can be added, accessed, and removed from the
collection.
2. **List:** A `List` is an ordered collection that allows duplicate elements. You can add
elements at specific positions, retrieve elements by index, and perform operations like sorting
and searching.
3. **Set:** A `Set` is a collection that does not allow duplicate elements. It ensures
uniqueness among its elements. Common implementations include `HashSet`, `TreeSet`, and
`LinkedHashSet`.
4. **Map:** A `Map` is a collection that stores key-value pairs. Each key is unique, and it
maps to a corresponding value. `HashMap`, `TreeMap`, and `LinkedHashMap` are common
implementations of the `Map` interface.
6. **Generics:** Java collections support generics, allowing you to specify the type of
elements they can hold. This helps in type safety and avoids runtime errors.
8. **Utility Classes:** The `Collections` class provides various utility methods like sorting
(`sort()`), finding minimum and maximum elements (`min()` and `max()`), and creating read-
only collections (`unmodifiableCollection()`).
### Example:
```
import java.util.ArrayList;
import java.util.List;
In this example:
- We import the ArrayList and List classes from the java.util package.
- We create an ArrayList called `namesList` to store strings.
- We add three names to the list: "Alice", "Bob", and "Charlie".
- We use a for-each loop to print each name in the list.
### Summary:
Collections in Java provide powerful tools for managing groups of objects. They come in
different types like lists, sets, and maps, each serving specific purposes. Using collections
makes it easier to work with data structures in your Java programs.
Collection Framework in Java:-
The Collection Framework in Java is like a toolbox that provides a set of pre-built tools
(classes and interfaces) for managing groups of objects efficiently. Here's a detailed
explanation in easy language:
1. **Interfaces:** The Collection Framework starts with interfaces like `Collection`, `List`,
`Set`, `Map`, etc. These interfaces define common behaviors for collections, such as adding,
removing, and iterating over elements.
2. **Classes:** Java provides various classes that implement these interfaces. For example,
`ArrayList` and `LinkedList` implement the `List` interface, `HashSet` and `TreeSet`
implement the `Set` interface, and `HashMap` and `TreeMap` implement the `Map` interface.
3. **Hierarchy:** The interfaces and classes form a hierarchy. At the top is the `Collection`
interface, which is the root interface for all collection types. It defines basic operations like
adding, removing, and checking for the presence of elements.
4. **Lists:** Lists maintain elements in a specific order, allowing duplicates. They provide
methods for accessing elements by index (`get(int index)`), adding elements at specific
positions (`add(int index, E element)`), and more.
5. **Sets:** Sets are collections that do not allow duplicate elements. They provide methods
for adding elements (`add(E element)`), removing elements (`remove(Object obj)`), and
checking for element existence (`contains(Object obj)`).
6. **Maps:** Maps store key-value pairs. They provide methods for adding (`put(K key, V
value)`), getting (`get(Object key)`), and removing (`remove(Object key)`) entries based on
keys.
7. **Iterators:** Iterators are used to traverse collections. They provide methods like
`hasNext()` to check if there are more elements and `next()` to retrieve the next element in the
collection.
8. **Utility Classes:** Java also provides utility classes like `Collections` and `Arrays` that
offer methods for sorting, searching, and manipulating collections and arrays efficiently.
1. **Interfaces**:
- **List**: Allows storing elements in a specific order. Examples include ArrayList and
LinkedList.
- **Set**: Stores unique elements, ensuring no duplicates. Examples include HashSet and
TreeSet.
- **Queue**: Represents a collection used for holding elements before processing.
Examples include PriorityQueue and LinkedList.
- **Map**: Maps keys to values, where each key is unique. Examples include HashMap
and TreeMap.
2. **Classes**:
- **ArrayList**: Implements the List interface, allowing dynamic resizing of arrays to store
elements.
- **LinkedList**: Implements the List interface using a doubly linked list, allowing for
efficient insertions and deletions.
- **HashSet**: Implements the Set interface using a hash table for storing elements,
ensuring uniqueness.
- **TreeSet**: Implements the Set interface using a tree structure, providing elements in
sorted order.
- **HashMap**: Implements the Map interface using a hash table for key-value pairs,
allowing quick retrieval based on keys.
- **TreeMap**: Implements the Map interface using a red-black tree, providing sorted key-
value pairs.
3. **Example**:
Let's create a simple example using ArrayList and HashMap:
```
import java.util.ArrayList;
import java.util.HashMap;
In this example, we use ArrayList to store integers and HashMap to store student names
with their scores. This showcases how we can use different collections to manage different
types of data efficiently.
Overall, the Collection Framework in Java provides a powerful way to handle data structures
and operations in an object-oriented manner, making it easier to work with collections of
objects in Java programs.
2. **List Interface**: This interface extends the Collection interface. Lists are ordered
collections of elements where each element has an index. You can access elements by their
index, and duplicate elements are allowed in lists.
3. **Set Interface**: Another sub-interface of Collection, Sets are collections that do not
allow duplicate elements. They ensure uniqueness among the elements they contain.
5. **Deque Interface**: Short for "Double Ended Queue," this interface extends Queue and
supports element insertion and removal at both ends. It can function as both a queue and a
stack.
6. **Map Interface**: Unlike collections, maps store elements in key-value pairs. Each key
in a map is associated with a single value. Maps do not extend the Collection interface but are
an essential part of the Collection Framework.
7. **SortedSet Interface**: Extending Set, this interface ensures that elements are stored in
sorted order. The sorting is typically based on either natural ordering (if elements implement
Comparable) or a Comparator.
9. **SortedMap Interface**: Similar to SortedSet, this interface extends Map and ensures
that the keys are stored in sorted order. Again, the sorting can be based on natural ordering or
a Comparator.
2. **Map Interface**:
- **Map**: Represents a mapping between keys and values.
- **HashMap**: Implements Map using a hash table for key-value pairs. It provides
constant-time performance for basic operations but doesn't guarantee the order of entries.
- **LinkedHashMap**: Extends HashMap and maintains the order of entries based on
insertion.
- **TreeMap**: Implements Map using a red-black tree, providing ordered entries based
on keys' natural ordering or a custom Comparator.
```
import java.util.*;
This example creates and uses an ArrayList, HashSet, and TreeMap, demonstrating how
elements can be added and manipulated in different types of collections.
Iterator Interface:-
The Iterator Interface in Java is a tool that helps you move through a collection of objects,
like lists or sets, one item at a time. It's like having a pointer that points to the current position
in the collection. Here's a detailed breakdown:
1. **Purpose**: The Iterator Interface is used when you want to access elements from a
collection sequentially, without worrying about the underlying structure of the collection.
2. **Methods**:
- `boolean hasNext()`: This method checks if there are more elements in the collection to
iterate over. It returns `true` if there are more elements, and `false` otherwise.
- `E next()`: This method returns the next element in the collection and moves the iterator
forward by one position.
- `void remove()`: This method removes the last element returned by the iterator from the
underlying collection. It's optional to implement and is usually used to remove elements
safely during iteration.
3. **Usage**:
- **Initialization**: You start by creating an iterator object for your collection using the
`iterator()` method provided by collection classes like ArrayList or HashSet.
- **Iteration**: You use a loop, often a while loop, along with `hasNext()` and `next()`
methods to iterate through the collection until there are no more elements.
- **Optional Removal**: If you need to remove elements while iterating, you can use the
`remove()` method. However, this is not always required.
4. **Benefits**:
- **Simplified Iteration**: It provides a simple way to iterate over collections without
needing to know the internal structure of the collection.
- **Safe Removal**: It allows safe removal of elements during iteration without causing
issues like concurrent modification exceptions.
5. **Considerations**:
- **Concurrent Modification**: If the underlying collection is modified while iterating
using an iterator (other than through the iterator's own `remove()` method), it can lead to
concurrent modification exceptions.
- **Single-Directional**: Iterators typically move forward only. If you need to iterate
backward or in a more complex manner, other techniques or custom iterators may be needed.
In essence, the Iterator Interface is a handy tool for sequentially accessing and processing
elements in collections in Java, making your code more organized and efficient when dealing
with collections.
1. **What is an Iterator?**
An Iterator is like a tool that helps you go through each item in a collection, one by one.
```
import java.util.ArrayList;
import java.util.Iterator;
In this example:
- We create an ArrayList called `names` and add some names to it.
- Then, we create an Iterator called `iterator` for the `names` ArrayList using `iterator()`.
- We use `hasNext()` to check if there are more names in the ArrayList, and `next()` to get
each name and print it.
5. **Why is it useful?**
Iterators are handy because they let you go through collections without worrying about their
internal structure. This makes your code more flexible and easier to maintain.
In summary, the Iterator Interface in Java is a tool that helps you traverse through collections
step by step, making it easier to work with elements without exposing the collection's
implementation details.
Collection Interface:-
The Collection Interface in Java is like a blueprint or a contract that defines how a group of
objects can be managed and manipulated. It's part of the Java Collections Framework, which
provides a set of classes and interfaces to work with collections of objects. Collections can
store objects of any type, including primitive types.
1. **Basic Purpose:** The Collection Interface is used to represent a group of objects known
as a collection. These objects could be of any type, such as integers, strings, or custom
objects.
2. **Common Operations:** It defines several common operations that you can perform on
collections, such as adding elements, removing elements, checking if an element exists, and
retrieving elements.
3. **Extensibility:** Many classes in Java, such as ArrayList and LinkedList, implement the
Collection Interface. This means you can use these classes interchangeably wherever the
Collection Interface is expected, making your code more flexible and reusable.
4. **No Specific Ordering:** Unlike some collection types like lists, the Collection Interface
doesn't guarantee any specific ordering of elements. It focuses more on the group of elements
rather than their order.
5. **Dynamic Size:** Collections can grow or shrink dynamically based on the elements you
add or remove. This makes them very flexible for managing varying amounts of data.
6. **Iterable:** The Collection Interface extends the Iterable Interface, which means you can
iterate over the elements in a collection using enhanced for loops or iterators.
```
import java.util.ArrayList;
import java.util.Collection;
The Collection Interface provides a flexible and standardized way to work with collections in
Java, making it easier to manage and manipulate groups of objects in your programs.
List Interface:-
The List Interface in Java is part of the Collection Framework and is used to store a collection
of elements in a specific order, allowing duplicate elements. Here are some key points about
the List Interface:
1. **Ordered Collection:** Lists maintain the order of elements as they are inserted. This
means you can retrieve elements in the same order you added them.
2. **Allows Duplicates:** Unlike some other collections, lists allow you to store duplicate
elements. This means you can have the same element multiple times in a list.
3. **Indexed Access:** Each element in a list has an index, starting from 0 for the first
element. This allows you to access elements by their position in the list.
4. **Dynamic Size:** Lists can grow or shrink dynamically as you add or remove elements.
You don't need to specify the size of a list upfront.
7. **ArrayList:** It's a resizable array implementation of the List Interface. It's good for
random access and fast iteration but may be slower for adding or removing elements in the
middle.
8. **LinkedList:** It's a doubly linked list implementation of the List Interface. It's good for
frequent insertions and deletions in the middle of the list but may be slower for random
access.
9. **Vector:** It's similar to ArrayList but is synchronized, meaning it's thread-safe for use in
concurrent environments. However, this synchronization can introduce some performance
overhead.
1. **Interface Concept:**
- The List Interface is like a blueprint that defines how a list should behave.
- It's part of Java's Collection Framework, which provides a set of classes and interfaces to
work with collections of objects.
```
import java.util.ArrayList;
import java.util.List;
// Updating an element
namesList.set(2, "David");
System.out.println("Updated Names List: " + namesList);
// Removing an element
namesList.remove("Alice");
System.out.println("Names List after removal: " + namesList);
}
}
```
In this example, the List Interface (`ArrayList`) helps us manage a list of names efficiently by
providing methods to add, retrieve, update, and remove elements.
ArrayList:-
What is ArrayList?
An ArrayList in Java is a resizable array implementation of the List interface. It allows you to
store and manipulate a collection of elements in a dynamic and flexible manner.
Here’s a detailed explanation without an example:
1. **Dynamic Sizing:** Unlike regular arrays in Java that have a fixed size, an ArrayList can
change its size dynamically. You can add or remove elements without worrying about the
array's initial size.
3. **Generics:** ArrayLists in Java use generics, which allow you to specify the type of
elements the ArrayList will hold. For example, `ArrayList<Integer>` means it will hold
integer values only.
4. **Indexed Access:** You can access elements in an ArrayList using their index. The first
element is at index 0, the second at index 1, and so on. This makes it easy to retrieve and
manipulate specific elements.
5. **Methods for Manipulation:** ArrayList provides various methods for adding, removing,
and manipulating elements. For instance, `add()` adds an element, `remove()` removes an
element, `size()` gives the number of elements, and `get()` retrieves an element at a specific
index.
6. **Iterating Through Elements:** You can iterate through an ArrayList using loops like for-
each or traditional for loops. This allows you to perform operations on each element in the
ArrayList.
7. **Ordered Collection:** ArrayList maintains the order in which elements are added. If you
add elements in a specific order, they will remain in that order unless you explicitly change it.
8. **Null Elements:** Unlike arrays, ArrayList can contain null elements. This can be useful
when you need to represent an absence of value in your collection.
1. **Resizable Array**: Unlike traditional arrays in Java that have a fixed size, ArrayList can
grow and shrink dynamically as elements are added or removed.
2. **List Interface Implementation**: ArrayList implements the List interface, which means
it supports operations like adding, removing, accessing elements by index, and more.
```
import java.util.ArrayList;
In this example:
This example demonstrates basic operations like adding, accessing, removing elements,
checking for emptiness, and getting the size of an ArrayList in Java.
LinkedList:-
A LinkedList in Java is a type of data structure that organizes elements in a sequence, similar
to an array. However, unlike arrays, which store elements in contiguous memory locations,
LinkedLists store elements as nodes where each node contains the data and a reference (or
link) to the next node in the sequence.
2. **Dynamic Size**: LinkedLists can grow or shrink dynamically because each node only
needs to know about the next node, not the entire sequence.
4. **Traversal**: To traverse a LinkedList, you start from the first node (known as the head)
and follow the next references until you reach the end (where the next reference is null). This
traversal can be done iteratively or recursively.
5. **Access Time**: While insertion and deletion are efficient, direct access to elements by
index (like in arrays) is slower in LinkedLists because you have to traverse the list to find the
desired element.
A LinkedList in Java is a type of data structure that organizes elements in a sequence, similar
to an array. However, unlike arrays, LinkedLists don't store elements in contiguous memory
locations. Instead, each element in a LinkedList contains a reference to the next element in
the sequence, forming a chain-like structure.
Here's a deeply detailed explanation of LinkedList in easy language with an example:
1. **Node Structure:** In a LinkedList, each element is called a "node." Each node contains
two parts:
- Data: This is the actual value or information stored in the node.
- Pointer (or Reference): This points to the next node in the sequence. In the last node, this
pointer is null, indicating the end of the list.
2. **Dynamic Size:** LinkedLists can grow or shrink dynamically because each node only
needs to know about its immediate neighbor.
3. **Traversal:** To traverse a LinkedList, you start from the first node (head) and follow the
pointers until you reach the end (null).
### Example:
```
import java.util.LinkedList;
// Removing an element
numbers.remove(2);
Output:
```
LinkedList: [10, 20, 30]
Modified LinkedList: [10, 15, 20, 30]
Final LinkedList: [10, 15, 30]
```
In this example:
- We create a LinkedList called `numbers`.
- Add elements 10, 20, and 30 to the list.
- Insert element 15 at index 1 (between 10 and 20).
- Remove element at index 2 (which is 20).
- Print the final LinkedList after modifications.
This demonstrates how LinkedLists can be easily modified by adding, inserting, or removing
elements, and how they maintain the sequence of elements using pointers.
Vector:-
In object-oriented programming using Java, a Vector is a data structure that stores elements in
an ordered sequence. Here's a detailed explanation:
2. **Resizable Array:** Internally, a Vector uses an array to store elements. It starts with a
default size, and as elements are added, it automatically grows to accommodate more
elements. This resizing is handled efficiently, ensuring optimal performance.
3. **Dynamic Capacity:** Unlike arrays with fixed sizes, Vectors can dynamically increase
their capacity as needed. When the number of elements exceeds the current capacity, the
Vector automatically reallocates memory to accommodate more elements.
4. **Thread-Safe Operations:** One of the key features of Vectors is their thread safety. All
operations on a Vector, such as adding, removing, or accessing elements, are synchronized.
This means that only one thread can access the Vector at a time, preventing data corruption or
inconsistent states.
5. **Iterable and Serializable:** Vectors implement the Iterable interface, allowing you to
easily iterate over their elements using enhanced for loops or iterators. They are also
Serializable, meaning they can be serialized and deserialized, making them suitable for data
storage or transmission.
6. **Legacy Collection:** While Vectors provide thread safety, their synchronization
overhead can impact performance in highly concurrent applications. For modern Java
development, ArrayLists are often preferred due to their better performance in non-threaded
scenarios. Vectors are considered a legacy collection in Java.
In Java, a `Vector` is a type of dynamic array that can grow or shrink in size as needed. It's
part of the Collection Framework and is similar to an ArrayList but is synchronized, which
means it's thread-safe for use in multi-threaded applications. Here's a detailed explanation in
easy language with an example:
1. **Dynamic Size:**
- A Vector can change its size dynamically, meaning you can add or remove elements from
it at runtime without specifying its size beforehand.
2. **Thread-Safe:**
- Vectors are synchronized, which means they are safe to use in multi-threaded
environments where multiple threads might access or modify the Vector simultaneously.
3. **Implementation:**
- Internally, a Vector uses an array to store elements. When elements are added and the
Vector exceeds its capacity, it automatically increases its size by allocating a new array and
copying the elements.
4. **Methods:**
- Vectors provide methods to add, remove, get, and modify elements. They also support
iteration using loops like for-each or traditional for loops.
### Example:
```
import java.util.Vector;
// Displaying elements
System.out.println("Names in the Vector:");
for (String name : names) {
System.out.println(name);
}
// Adding a new element
names.add("David");
// Removing an element
names.remove("Bob");
In this example, we create a Vector of Strings, add elements to it, remove an element, and
then display the updated elements. Vectors are handy when you need a resizable array that
can be used safely in concurrent applications.
Stack:-
In object-oriented programming using Java, a stack is a data structure that follows the Last-
In-First-Out (LIFO) principle. Here's a detailed explanation in easy language:
1. **What is a Stack?**
- A stack is like a stack of plates where you can only add or remove plates from the top.
- In programming, it's a collection of elements (like numbers, characters, or objects) where
you can only add new elements or remove the most recently added one.
3. **Operations on a Stack:**
- **Push:** Adding an element to the top of the stack. It's like putting a new book on top of
the stack of books.
- **Pop:** Removing the top element from the stack. It's like taking the top book from the
stack.
- **Peek:** Looking at the top element without removing it. It's like checking which book
is on top of the stack without taking it out.
4. **Real-World Example:**
- Think of a stack of trays in a cafeteria. When you take a tray, you take the one from the
top (pop operation).
- When new trays come in, they are added on top of the stack (push operation).
- If you want to know which tray is on top without taking it, you peek at the top of the
stack.
5. **Why Use a Stack?**
- Stacks are handy for tasks that follow a last-in-first-out order, like managing function calls
in programming.
- They help in managing memory efficiently because elements are added and removed in a
predictable order.
1. **Stack Operations**:
- `push(element)`: Adds an element to the top of the stack.
- `pop()`: Removes and returns the top element from the stack.
- `peek()`: Returns the top element without removing it.
- `isEmpty()`: Checks if the stack is empty.
- `size()`: Returns the number of elements in the stack.
2. **Example Code**:
```
import java.util.Stack;
**Output**:
```
Stack: [10, 20, 30]
Removed Element: 30
Stack after removal: [10, 20]
Top Element: 20
Is Stack Empty? false
Stack Size: 2
```
In this example, we create a stack using the `Stack` class, add elements to it, remove an
element, peek at the top element, check if it's empty, and get its size. This demonstrates the
basic operations of a stack in Java.
Queue Interface:-
The Queue Interface in Java is part of the Collection Framework and represents a collection
of elements that follow the First-In-First-Out (FIFO) principle. Here's a detailed explanation
in easy language:
1. **What is a Queue?**
- A queue is like a line at a store where the first person to join the line is the first to be
served. Similarly, in programming, a queue is a data structure that works on the principle of
FIFO, which stands for First-In-First-Out.
2. **Purpose of a Queue:**
- Queues are used when you need to maintain the order of elements based on when they
were added. For example, in a print queue, the document that was sent to print first should be
printed first.
3. **Key Operations:**
- Queues typically support operations like adding elements at the end (enqueue) and
removing elements from the front (dequeue). These operations ensure that elements are
processed in the order they were added.
5. **Types of Queues:**
- There are different types of queues based on how they handle elements. For example, a
priority queue may process elements based on their priority rather than the order they were
added.
6. **Underlying Implementation:**
- Queues can be implemented using various data structures such as arrays or linked lists.
The choice of implementation depends on factors like the expected size of the queue and the
required efficiency of operations.
7. **Use Cases:**
- Queues are used in scenarios like task scheduling, job processing, event handling, and
network packet management, where maintaining order and fairness in processing is crucial.
8. **Thread Safety:**
- In multi-threaded environments, concurrent queues ensure that operations like enqueue
and dequeue are thread-safe, preventing data corruption when multiple threads access the
queue simultaneously.
1. **Addition Order:** You can add elements to a Queue using the `add()` method. This adds
elements to the end of the queue, just like people joining the line at the store.
2. **Removal Order:** When you want to remove elements from the Queue, you use the
`remove()` method. This removes the first element that was added to the queue, similar to
serving the first person in line at the store.
3. **Peek:** Sometimes, you might want to see who's at the front of the line without
removing them. You can do this using the `peek()` method in Java. It lets you look at the first
element without actually taking them out of the queue.
4. **Size:** You can find out how many elements are in the Queue using the `size()` method.
This is like counting how many people are in line at the store.
5. **Empty Check:** If you want to know if the Queue is empty or not, you can use the
`isEmpty()` method. It returns true if there are no elements in the queue, just like seeing if
there's anyone in line at the store.
6. **Poll:** Another way to remove elements from the Queue is by using the `poll()` method.
It works like `remove()`, but if the Queue is empty, it returns null instead of throwing an
exception.
7. **Iteration:** You can also iterate through the elements in a Queue using iterators or the
enhanced for loop in Java. This lets you process each element in the order they were added.
Overall, the Queue Interface in Java is useful for managing elements in a FIFO order, making
it great for tasks where you need to process things in the order they were added, like
processing tasks in a to-do list or managing incoming requests in a server.
1. **`add(element)` / `offer(element)`**:
- Both methods add an element to the end of the queue.
- `add(element)` throws an exception if the queue is full, while `offer(element)` returns
`false` if the queue is full.
2. **`remove()` / `poll()`**:
- Both methods remove and return the element at the front of the queue.
- `remove()` throws an exception if the queue is empty, while `poll()` returns `null` if the
queue is empty.
3. **`element()` / `peek()`**:
- Both methods return the element at the front of the queue without removing it.
- `element()` throws an exception if the queue is empty, while `peek()` returns `null` if the
queue is empty.
```
import java.util.LinkedList;
import java.util.Queue;
In this example:
- We create a Queue using the LinkedList class.
- We add elements "Apple", "Banana", and "Cherry" to the queue.
- We remove the front element using `remove()` and check the front element using `peek()`.
This demonstrates basic operations like adding, removing, and peeking elements in a Queue
using Java's Queue interface.
Set Interface:-
The Set interface in Java is part of the Java Collections Framework and represents a
collection of unique elements. Here are some detailed explanations about the Set interface:
1. **Uniqueness**: A Set does not allow duplicate elements. If you try to add an element that
already exists in the Set, the addition operation will return false and the Set will remain
unchanged.
2. **Ordering**: Sets do not guarantee any specific order of elements. Unlike lists, where
elements are stored in a specific order, Sets focus on uniqueness rather than order.
4. **Hashing**: HashSet, for example, uses hashing techniques to store elements efficiently.
It internally uses a hash table to store elements, which allows for constant-time performance
for basic operations like add, remove, and contains.
5. **Sorted Sets**: If you need a Set with a specific ordering, you can use TreeSet, which
implements the SortedSet interface. TreeSet maintains elements in sorted order, either
according to their natural ordering or a custom comparator provided by the user.
6. **Set Operations**: Sets support various operations common to mathematical sets, such as
union, intersection, difference, and subset checks. These operations are useful when working
with sets of data and performing set-based computations.
7. **Immutability**: The Set interface itself does not provide methods to modify the
structure of the Set (add or remove elements) directly. Instead, it focuses on defining
operations for manipulating sets as a whole, such as checking for containment, equality, and
size.
8. **Use Cases**: Sets are commonly used in scenarios where uniqueness is essential, such
as maintaining a collection of unique identifiers, eliminating duplicate entries from data, or
performing set-based computations in algorithms.
9. **No Specific Order:** Unlike some other collection types like Lists, Sets do not maintain
a specific order of elements. This means that the elements in a Set are not stored in the order
in which they were added.
11. **Implementations of Set:** There are several classes that implement the Set interface in
Java, such as HashSet, TreeSet, and LinkedHashSet. Each implementation has its own
characteristics regarding performance, ordering, and uniqueness of elements.
12. **HashSet:** This implementation uses a hash table for storage. It does not guarantee the
order of elements and allows null elements.
13. **TreeSet:** Elements in a TreeSet are sorted in natural order (if they implement
Comparable) or according to a Comparator provided at set creation time. It does not allow
null elements.
In summary, the Set interface in Java provides a way to store a collection of unique elements
without a specific order. It offers methods for adding, removing, and checking elements in the
set, and there are different implementations of Sets with varying characteristics.
HashSet:-
A HashSet in Java is a class that implements the Set interface. It's called a "hash" set because
it uses hashing to store its elements. Here's a deeper explanation in easy language:
1. **What is a Set?**
A Set is a collection in Java that does not allow duplicate elements. It's like a bag where you
can put things, but each thing you put in the bag must be unique.
2. **How does HashSet work?**
When you add an element to a HashSet, it uses a hash function to compute a hash code for
that element. This hash code is like a unique identifier for the element. The HashSet then
stores the element based on its hash code.
5. **Unique Elements:**
HashSet ensures that each element in the set is unique. If you try to add a duplicate element,
HashSet will ignore it because it's already present.
6. **Ordering:**
HashSet does not guarantee the order of elements. The elements are stored in a way that
optimizes retrieval and manipulation but may not follow a specific order like lists or arrays.
7. **Performance:**
HashSet provides constant-time performance (O(1)) for basic operations like adding,
removing, and checking containment. However, iterating over a HashSet may not have a
predictable order due to its hashing mechanism.
A HashSet in Java is a collection that stores unique elements. It is part of the Java Collections
Framework and implements the Set interface, which means it doesn't allow duplicate
elements. Here's a detailed breakdown:
1. **What is a HashSet?**
- A HashSet is a collection class in Java that stores elements using a hashing mechanism.
- It ensures that each element is unique, meaning no duplicates are allowed.
- HashSet does not guarantee the order of elements, as it does not maintain the insertion
order.
// Removing an element
fruitSet.remove("Orange");
In this example, we create a HashSet called `fruitSet` to store fruit names. Notice that adding
"Apple" again doesn't change the HashSet because it ignores duplicates. We check if
"Banana" is present and then remove "Orange" from the HashSet.
Overall, HashSet is a useful data structure in Java for maintaining unique collections of
elements efficiently.
LinkedHashSet:-
LinkedHashSet is a class in Java that extends HashSet and implements the Set interface. It
combines the features of a HashSet and a LinkedList, providing a collection that is both
unordered like HashSet and allows for predictable iteration order like LinkedList.
1. **HashSet**:
- A `HashSet` is a collection that stores elements in a hash table, which allows for fast
retrieval of elements.
- It does not guarantee the order of elements, meaning the elements are not stored in any
particular sequence.
2. **Linked List**:
- A linked list is a data structure where each element is linked to the next element, forming a
chain-like structure.
- This structure allows for maintaining the order of elements in the list.
2. **Ordering:** Unlike HashSet, which does not guarantee any specific order of elements,
LinkedHashSet maintains the order of elements as they are inserted into the set. This order is
predictable and remains constant unless elements are added or removed.
5. **Usage:** LinkedHashSet is useful when you need a set that preserves the insertion order
of elements and also requires fast access for operations like add, remove, and contains.
```
import java.util.LinkedHashSet;
// Removing an element
linkedHashSet.remove("Cherry");
SortedSet Interface:-
The `SortedSet` interface in Java is a part of the Java Collections Framework and extends the
`Set` interface. It maintains a sorted order of its elements based on a specified comparator or
their natural ordering if no comparator is provided. Here's a detailed explanation in easy
language:
1. **SortedSet Basics**:
- A SortedSet is like a regular Set but with an added feature: it maintains its elements in a
sorted order.
- This sorting is based on the natural ordering of elements or a custom Comparator that you
can specify.
2. **Unique Elements**:
- Like other Set implementations, a SortedSet does not allow duplicate elements. Each
element in a SortedSet is unique.
3. **Ordering**:
- The order of elements in a SortedSet is determined either by the natural ordering of its
elements (if they implement the Comparable interface) or by a Comparator that you provide.
- If you use natural ordering, elements are sorted according to their natural ordering, such as
alphabetical order for strings or numerical order for numbers.
- If you provide a Comparator, the SortedSet uses that Comparator to determine the order of
elements.
4. **Methods**:
- SortedSet inherits methods from its parent interfaces like Set and Collection. These
include methods for adding, removing, checking the presence of elements, and more.
- Additionally, SortedSet provides methods specific to sorted operations, such as retrieving
the first and last elements, finding elements based on their order, and getting a subset of
elements within a specified range.
5. **Performance**:
- SortedSet implementations like TreeSet typically offer efficient performance for
operations like adding, removing, and retrieving elements in sorted order.
- The underlying data structure used by SortedSet implementations (often a balanced tree
structure) ensures that elements are efficiently organized and accessed according to their
order.
6. **Use Cases**:
- SortedSet is useful when you need to maintain a collection of elements in sorted order
without duplicates.
- It's commonly used in scenarios where you need to work with sorted data, such as
managing a list of names in alphabetical order or storing scores in numerical order.
1. **Interface Overview**:
- The `SortedSet` interface ensures that the elements in the set are sorted either in their
natural order or according to a custom comparator.
- It does not allow duplicate elements.
- This interface provides methods for operations such as adding, removing, and retrieving
elements from the set, as well as navigation through the sorted set.
2. **Key Methods**:
- `Comparator<? super E> comparator()`: Returns the comparator used to order the
elements in the set, or `null` if the set uses the natural ordering of its elements.
- `E first()`: Returns the first (lowest) element in the sorted set.
- `E last()`: Returns the last (highest) element in the sorted set.
- `SortedSet<E> headSet(E toElement)`: Returns a view of the portion of the set whose
elements are less than `toElement`.
- `SortedSet<E> tailSet(E fromElement)`: Returns a view of the portion of the set whose
elements are greater than or equal to `fromElement`.
- `SortedSet<E> subSet(E fromElement, E toElement)`: Returns a view of the portion of the
set whose elements range from `fromElement` (inclusive) to `toElement` (exclusive).
3. **Example**:
```
import java.util.*;
In the example, we create a `SortedSet` using `TreeSet`, which automatically sorts elements
in their natural order (alphabetical for strings). We then demonstrate various methods like
`first()`, `last()`, `headSet()`, `tailSet()`, and `subSet()` to work with the sorted set's elements
efficiently.
TreeSet:-
What is TreeSet?
A TreeSet in Java is a class that implements the SortedSet interface and uses a tree-like data
structure to store elements. It maintains the elements in sorted order, which makes it efficient
for operations like searching, insertion, and deletion.
1. **Set Interface:**
- Sets are collections that do not allow duplicate elements. In other words, each element in a
set must be unique.
- The Set interface provides methods for adding, removing, checking the presence of
elements, and more. It does not guarantee the order of elements.
2. **SortedSet Interface:**
- The SortedSet interface extends Set and adds functionality for maintaining elements in
sorted order.
- Elements in a SortedSet are sorted either in their natural order (if they implement the
Comparable interface) or using a Comparator.
3. **TreeSet Class:**
- TreeSet is a class that implements SortedSet.
- It uses a tree structure (specifically, a red-black tree) to store elements in sorted order.
- When you add elements to a TreeSet, they are automatically sorted based on their natural
order or the order defined by a Comparator if one is provided.
- TreeSet provides methods for accessing elements, finding the first and last elements, and
navigating the set in sorted order.
- Operations like add, remove, and contains have a time complexity of O(log n), where n is
the number of elements in the set. This is because of the efficient tree-based data structure
used by TreeSet.
4. **Key Points:**
- TreeSet is ideal when you need a collection that maintains elements in sorted order and
allows quick access to elements based on their order.
- It is not synchronized, so if multiple threads access a TreeSet concurrently and at least one
of the threads modifies the set, it must be synchronized externally.
- TreeSet does not allow null elements. If you try to add a null element, it will throw a
NullPointerException.
1. **Sorted Order**: TreeSet automatically sorts its elements based on their natural ordering
(if they implement the Comparable interface) or using a Comparator provided during TreeSet
creation.
2. **Balanced Tree Structure**: TreeSet uses a balanced tree structure, usually a Red-Black
Tree, which ensures efficient operations like adding, removing, and searching for elements.
1. **Adding Elements**: When you add elements to a TreeSet, it places them in the correct
position according to their order. For example:
```
TreeSet<Integer> numbers = new TreeSet<>();
numbers.add(5);
numbers.add(3);
numbers.add(8);
```
```
numbers.remove(5);
```
3. **Searching for Elements**: TreeSet provides efficient searching based on its sorted order.
For example:
```
boolean containsFive = numbers.contains(5);
```
Here, `containsFive` will be `false` because we removed `5` from the TreeSet.
```
Integer firstElement = numbers.first(); // Returns 3
Integer lastElement = numbers.last(); // Returns 8
```
### Summary:
1. **Key-Value Pairs**: A Map stores data in key-value pairs. The key is used to uniquely
identify a value in the Map. Think of it like a dictionary where each word (key) has a
corresponding definition (value).
2. **Unique Keys**: Keys in a Map must be unique. This means you cannot have duplicate
keys in a single Map. If you try to add a duplicate key, it will replace the existing value
associated with that key.
3. **No Indexing**: Unlike lists or arrays, Maps do not use indexes to access elements.
Instead, you access values in a Map using their keys. This makes it efficient for searching and
retrieving specific values based on their keys.
4. **Implementation Classes**: Java provides several classes that implement the Map
interface, such as HashMap, TreeMap, LinkedHashMap, and ConcurrentHashMap. Each
class has its own characteristics and is suited for different use cases.
6. **TreeMap**: This implementation sorts the keys in a natural order or based on a custom
comparator if provided. It offers efficient operations for searching, inserting, and deleting
elements, but it may be slower than HashMap for large data sets due to sorting overhead.
9. **Common Operations**: Some common operations you can perform with a Map include
adding key-value pairs (`put(key, value)`), retrieving a value by its key (`get(key)`), checking
if a key exists (`containsKey(key)`), removing a key-value pair (`remove(key)`), and getting
the number of key-value pairs in the Map (`size()`).
1. **Unique Keys**: In a `Map`, keys are unique. This means you can't have two entries with
the same key. If you try to add a key-value pair with an existing key, the new value will
replace the old one.
2. **Key-Value Pairing**: Each key in a `Map` is associated with exactly one value. When
you want to retrieve a value, you provide the key, and the `Map` returns the corresponding
value.
3. **Methods**: The `Map` interface provides methods to add, remove, retrieve, and check
for the presence of key-value pairs. Some common methods include `put(key, value)`,
`get(key)`, `remove(key)`, and `containsKey(key)`.
```
import java.util.HashMap;
import java.util.Map;
In this example, we create a `Map` called `gradesMap` that stores the grades of three
students. We use `put(key, value)` to add entries, `get(key)` to retrieve values,
`containsKey(key)` to check if a key exists, and `remove(key)` to delete an entry.
HashMap Class:-
### What is HashMap?
HashMap is a class in Java that implements the Map interface. It allows you to store key-
value pairs and provides efficient retrieval and insertion of elements based on the keys.
HashMap uses a hashing technique to store and retrieve elements quickly, making it suitable
for scenarios where you need fast access to data. It is implemented using a hash table data
structure, which provides efficient performance for operations like insertion, deletion, and
retrieval.
1. **Key-Value Pairs**: A HashMap stores data as key-value pairs. Each key in a HashMap
must be unique, and each key is associated with exactly one value. This allows for efficient
retrieval of values based on their keys.
3. **Collision Handling**: In cases where different keys produce the same hash code (known
as a collision), HashMap uses a linked list or a tree (depending on the JDK version and the
number of elements in the bucket) at that index to handle multiple key-value pairs with the
same hash code.
5. **Iterating Over Elements**: You can iterate over the elements of a HashMap using
iterators or enhanced for loops. The order of iteration is not guaranteed and may vary
between different executions or versions of Java.
7. **Capacity and Load Factor**: HashMap has an initial capacity and a load factor. The
initial capacity is the number of buckets allocated when the HashMap is created, and the load
factor is a measure of how full the HashMap can be before it is resized. Resizing occurs when
the number of elements exceeds the product of the load factor and the current capacity.
1. **Hashing**: When you add a key-value pair to a HashMap, Java calculates the hash code
of the key. The hash code is an integer value that represents the key's memory address or
content.
2. **Bucket Storage**: HashMap uses an array of buckets to store elements. Each bucket can
hold multiple elements, forming a linked list or a tree structure if there are collisions (two
different keys having the same hash code).
3. **Index Calculation**: After calculating the hash code, Java converts it into an index
within the array using a technique called modulo hashing. This index determines which
bucket the key-value pair will be stored in.
4. **Handling Collisions**: If two keys hash to the same index (collision), HashMap handles
it by either creating a linked list or a tree structure in that bucket to store multiple elements
with the same index.
- **Fast Retrieval**: HashMap provides constant-time performance for basic operations like
get() and put() if the hash function distributes elements evenly across buckets.
- **Null Keys and Values**: HashMap allows null keys and null values. You can have at
most one null key and multiple null values in a HashMap.
```
import java.util.HashMap;
// Removing an element
employeeMap.remove(103);
System.out.println("After removing ID 103: " + employeeMap);
}
}
```
In this example, we create a HashMap `employeeMap` to store employee IDs as keys and
their names as values. We add elements, retrieve a value using a key, check if a key exists,
and remove an element from the HashMap.
LinkedHashMap Class:-
What is LinkedHashMap?
A `LinkedHashMap` in Java is a type of map that combines the features of a HashMap and a
LinkedList. It maintains a predictable iteration order, which is the order in which elements
were inserted into the map. This means that when you iterate over a LinkedHashMap, you
will get the elements in the order they were added.
2. **Preserves Insertion Order**: Unlike a `HashMap` that doesn't guarantee any specific
order of elements, a `LinkedHashMap` maintains the order in which elements are inserted.
This is because it uses a doubly linked list internally to maintain this order.
3. **Doubly Linked List**: Each entry in a `LinkedHashMap` has pointers to the previous
and next entries in the list. This allows for efficient traversal of elements in the order they
were added.
4. **Iteration Order**: When you iterate over a `LinkedHashMap`, it will return elements in
the same order they were inserted. This can be useful when you need to process elements in a
specific sequence.
### Example:
```
import java.util.LinkedHashMap;
import java.util.Map;
In this example, we create a LinkedHashMap and add elements to it. When we iterate over
the map, the elements will be printed in the order they were inserted, which is 1: One, 2: Two,
and 3: Three.
### Summary:
1. **Sorted Structure**: Unlike HashMap, TreeMap maintains the elements in sorted order
based on the natural ordering of the keys or a custom comparator provided during TreeMap
creation.
2. **Balanced Tree Structure**: TreeMap uses a Red-Black tree internally to store the
elements. This tree structure ensures that the elements are balanced, which leads to efficient
search, insertion, and deletion operations.
3. **Key-Value Pairs**: TreeMap stores elements as key-value pairs, where each key is
unique. It uses the keys to determine the ordering of elements.
6. **SubMap Views**: You can obtain subMap views of the TreeMap using methods like
subMap, headMap, and tailMap. These views allow you to work with a subset of elements
based on specified ranges of keys.
3. **Key Characteristics**:
- TreeMap does not allow null keys but can have null values.
- It maintains a sorted order based on keys.
- Iterating through a TreeMap will produce keys in sorted order.
4. **Example**:
```
import java.util.*;
// Removing an element
treeMap.remove(1);
System.out.println("TreeMap after removal: " + treeMap);
5. **Performance**:
- TreeMap provides guaranteed log(n) time cost for the containsKey, get, put, and remove
operations.
- Iteration over TreeMap entries takes O(log n + m) time, where n is the number of
elements and m is the number of returned entries.
6. **Use Cases**:
- TreeMap is useful when you need a sorted collection of key-value pairs.
- It's commonly used in scenarios where you need to maintain a sorted order of elements,
such as dictionary implementations or sorted data processing.
Overall, TreeMap in Java provides a sorted and efficient way to store key-value pairs, making
it a valuable tool for various programming tasks.
Hashtable Class:-
The `Hashtable` class in Java is a data structure that stores key-value pairs. It's part of the
Java Collections Framework and provides a way to map keys to values.
1. **Purpose**: `Hashtable` is used to store data in key-value pairs, where each key is
unique. It allows you to quickly retrieve values based on their keys.
5. **Performance**: While `Hashtable` provides thread safety, it can be slower than some
other data structures due to the synchronization overhead. For scenarios where thread safety
is not a requirement, other data structures like `HashMap` may be more suitable.
6. **Null Handling**: Unlike some other data structures, `Hashtable` does not allow null
keys or values. If you try to put a null key or value into a `Hashtable`, it will throw a
`NullPointerException`.
8. **Legacy Class**: `Hashtable` is considered a legacy class in Java, as it has been around
since the early versions of Java. It is still used in some cases where thread safety is essential
and where newer alternatives like `ConcurrentHashMap` are not required.
### Explanation:
1. **Key-Value Mapping:**
- A `Hashtable` is like a dictionary where each word (key) has a corresponding definition
(value).
- Keys must be unique, meaning you can't have two entries with the same key.
- Values can be duplicated, so multiple keys can have the same value.
2. **Hashing Technique:**
- Internally, `Hashtable` uses a hashing technique to store and retrieve elements quickly.
- When you add a key-value pair, the key is hashed to generate an index where the value is
stored.
- Hashing helps in efficient retrieval, especially for large collections of data.
3. **Thread-Safe:**
- One key feature of `Hashtable` is that it's synchronized or thread-safe.
- This means multiple threads can access a `Hashtable` object concurrently without causing
data corruption.
4. **Null Handling:**
- Both keys and values in a `Hashtable` cannot be null. If you try to add a null key or value,
it will throw a `NullPointerException`.
### Example:
Let's say you want to store some information about students using a `Hashtable`. Here's how
you can do it:
```
import java.util.Hashtable;
In this example:
- We create a `Hashtable` named `studentInfo` to store student IDs (keys) and names (values).
- We add three students with IDs 101, 102, and 103 along with their names.
- We then retrieve and print the information for each student.
- Uncommenting the lines that try to add a null key or value will result in
`NullPointerExceptions` as mentioned earlier.
This example demonstrates the basic usage of `Hashtable` in Java for storing and retrieving
key-value pairs.
Sorting:-
In Java, sorting refers to arranging elements in a collection or array in a specific order, such
as ascending or descending. The sorting process is essential for organizing data in a
meaningful way, making it easier to search and retrieve information efficiently.
2. **Sorting Algorithms**:
- Java uses various sorting algorithms under the hood, such as QuickSort, MergeSort, and
TimSort (a hybrid of MergeSort and InsertionSort).
- The `Arrays` and `Collections` classes in Java provide static methods like `sort` and `sort`
(for objects) that internally use efficient sorting algorithms to sort arrays and collections,
respectively.
1. **Arrays.sort()**
- This method is used to sort arrays of primitive types or objects.
- Example:
```java
int[] numbers = {5, 2, 8, 1, 9};
Arrays.sort(numbers); // Sorts the array in ascending order
```
2. **Collections.sort()**
- This method is used to sort collections like ArrayList, LinkedList, etc.
- Example:
```java
ArrayList<Integer> list = new ArrayList<>();
list.add(5);
list.add(2);
list.add(8);
list.add(1);
list.add(9);
Collections.sort(list); // Sorts the ArrayList in ascending order
```
Sometimes, you may need to sort objects based on specific criteria, such as sorting a list of
custom objects by their attributes.
@Override
public int compareTo(Student other) {
return this.id - other.id; // Sorts students by their ID in ascending order
}
}
```
2. **Using Comparator Interface**
- If you want to sort objects based on different criteria without modifying the class, you can
use the `Comparator` interface.
- Example:
```java
ArrayList<Student> students = new ArrayList<>();
// Add students to the list
Under the hood, Java's built-in sorting methods use efficient algorithms like Quicksort,
Mergesort, or Timsort (a hybrid of Mergesort and Insertion sort) depending on the data and
context. These algorithms ensure fast and accurate sorting of elements.
Understanding sorting in Java is essential for organizing data effectively and optimizing
performance in your applications.
Comparable Interface:-
The Comparable interface in Java is used to define a natural ordering for a class of objects.
When a class implements the Comparable interface, it means that objects of that class can be
compared to each other and sorted based on their natural order.
2. **compareTo Method**: The Comparable interface has one method called `compareTo`,
which is used to compare two objects of the same class. The signature of the `compareTo`
method is as follows:
```java
int compareTo(T o);
```
Here, `T` is the type of objects being compared, and `o` is the object to be compared with.
1. **Interface Definition**:
The Comparable interface is defined in Java as follows:
```java
public interface Comparable<T> {
int compareTo(T o);
}
```
2. **Method Explanation**:
- `compareTo(T o)`: This method compares the current object (denoted by `this`) with the
object `o` passed as an argument. It returns an integer value based on the comparison:
- If `this` object is less than `o`, it returns a negative integer.
- If `this` object is equal to `o`, it returns 0.
- If `this` object is greater than `o`, it returns a positive integer.
3. **Usage Example**:
Let's say we have a class `Person` that implements the Comparable interface to compare
persons based on their age. Here's how it looks:
```java
public class Person implements Comparable<Person> {
private String name;
private int age;
System.out.println(person1.compareTo(person2)); // Output: -5
}
}
```
In this example, the `compareTo` method compares persons based on their ages (`this.age -
otherPerson.age`). When we compare `person1` (age 25) with `person2` (age 30), the result is
`-5`, indicating that `person1` is younger than `person2`.
4. **Sorting Objects**:
The Comparable interface is commonly used in sorting algorithms, such as
`Collections.sort()` or arrays' `Arrays.sort()`. When you have a collection of objects that
implement Comparable, these methods use the compareTo method to sort the objects based
on their natural ordering.
```
public static void main(String[] args) {
Person person1 = new Person("Alice", 25);
Person person2 = new Person("Bob", 30);
Person person3 = new Person("Charlie", 20);
Collections.sort(people);
In this example, the `people` list is sorted based on the natural ordering defined by the
`compareTo` method in the `Person` class.
Comparator Interface:-
The `Comparator` interface in Java is used to define a custom way of comparing objects. It's
helpful when you want to sort objects based on criteria other than their natural order (like
alphabetical for strings or numerical for numbers).
6. **Example Scenario:**
- Suppose you have a list of Person objects and you want to sort them based on their ages.
- You can create a `PersonAgeComparator` class that implements Comparator<Person>.
- In the `compare` method of `PersonAgeComparator`, you compare the ages of two Person
objects and return the appropriate integer value for sorting.
```
import java.util.*;
In this example:
- We define a `Comparator` called `ageComparator` that compares `Person` objects based
on their age.
- We sort the list of `Person` objects using `Collections.sort(people, ageComparator)`.
- The output will be:
```
Charlie - 20
Alice - 25
Bob - 30
```
4. **Summary:**
- `Comparator` provides a way to customize sorting logic for objects in Java.
- It's used with methods like `Collections.sort()` to sort objects based on specific criteria.
- You implement `Comparator` by defining the `compare()` method to return negative, zero,
or positive values based on the comparison result.
1. **Purpose**:
- The `Properties` class is used to store configuration data such as database connection
settings, application settings, and other parameters in a structured manner.
4. **Accessing Properties**:
- Properties can be accessed using their keys.
- The `getProperty()` method retrieves the value associated with a key.
- If a key does not exist, a default value can be specified.
5. **Modifying Properties**:
- Properties can be modified by adding, changing, or removing key-value pairs.
- The `setProperty()` method adds or modifies a key-value pair.
- The `remove()` method removes a key-value pair.
6. **Use Cases**:
- The `Properties` class is commonly used in applications where configuration data needs to
be externalized and easily configurable without modifying the source code.
- It is particularly useful for applications that require dynamic configuration changes
without redeployment.
7. **Thread Safety**:
- The `Properties` class is not inherently thread-safe.
- Synchronization mechanisms should be used when accessing or modifying properties in a
multi-threaded environment.
3. **Accessing Properties**:
- You can retrieve a property using its key: `String url = props.getProperty("database.url");`
- If the key doesn't exist, you can provide a default value: `String user =
props.getProperty("database.user", "root");`
4. **Example**:
```
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
// Set properties
props.setProperty("database.url", "jdbc:mysql://localhost:3306/mydb");
props.setProperty("database.user", "root");
In this example, we create a `Properties` object, set some properties, save them to a file, and
then load and retrieve them. This class is handy for managing configuration data or any key-
value pairs where string values are used.