Java's Collection API 4
Java's Collection API 4
What is an API?
Imagine you have a toy car, and you want to control it with a remote. The remote is like an
API. It gives you a few buttons to press: forward, backward, left, right. You don’t need to
know how the toy car’s motor works on the inside, you just need to know what each button
does to control the car.
API (Application Programming Interface) is like that remote but for software. It gives you
a set of tools or methods to interact with a piece of software or a system without knowing
how it works on the inside.
Example of an API:
Let’s say you want to use a weather app. The app doesn’t figure out the weather itself—it
asks a weather API to provide the information. The API has methods like
getTemperature(), getHumidity(), etc., that the app can use to get weather details. You
just interact with the app, and the app uses the API to fetch the data.
In Java, an API is like a set of ready-made tools or methods that Java provides for you to
use in your programs. It helps you do tasks without writing everything from scratch.
Now, imagine you’re given a toolbox to help you organize things—like a drawer to put
things in, a jar to store pens, etc. The Collection API in Java is like a toolbox for handling
groups of objects (like lists, sets, and maps). It gives you methods to store, retrieve, and
organize objects without worrying about how it's managed behind the scenes.
For example:
ArrayList is part of the Collection API. It’s like a list where you can keep adding or
removing items.
HashMap is like a dictionary where you can store a key and a value (like storing a
person's name and their phone number).
You use these without having to know how they work inside. Java has already done that hard
work for you!
Summary:
API is like a remote control that lets you interact with software without knowing its
internal details.
Java’s Collection API is one of the toolsets that helps you handle and organize data
(like lists, sets, and maps).
Let’s dive a bit deeper into the concept of API and specifically the Collection API in Java.
An API is like a bridge that allows one piece of software to talk to another. It defines a set of
rules or methods that one program can use to request services or information from another.
Think of APIs as a menu in a restaurant. The menu tells you what dishes you can order
(methods or services), but it doesn’t tell you how those dishes are made in the kitchen (the
internal workings of the system). When you order, the chef (API provider) prepares the food
and gives it to you, but you don’t care how the chef cooked it—you just receive the result.
Let’s say you want to look at a bank's transaction history in a mobile app:
The app will use the bank’s API to ask for the data, like
getTransactionHistory().
You don't need to know how the bank stores the data in their databases, you just get
the transactions displayed in your app.
In programming, an API provides methods that you can call (like pressing buttons on a
remote) to perform actions, and the details of how those actions are performed are hidden
away.
2. Java API:
Java comes with a lot of built-in APIs. These APIs provide methods and classes that you can
use to do things like:
You don’t need to build all of these things yourself from scratch—Java gives you ready-to-
use tools. For example:
You want to print something to the screen? Java has a built-in API with a method
called [Link]() that handles this for you.
Want to create a list of items? Java has an API with a class called ArrayList.
The Collection API in Java is a specific set of tools or classes that help you work with
groups of objects. It allows you to store, manage, and manipulate a collection of items like
lists, sets, and maps. This helps you handle lots of objects in a structured way without
worrying about how the data is managed internally.
Here’s a breakdown:
1. List (ArrayList)
A List is like a dynamic array. You can add items, remove them, and access them by
their position.
For example, an ArrayList grows automatically as you add more elements.
Example:
java
Copy code
import [Link];
// Accessing an item
[Link]([Link](1)); // Output: Banana
}
}
Here, you didn't have to worry about how the list stores data; you just used the API to add or
retrieve items.
2. Set (HashSet)
A Set is a collection that does not allow duplicates. This is like a bag where no two
items can be the same.
For example, a HashSet stores items in no particular order but makes sure each item
is unique.
Example:
java
Copy code
import [Link];
3. Map (HashMap)
A Map is a collection that stores key-value pairs. This is like a dictionary where you
look up a value by its key.
For example, a HashMap allows you to store and retrieve values by a key.
Example:
java
Copy code
import [Link];
Here, you used the HashMap API to store and retrieve data using keys (names) and values
(ages).
Using APIs like the Collection API saves you time because:
You don’t have to reinvent the wheel—Java provides well-tested, efficient ways to
work with data.
You can focus on building your application rather than worrying about the
underlying data structure implementation.
It makes your code cleaner, more readable, and easier to maintain.
Java has many other APIs beyond the Collection API. For example:
File API: Helps you work with files on your computer (like reading and writing files).
Network API: Lets you send data over the internet, like fetching data from a web
server.
Date/Time API: Helps you work with dates and times.
Conclusion:
Does this give you a clearer picture of APIs? Let me know if you have any more questions!
In Java, an API often refers to the collection of classes, interfaces, and methods that Java
provides through the Java Development Kit (JDK) and Java Runtime Environment
(JRE). These APIs give your Java programs access to common, low-level functionality that
the JRE can execute. Here, the "software" is your Java application itself interacting with:
Java Libraries: Ready-made classes and methods (such as those for file handling,
networking, and data structures) provided by Java.
Java Runtime (JRE): The engine that runs your Java program. It contains an
implementation of the Java APIs that you use in your code.
Example:
Let’s say your Java program wants to read a file from the computer. Java provides an API
for that through the [Link] package, which contains classes like FileReader and
BufferedReader. Your Java program interacts with this API, and the JRE executes the
actual reading from the file system.
Example code:
java
Copy code
import [Link];
import [Link];
import [Link];
String line;
while ((line = [Link]()) != null) {
[Link](line);
}
[Link]();
} catch (IOException e) {
[Link]();
}
}
}
Here, your program uses Java’s file-handling API to communicate with the file system
through the JRE, without worrying about the operating system details.
Sometimes, Java APIs interact with external systems or other libraries. These libraries can
be added to your project and used to extend the functionality of your Java application. These
external systems could be:
In these cases, Java APIs help your program communicate with external software.
Summary:
1. Java’s internal libraries (like the Collection API, File API, etc.).
2. External systems such as databases, web services, and third-party software.
3. Java frameworks that help you build applications more easily.
So when you’re using Java APIs, the “software” involved can be:
1. Collection API:
o A concept that provides a framework for working with data structures and
algorithms.
o Introduced in Java 1.2 to simplify working with data.
2. Collection (Interface):
o An interface representing a group of objects (elements).
o Defines the common methods that data structure classes must implement.
3. Collections (Class):
o A utility class with static methods for operations on collections (e.g., sorting,
searching).
Array Limitations:
o Arrays have a fixed size.
o Manually resizing an array is complex.
Collection API Advantages:
o Provides dynamic data structures (e.g., ArrayList, LinkedList).
o Pre-built data structures like Stack, Queue, List, Set, Map.
o Simplifies tasks like sorting, searching, and fetching unique values.
Key Concepts:
When to Use?
3. TREE set
1. Collection Interface
2. ArrayList Example
Creating ArrayList:
java
Copy code
List<Integer> nums = new ArrayList<>();
Adding Elements:
java
Copy code
[Link](6);
[Link](5);
[Link](8);
[Link](2);
java
Copy code
[Link](nums); // Output: [6, 5, 8, 2]
java
Copy code
for (int n : nums) {
[Link](n);
}
3. Generics in Collections
java
Copy code
Collection nums = new ArrayList();
[Link](5); // Works, but nums is treated as `Object`
java
Copy code
List<Integer> nums = new ArrayList<>();
java
Copy code
[Link](6);
java
Copy code
[Link]([Link](2)); // Output: 8 (element at index 2)
java
Copy code
[Link]([Link](5)); // Output: 1
java
Copy code
[Link](1, 10); // Changes value at index 1 to 10
java
Copy code
Object[] arr = [Link]();
Generics ensure compile-time errors instead of runtime exceptions when types don’t match.
Example of compile-time error if non-integers are added to a list of integers:
java
Copy code
List<Integer> nums = new ArrayList<>();
[Link]("5"); // Compile-time error, as the list expects Integer
java
Copy code
for (int n : nums) {
[Link](n);
}
SET:
Java Collections - List vs Set
1. List Overview
Supports Index: Elements can be accessed using their index (e.g., [Link](index)).
Allows Duplicates: List can have multiple elements with the same value.
java
Copy code
List<Integer> list = new ArrayList<>();
[Link](6);
[Link](6); // Duplicate value
2. Set Overview
Does Not Support Index: Elements cannot be accessed using index (no get(index)
method).
Unique Elements: Set does not allow duplicate elements.
java
Copy code
Set<Integer> set = new HashSet<>();
[Link](6);
[Link](6); // Will not add the second 6
3. HashSet
java
Copy code
Set<Integer> set = new HashSet<>();
[Link](6);
[Link](5);
[Link](6); // Duplicate ignored
[Link](2);
[Link](set); // Output: [5, 2, 6] - No order, no
duplicates
4. TreeSet
Sorted Set: TreeSet maintains the elements in a sorted order (natural ordering).
No Duplicates: Like HashSet, TreeSet does not allow duplicate values.
java
Copy code
Set<Integer> set = new TreeSet<>();
[Link](54);
[Link](21);
[Link](82);
[Link](set); // Output: [21, 54, 82] - Sorted order
5. Collection Interface
Super Interface: Both List and Set extend the Collection interface.
Methods: Common methods include add(), remove(), contains(), etc.
java
Copy code
Collection<Integer> collection = new HashSet<>();
[Link](10);
[Link](20);
6. Iterable Interface
java
Copy code
Iterator<Integer> iterator = [Link]();
while ([Link]()) {
[Link]([Link]());
}
java
Copy code
for (int num : set) {
[Link](num);
}
java
Copy code
Iterator<Integer> it = [Link]();
while ([Link]()) {
[Link]([Link]());
}
8. LinkedHashSet
java
Copy code
Set<Integer> linkedSet = new LinkedHashSet<>();
[Link](10);
[Link](30);
[Link](10); // Duplicate ignored
[Link](linkedSet); // Output: [10, 30] - Maintains
insertion order
Key Differences:
This covers the key points regarding List, Set, HashSet, TreeSet, and how to iterate through
collections using loops and iterators.
MAP:
Map Overview
Key-Value Pair
Creating a Map
Map<KeyType, ValueType> mapName = new HashMap<>();
o Example:
java
Copy code
Map<String, Integer> students = new HashMap<>();
Adding Entries
java
Copy code
[Link]("Navin", 56);
[Link]("Harsh", 23);
Printing the Map
java
Copy code
[Link](students);
Key Observations
java
Copy code
[Link]("Harsh"); // Output: 23
Updating a Value
Example:
java
Copy code
[Link]("Harsh", 45); // Updates Harsh’s marks from 23 to 45.
java
Copy code
for (String key : [Link]()) {
[Link](key + ": " + [Link](key));
}
Key-Related Methods
----------------------------------------------------------------------------------------------------------------
To sort a collection in Java, you can use the [Link]() method. Here's an
example of sorting a list of integers:
java
Copy code
List<Integer> nums = new ArrayList<>();
[Link](4);
[Link](9);
[Link](3);
[Link](7);
Java 1.7 Update: It's no longer necessary to specify the type on both sides of variable
assignment. For example:
java
Copy code
List<Integer> nums = new ArrayList<>();
If you want to sort a list based on custom logic (e.g., based on the last digit of a number), you
need to use a Comparator.
java
Copy code
Comparator<Integer> comp = new Comparator<Integer>() {
@Override
public int compare(Integer i, Integer j) {
return [Link](i % 10, j % 10); // Compare last
digits
}
};
3. Understanding Comparator
Example:
java
Copy code
@Override
public int compare(Integer i, Integer j) {
return [Link](i % 10, j % 10);
}
4. Challenge Task
Try creating a list of Strings and sort them based on their length using Comparator:
Hint: You can write logic inside the comparator to compare string lengths using
[Link]().
When working with complex objects (like a class Student), you can use a comparator to sort
them based on any attribute, such as age or name.
java
Copy code
class Student {
int age;
String name;
@Override
public String toString() {
return name + " (" + age + ")";
}
}
java
Copy code
Comparator<Student> comp = new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
return [Link]([Link], [Link]);
}
};
The Comparable interface allows a class to define its own natural sorting order.
To use it, implement the Comparable<T> interface and override the compareTo()
method in your class.
Example:
java
Copy code
class Student implements Comparable<Student> {
int age;
String name;
@Override
public int compareTo(Student that) {
return [Link]([Link], [Link]); // Compare based on
age
}
}
java
Copy code
[Link](students); // Natural sorting by age using compareTo
Comparator: Allows custom sorting logic. You can have multiple comparators for
different sorting criteria.
Comparable: Defines the natural order for objects (e.g., a class Student can define
its own natural sorting order based on age or name).
java
Copy code
Comparator<Student> comp = (s1, s2) -> [Link]([Link], [Link]);
[Link](students, comp);
This reduces the code to one line, making it more readable and concise.
You can also use the ternary operator to make the comparison logic shorter:
java
Copy code
Comparator<Student> comp = (s1, s2) -> [Link] > [Link] ? 1 : -1;
10. Conclusion
Use Comparable if you want to define natural sorting logic within the class itself.
Use Comparator when you need multiple ways to sort objects (e.g., by age, name,
etc.).
Lambda expressions and ternary operators make it easier to define comparators
concisely.
Introduction:
We want to work with a list of integers and perform operations like filtering, doubling, and
summing up values.
1. Creating a List:
o We can create a list of integers using the ArrayList class or
[Link]() method for simplicity.
o Example:
java
Copy code
List<Integer> nums = [Link](1, 4, 2, 6, 3);
2. Printing a List:
o To print the list, you can simply use:
java
Copy code
[Link](nums); // Output: [1, 4, 2, 6, 3]
java
Copy code
int sum = 0;
for (int n : nums) {
if (n % 2 == 0) { // Check if the number is even
n = n * 2; // Double the even number
sum += n; // Add the doubled number to the sum
}
}
[Link](sum); // Output: 24
Explanation:
Example Flow:
For the list [1, 4, 2, 6, 3]:
Stream API works with collections and allows method chaining to perform multiple
operations.
Example:
java
Copy code
int result = [Link]()
.filter(n -> n % 2 == 0) // Filter even numbers
.map(n -> n * 2) // Double the numbers
.reduce(0, Integer::sum); // Sum them up
Explanation:
java
Copy code
for (int i = 0; i < [Link](); i++) {
[Link]([Link](i));
}
java
Copy code
for (int n : nums) {
[Link](n);
}
java
Copy code
[Link](n -> [Link](n));
o This is the simplest and most modern approach, using Java's lambda
expressions.
Conclusion:
There are different ways to iterate over a list (standard loop, enhanced for loop, and
forEach()).
The Stream API provides a more functional and efficient way to handle collections
by using methods like filter(), map(), and reduce().
We will dive deeper into how the Stream API works in the next lesson.
1. Introduction to forEach
Java 1.8 introduced a new method called forEach, which is part of the Stream API
and List interface.
This method allows iterating over elements in a simplified manner, compared to
traditional loops.
Syntax:
java
Copy code
[Link](n -> {
// operation on 'n'
});
How it works:
o The forEach method takes one value at a time from the list.
o We can perform any operation on this value. In the above syntax, n refers to
one element from the list.
java
Copy code
for (int i = 0; i < [Link](); i++) {
[Link]([Link](i));
}
java
Copy code
for (int n : nums) {
[Link](n);
}
Using forEach:
java
Copy code
[Link](n -> [Link](n));
Which is better?
o forEach simplifies the process.
o It's less verbose and easier to read.
java
Copy code
Consumer<Integer> con = new Consumer<Integer>() {
@Override
public void accept(Integer n) {
[Link](n);
}
};
[Link](con);
java
Copy code
[Link](n -> [Link](n));
Further Simplified:
o Since it's a single statement, curly braces {} and return type can be omitted.
o Java understands the type, so you can omit Integer too.
java
Copy code
[Link](n -> [Link](n));
java
Copy code
Consumer<Integer> con = (Integer n) -> {
[Link](n);
};
[Link](con);
java
Copy code
Consumer<Integer> con = (n) -> {
[Link](n);
};
[Link](con);
java
Copy code
Consumer<Integer> con = n -> {
[Link](n);
};
[Link](con);
java
Copy code
Consumer<Integer> con = n -> [Link](n);
[Link](con);
java
Copy code
[Link](n -> [Link](n));
This should provide you a clear and simple understanding of how forEach works and how
lambda expressions simplify the process in Java 1.8. Let me know if you'd like to dive deeper
into Stream API next!
Memory updated
Creating a Stream
java
Copy code
Stream<Integer> s1 = [Link]();
Characteristics of Streams
One-time use: A stream can only be consumed once. After an operation, it cannot be
reused.
Example of reuse issue:
o Using [Link](...) can be done multiple times.
o Using [Link](...) will throw an error if called again after its first
usage.
1. Filtering:
o Example: Get even numbers from a stream.
java
Copy code
Stream<Integer> s2 = [Link](n -> n % 2 == 0);
2. Mapping:
o Example: Double the values of the filtered stream.
java
Copy code
Stream<Integer> s3 = [Link](n -> n * 2);
3. Reducing:
o Example: Sum up all the doubled values.
java
Copy code
int result = [Link](0, (c, e) -> c + e);
Filter: Accepts a condition and returns a new stream containing only the elements
that match.
Map: Accepts a function and applies it to each element, returning a new stream of
transformed elements.
Reduce: Aggregates the elements of a stream into a single value (e.g., sum).
java
Copy code
int result = [Link]()
.filter(n -> n % 2 == 0)
.map(n -> n * 2)
.reduce(0, (c, e) -> c + e);
Conclusion
Streams make it easier to work with data in a more readable and functional style.
Familiarity with streams will improve coding efficiency and clarity.
Additional Notes
The quote by Venkat Subramanian: “It’s not difficult, it’s just unfamiliar.”
emphasizes that with practice, using streams becomes intuitive.
Further exploration and practice with streams will enhance your understanding and
application in real-world scenarios.
These notes encapsulate the core concepts of the Stream API as presented in the video. You
can use them for a quick review later on!
Here are detailed and simplified notes based on the video transcript discussing the Java
Stream API, focusing on the filter, map, and reduce methods.
The Java Stream API allows for functional-style operations on streams of elements, such as
filtering, mapping, and reducing data.
1. Filter
Code Example:
java
Copy code
import [Link];
Code Example:
import [Link];
3. Reduce
java
Copy code
BinaryOperator<Integer> add = (c, e) -> c + e; // Add two integers
int sum = [Link](0, add); // Start with 0 and reduce by adding
elements
Sorting: After filtering, you can sort the stream using the sorted() method.
Code Example:
java
Copy code
[Link](value -> [Link](value)); // Print sorted
values
Note: Avoid using parallelStream() with sorting because sorting requires all elements to
be in order.
Summary
These notes capture the essential details and examples from the video, making it easier for
you to review and understand the concepts of the Java Stream API. If you need any more
specific details or further simplification, feel free to ask!
1. Introduction
java
Copy code
import [Link];
import [Link];
import [Link];
Initialize List:
java
Copy code
List<Integer> nums = new ArrayList<>(10000);
Using Streams:
Standard Stream:
java
Copy code
int sum1 = [Link]()
.map(i -> i * 2) // Multiply each element by 2
.reduce(0, Integer::sum); // Sum all elements
Using mapToInt:
java
Copy code
int sum2 = [Link]()
.mapToInt(i -> i * 2) // Convert to IntStream
.sum(); // Directly get the sum
java
Copy code
int sum3 = [Link]()
.mapToInt(i -> i * 2) // Same as above but in
parallel
.sum();
java
Copy code
long startSeq = [Link]();
// Sum operation for Sequential Stream
long endSeq = [Link]();
Observation: Sequential streams are faster for simple operations due to the overhead of
managing threads in parallel streams.
Simulate a Delay: To illustrate performance, add a 1-millisecond delay during the map
operation using [Link]().
java
Copy code
try {
[Link](1); // Introduce delay
} catch (InterruptedException e) {
[Link]();
}
7. Key Takeaways
8. Conclusion
Understanding parallel streams can help optimize performance in data processing tasks
when used appropriately.
Notes on Optional Class and Null Pointer Exception Handling in Java 1.8
Java 1.8 introduced the Optional class to address one of the most common and
frustrating errors in Java: Null Pointer Exception (NPE).
NPE occurs when you try to operate on a null object, leading to unexpected crashes.
Optional is a container object which may or may not contain a non-null value. If a
value is present, Optional will hold it; if not, it prevents NPE by providing
alternative behavior.
2. Example Scenario:
java
Copy code
List<String> names = [Link]("Navin", "Laxmi", "John",
"Kishor");
The task is to find the first name in the list that contains the letter "x".
We can use Stream API to filter names and find the first occurrence with "x":
java
Copy code
String nameWithX = [Link]()
.filter(name -> [Link]("x"))
.findFirst()
.get(); // This can cause Null Pointer
Exception if no result is found
Problem: If no name contains "x", findFirst() will return null, and calling .get()
on null will cause a Null Pointer Exception.
findFirst() returns an Optional<String>, not just a String. This way, the value
may or may not exist, but you handle it gracefully.
java
Copy code
Optional<String> nameWithX = [Link]()
.filter(name -> [Link]("x"))
.findFirst(); // Returns
Optional<String>
a) Using .get():
If you're sure that the value exists, you can retrieve it using .get(). But this is risky
because it throws an exception if the value is not present.
java
Copy code
if ([Link]()) {
[Link]([Link]()); // Safe way to get value if
present
}
b) Using .orElse():
java
Copy code
String result = [Link]("Not Found");
[Link](result); // Prints "Not Found" if no name
contains "x"
Explanation:
o .orElse("Not Found") will return the found name if present, or the string
"Not Found" if no name matches the condition.
java
Copy code
String nameWithX = [Link]()
.filter(name -> [Link]("x"))
.findFirst()
.orElse("Not Found");
o This directly gives you the result, avoiding both NPE and unnecessary .get()
checks.
Avoids Null Pointer Exception: Handles null values gracefully without crashing the
program.
Readable Code: Makes code more readable by clearly indicating that a value may or
may not be present.
Cleaner Null Checks: Reduces the need for verbose if-else null checks.
8. Key Methods in Optional:
Conclusion:
Optional is a crucial feature introduced in Java 1.8 to handle cases where a value may
be absent, helping developers avoid Null Pointer Exceptions and write more reliable,
readable code.
By using Optional, you ensure safer code practices when dealing with potentially
null values.
Example Setup:
1. List of names:
java
Copy code
List<String> names = [Link]("Navin", "Harsh", "John");
2. Goal:
o Print all names in uppercase.
java
Copy code
List<String> uNames = [Link]()
.map(name -> [Link]())
.collect([Link]());
java
Copy code
[Link](i -> [Link](i));
java
Copy code
List<String> uNames = [Link]()
.map(String::toUpperCase)
.collect([Link]());
java
Copy code
[Link]([Link]::println);
Conclusion:
Lambda expression:
java
Copy code
[Link]()
.map(name -> [Link]())
.collect([Link]());
java
Copy code
[Link]()
.map(String::toUpperCase)
.collect([Link]());
This eliminates the need to write out lambda expressions where you are only calling a
method.
Explanation:
o String::toUpperCase refers to the method toUpperCase() in the String
class.
o The map() method applies the method for each element in the stream.
2. Constructor Reference:
Scenario Example:
1. Student Class:
o Two attributes: name (String), age (int).
o A constructor that takes name as a parameter.
Example:
java
Copy code
class Student {
private String name;
private int age;
// Constructor
public Student(String name) {
[Link] = name;
[Link] = 0; // Default age
}
java
Copy code
List<Student> students = new ArrayList<>();
for (String name : names) {
[Link](new Student(name)); // Creates Student object with
name
}
java
Copy code
List<Student> students = [Link]()
.map(name -> new Student(name)) //
Lambda creating Student
.collect([Link]());
java
Copy code
List<Student> students = [Link]()
.map(Student::new) // Constructor
reference
.collect([Link]());
Explanation:
3. Key Differences:
java
Copy code
[Link]().map(Student::new).collect([Link]());
Conclusion: