0% found this document useful (0 votes)
13 views37 pages

Java's Collection API 4

An API (Application Programming Interface) is a set of tools that allows software to interact without needing to understand the internal workings. The Collection API in Java provides a framework for managing groups of objects, such as lists, sets, and maps, simplifying data handling. Java APIs also facilitate communication between different parts of a program and external systems, enhancing development efficiency.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
13 views37 pages

Java's Collection API 4

An API (Application Programming Interface) is a set of tools that allows software to interact without needing to understand the internal workings. The Collection API in Java provides a framework for managing groups of objects, such as lists, sets, and maps, simplifying data handling. Java APIs also facilitate communication between different parts of a program and external systems, enhancing development efficiency.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

API & Collection API

Alright! Let's break down API in the simplest way possible.

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.

What’s an API in Java?

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.

What is the Collection API?

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.

1. What is an API (Application Programming Interface)?

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.

Example in everyday life:

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:

 Work with files


 Send data over the internet
 Store data in collections (like arrays, lists, or maps)

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.

3. What is the Collection API?

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];

public class Main {


public static void main(String[] args) {
// Create a list of fruits
ArrayList<String> fruits = new ArrayList<>();

// Add some fruits


[Link]("Apple");
[Link]("Banana");
[Link]("Orange");

// Print the list


[Link](fruits); // Output: [Apple, Banana, Orange]

// 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];

public class Main {


public static void main(String[] args) {
// Create a set of unique numbers
HashSet<Integer> numbers = new HashSet<>();
// Add some numbers
[Link](1);
[Link](2);
[Link](3);
[Link](1); // Duplicate, will not be added

// Print the set


[Link](numbers); // Output: [1, 2, 3] (no duplicates)
}
}

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];

public class Main {


public static void main(String[] args) {
// Create a map to store names and ages
HashMap<String, Integer> people = new HashMap<>();

// Add some key-value pairs


[Link]("John", 25);
[Link]("Alice", 30);
[Link]("Bob", 22);

// Get the age of John


[Link]([Link]("John")); // Output: 25
}
}

Here, you used the HashMap API to store and retrieve data using keys (names) and values
(ages).

4. Why use APIs like Collection API?

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.

5. Other APIs in Java

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:

 API: A set of tools and rules for interacting with software.


 Collection API in Java: A toolkit for working with groups of objects like lists, sets,
and maps.
 Example APIs: ArrayList (a list), HashSet (a set), HashMap (a map).
 APIs make your job easier by providing built-in methods, so you don’t have to write
everything from scratch!

Does this give you a clearer picture of APIs? Let me know if you have any more questions!

In the context of Java APIs, the "software" or "programs" involved aren't


always separate applications like we usually think of in other scenarios
(e.g., a mobile app talking to a weather service). Instead, Java APIs
typically serve as a way for different parts of your Java program to
communicate or interact with libraries, frameworks, and the Java Runtime
Environment (JRE).

Let's break this down further:

1. Java APIs as part of the Java Standard Library (JDK)

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];

public class FileReaderExample {


public static void main(String[] args) {
try {
// Interact with the [Link] API to read a file
BufferedReader reader = new BufferedReader(new
FileReader("[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.

2. Java APIs interacting with external systems or libraries

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:

 Databases (like MySQL or MongoDB)


 Web Servers (to host a website or a web service)
 Third-party APIs (like Google Maps or Twitter’s API)

In these cases, Java APIs help your program communicate with external software.

Summary:

In Java, APIs allow different parts of your program to talk to:

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:

 Java libraries (e.g., Collection API, I/O API)


 External systems (e.g., Databases, Web services)
 Third-party libraries or frameworks (e.g., Google APIs, Spring Framework)

Java Collection Framework

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).

Why Collection API?

 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:

1. Array: Fixed-size, store elements of the same type.


2. Stack (LIFO): Last In First Out.
3. Queue (FIFO): First In First Out.
4. Dynamic Structures: Collection API offers resizable, flexible data structures.

When to Use?

 Use Array when the size is known and fixed.


 Use Collection API for:
o Dynamic sizing.
o Specialized algorithms.
o Simplified operations like sorting, finding unique values, or handling key-
value pairs.
Collection API -> concept
Collection -> Interface
Collections -> classes with multiple methods
different type of data structures
ARRAY LIST:

3. TREE set

Java Collection Framework - Implementation

1. Collection Interface

 Belongs to: [Link] package.


 Interface: Cannot be instantiated directly, requires a class implementing it.
 Common Interfaces:
o List (e.g., ArrayList, LinkedList)
o Queue (e.g., Dequeue)
o Set (e.g., HashSet, LinkedHashSet)
o Map (e.g., HashMap, TreeMap) [Map will be covered later]

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);

 Printing the List:


o Directly:

java
Copy code
[Link](nums); // Output: [6, 5, 8, 2]

o Using Enhanced For Loop:

java
Copy code
for (int n : nums) {
[Link](n);
}

3. Generics in Collections

 Why Use Generics?


o To specify the type of elements the collection will store (e.g., Integer, String).
o Prevents runtime errors and ensures type safety at compile time.
 Example Without Generics:

java
Copy code
Collection nums = new ArrayList();
[Link](5); // Works, but nums is treated as `Object`

o Causes runtime errors if non-integers are added (e.g., "5").


 With Generics:

java
Copy code
List<Integer> nums = new ArrayList<>();

o Prevents non-integer values from being added.

4. ArrayList Key Methods

 add: Add elements to the list.

java
Copy code
[Link](6);

 get: Retrieve elements by index.

java
Copy code
[Link]([Link](2)); // Output: 8 (element at index 2)

 indexOf: Get the index of an element.

java
Copy code
[Link]([Link](5)); // Output: 1

 set: Modify the value at a specific index.

java
Copy code
[Link](1, 10); // Changes value at index 1 to 10

 toArray: Convert list to an array.

java
Copy code
Object[] arr = [Link]();

5. Handling Compile-Time Errors with Generics

 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

6. List vs. Collection

 List supports index-based access, while Collection does not.


 Use List when you need to access elements by index (get, set, indexOf).

7. Enhanced For Loop

 Simplified loop to iterate through a collection:

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

 Order: List maintains the order in which elements are added.

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

 No Guaranteed Order: Set does not maintain the insertion order.

3. HashSet

 Implementation of Set: HashSet is one of the implementations of the Set interface.


 No Order: Elements are not stored in a particular order (not sorted, no insertion
order).
 No Duplicates: Duplicate elements are ignored.

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

 Top-most Interface: Collection interface extends Iterable, allowing the use of


for-each loops and iterators.
 Iterator: Provides a way to loop through elements using an iterator.

java
Copy code
Iterator<Integer> iterator = [Link]();
while ([Link]()) {
[Link]([Link]());
}

7. Iterator vs For-Each Loop

 For-Each Loop: Simple and clean way to iterate over collections.

java
Copy code
for (int num : set) {
[Link](num);
}

 Iterator: More flexible, allows element removal while iterating.

java
Copy code
Iterator<Integer> it = [Link]();
while ([Link]()) {
[Link]([Link]());
}

8. LinkedHashSet

 Maintains Insertion Order: Unlike HashSet, LinkedHashSet maintains the order in


which elements are added.
 No Duplicates: Like other sets, it does not allow duplicate values.

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:

 List: Supports index, allows duplicates, maintains order.


 Set: No index, no duplicates, order may vary.
o HashSet: No order.
o TreeSet: Sorted order.
o LinkedHashSet: Maintains insertion order.

This covers the key points regarding List, Set, HashSet, TreeSet, and how to iterate through
collections using loops and iterators.

MAP:
Map Overview

 Map stores key-value pairs.


 Unlike other collections (List, Set), it does not extend the Collection interface.
 Part of the Java Collection Framework.

Why Use a Map?

 In lists, values are accessed using index numbers (e.g., 0, 1, 2).


 With Map, you use keys instead of indexes.
o Example: Storing student names as keys and their marks as values.
o Keys are more meaningful than just numbers.

Key-Value Pair

 Key: Identifier (e.g., name of a student).


 Value: Associated data (e.g., marks of that student).

Creating a Map
 Map<KeyType, ValueType> mapName = new HashMap<>();
o Example:

java
Copy code
Map<String, Integer> students = new HashMap<>();

Adding Entries

 Use the put() method to add key-value pairs.


o Example:

java
Copy code
[Link]("Navin", 56);
[Link]("Harsh", 23);
Printing the Map

 Simply print the map to see all entries:

java
Copy code
[Link](students);

o Output: {Navin=56, Harsh=23, Sushil=67, Kiran=92}

Key Observations

 Keys are unique (you cannot repeat them).


o If a key exists, put() will replace the value.
 Order is not maintained (unlike lists).

Fetching a Specific Value

 Use get() to fetch a value by its key:

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.

Iterating Over Map Entries

 Use a for-each loop to print all keys and their values:

java
Copy code
for (String key : [Link]()) {
[Link](key + ": " + [Link](key));
}

Key-Related Methods

 keySet(): Returns a Set of all keys.


 values(): Returns a Collection of all values.

Other Important Methods

 remove(key): Removes the key-value pair for a specified key.


 replace(key, newValue): Replaces the value for a given key.
HashMap vs. HashTable

 HashMap: Not synchronized, better for single-threaded environments.


 HashTable: Synchronized, better for multi-threaded environments.
 You can make a HashMap synchronized externally if needed.

----------------------------------------------------------------------------------------------------------------

Sorting in Java with Comparator and Comparable - Detailed Notes

1. Basic Sorting with [Link]()

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);

// Sorting the list


[Link](nums);

// Printing sorted values


[Link](nums); // Output: [3, 4, 7, 9]

 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<>();

2. Custom Sorting using Comparator

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.

 Example: Sort numbers based on their last digit:

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
}
};

[Link](nums, comp); // Sort using comparator


[Link](nums); // Custom sorted output based on last
digit

3. Understanding Comparator

 Comparator is an interface used to define custom sorting logic.


 compare() method: This method takes two values (say i and j) and returns:
o 1 if the first value is greater than the second (and needs to be swapped).
o -1 if the second value is greater (no swap).
o 0 if both are equal.

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]().

5. Sorting Complex Objects (e.g., Student)

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;

public Student(int age, String name) {


[Link] = age;
[Link] = name;
}

@Override
public String toString() {
return name + " (" + age + ")";
}
}

// Creating a list of students


List<Student> students = new ArrayList<>();
[Link](new Student(21, "Naveen"));
[Link](new Student(12, "John"));
[Link](new Student(18, "Parul"));
[Link](new Student(20, "Kiran"));
To sort this list based on age, you can use:

java
Copy code
Comparator<Student> comp = new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
return [Link]([Link], [Link]);
}
};

[Link](students, comp); // Sort students by age


[Link](students);

6. Using Comparable for Natural Sorting

 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;

public Student(int age, String name) {


[Link] = age;
[Link] = name;
}

@Override
public int compareTo(Student that) {
return [Link]([Link], [Link]); // Compare based on
age
}
}

Now, you can sort the list directly:

java
Copy code
[Link](students); // Natural sorting by age using compareTo

7. Difference between Comparator and Comparable

 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).

8. Lambda Expression with Comparator


You can simplify the comparator using lambda expressions (available in Java 8 and
onwards).

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.

9. Ternary Operator in Comparator

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.

Stream API in Java (Introduced in Java 1.8)

Introduction:

 Stream API is a new feature introduced in Java 1.8.


 It provides a more efficient and cleaner way to work with collections (like lists).
 Before Stream API, developers would use loops and conditional checks to perform
operations on collections.
 Stream API simplifies this by offering methods to filter, map, and reduce data in a
declarative manner.

Example: Simple List Operations

We want to work with a list of integers and perform operations like filtering, doubling, and
summing up values.

Steps to Create and Manipulate a List:

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]

3. Operations on List (Without Stream API):

Let's say we want to:

o Filter even numbers (ignore odd numbers).


o Double the even numbers.
o Sum them up.

Example Without Stream API:

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:

o We loop through each element of the list.


o We check if it's even (n % 2 == 0), then double it.
o Finally, we add the doubled values and print the sum.

Example Flow:
For the list [1, 4, 2, 6, 3]:

o Only 4, 2, and 6 are even.


o After doubling: 8, 4, and 12.
o Sum: 8 + 4 + 12 = 24.

Introduction to Stream API:

 Why Stream API?


o Operations like filtering, mapping (changing values), and reducing (summing
values) can be done more easily and cleanly with Stream API.
o Stream API provides methods like:
 filter() to filter elements.
 map() to transform elements (like doubling).
 reduce() to combine elements (like summing them).
Stream API Methods:

 filter(): Filters elements based on a condition.


 map(): Transforms each element.
 reduce(): Combines elements to produce a single result.

Working with Stream API (Preview):

 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:

 stream(): Converts the list into a stream.


 filter(): Keeps only the even numbers.
 map(): Doubles each even number.
 reduce(): Adds all the values to give the final result.

Different Ways to Print List Elements:

1. Using a Standard For Loop:

java
Copy code
for (int i = 0; i < [Link](); i++) {
[Link]([Link](i));
}

2. Using an Enhanced For Loop:

java
Copy code
for (int n : nums) {
[Link](n);
}

3. Using forEach() Method:


o With the forEach() method, you can print each element as follows:

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.

Summary of Important Methods:

 filter(): Used to filter elements based on a condition.


 map(): Used to transform or modify elements.
 reduce(): Used to combine elements to produce a result.
 forEach(): Simplified method to iterate over elements.

Detailed Notes: Understanding forEach and Lambda Expressions in Java 1.8

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.

2. Basic Structure of forEach

 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.

3. Traditional Loop vs forEach


 Old approach (for loop):

java
Copy code
for (int i = 0; i < [Link](); i++) {
[Link]([Link](i));
}

 Enhanced for loop:

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.

4. Understanding the forEach Method Internally

 The forEach method works with a functional interface called Consumer<T>.


o Consumer belongs to [Link] package and has a method
accept(T t) that takes an input and performs an operation.
 Without Lambda Expressions:
o You could use Consumer<Integer> and override the accept method.

java
Copy code
Consumer<Integer> con = new Consumer<Integer>() {
@Override
public void accept(Integer n) {
[Link](n);
}
};
[Link](con);

5. Simplifying Using Lambda Expressions

 What is Lambda Expression?


o Lambda expressions provide a concise way to represent anonymous
functions.
o They can be used wherever functional interfaces are expected.
o In our case, instead of creating an entire Consumer object, we can use lambda
to directly pass the behavior.
 Simplified Lambda Version:

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));

6. Step-by-Step Evolution to Lambda Expressions

 With Consumer Interface:

java
Copy code
Consumer<Integer> con = (Integer n) -> {
[Link](n);
};
[Link](con);

 Simplifying by Removing Unnecessary Parts:


o Remove type (Integer is inferred):

java
Copy code
Consumer<Integer> con = (n) -> {
[Link](n);
};
[Link](con);

o Since only one parameter, parentheses () are optional:

java
Copy code
Consumer<Integer> con = n -> {
[Link](n);
};
[Link](con);

o One statement means curly braces {} can be omitted:

java
Copy code
Consumer<Integer> con = n -> [Link](n);
[Link](con);

 Final Version with Inline Lambda:


o You don’t need a Consumer object. You can directly pass the lambda
expression:

java
Copy code
[Link](n -> [Link](n));

7. Key Takeaways: forEach with Lambda Expressions

 forEach simplifies looping over collections.


 Lambda expressions make the code concise and readable.
 No need for creating separate Consumer objects; you can directly pass the lambda.

What's Next: Stream API

 After understanding forEach, you’re ready to dive into Stream API.


 Stream API will help you perform more complex operations (like filtering, mapping,
reducing) efficiently.

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

Notes on Java Stream API

Introduction to Stream API

 Stream is an interface introduced in Java 8.


 Provides a way to process collections of data in a functional style.
 Allows operations on the data without modifying the original collection.

Creating a Stream

 You can create a stream from a collection (e.g., List).


 Example:

java
Copy code
Stream<Integer> s1 = [Link]();

 Operations on the stream do not affect the original collection (nums).

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.

Benefits of Using Streams

 Streams provide a variety of methods to manipulate data:


o Filter: To exclude certain elements.
o Map: To transform elements.
o Reduce: To aggregate elements into a single value.

Example Operations with Streams

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);

Stream Operations Explained

 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).

Chaining Stream Operations

 You can chain multiple operations in a single statement:

java
Copy code
int result = [Link]()
.filter(n -> n % 2 == 0)
.map(n -> n * 2)
.reduce(0, (c, e) -> c + e);

 This method is often more readable than traditional loops.

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.

Java Stream API Overview

The Java Stream API allows for functional-style operations on streams of elements, such as
filtering, mapping, and reducing data.

1. Filter

 Purpose: To select elements from a stream that meet a specific condition.


 Predicate: The filter method requires an object of Predicate, which is a functional
interface.
o Definition: Predicate has a single method test(T t) that returns a boolean
value.
o Example: To filter even numbers, you would use a Predicate that checks if a
number is even.

Code Example:

java
Copy code
import [Link];

Predicate<Integer> p = n -> n % 2 == 0; // Lambda expression to check if n


is even
[Link](p); // Filter stream using the Predicate
2. Map

 Purpose: To transform each element in a stream into another form.


 Function: The map method takes an object of Function, which is another functional
interface.
o Definition: Function<T, R> has a method apply(T t) that takes a value and
returns another value.

Code Example:

import [Link];

Function<Integer, Integer> fun = n -> n * 2; // Lambda to double the value


[Link](fun); // Apply transformation to each element

3. Reduce

 Purpose: To aggregate the elements of a stream into a single result.


 Binary Operator: The reduce method uses a BinaryOperator, which is a specialized
type of BiFunction.
o Definition: It takes two values and returns one, allowing operations like
summation or concatenation.

Example: To sum a list of numbers:

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

4. Sorting and Parallel Streams

 Sorting: After filtering, you can sort the stream using the sorted() method.

Code Example:

java
Copy code
[Link](value -> [Link](value)); // Print sorted
values

 Parallel Streams: For performance improvements, you can use parallelStream()


to leverage multiple threads for operations that don’t require sorted order.

Note: Avoid using parallelStream() with sorting because sorting requires all elements to
be in order.

Summary

 Filter selects elements based on a condition (Predicate).


 Map transforms each element in the stream (Function).
 Reduce aggregates elements into a single value (BinaryOperator).
 Sorting and parallel streams offer additional capabilities for managing data
effectively.

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!

Exploring Parallel Streams in Java

1. Introduction

 Topic: Expansion on the use of parallel streams.


 Purpose: Demonstrate the benefits of parallel streams with a large dataset.

2. Creating a Large Dataset

 Objective: Generate a list of 10,000 random integers to illustrate parallel processing.

Steps to Create the Dataset:

 Import Required Packages:

java
Copy code
import [Link];
import [Link];
import [Link];

 Initialize List:

java
Copy code
List<Integer> nums = new ArrayList<>(10000);

 Generate Random Numbers:


o Use the Random class to create random integers.
o Add 10,000 random integers to the list using a loop.

Random ran = new Random();


for (int i = 0; i < 10000; i++) {
[Link]([Link](100)); // Generate numbers between 0 and 99
}

3. Processing the Data

 Objective: Multiply each number by 2 and calculate the sum.

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

 Using Parallel Stream:

java
Copy code
int sum3 = [Link]()
.mapToInt(i -> i * 2) // Same as above but in
parallel
.sum();

4. Measuring Execution Time

 Calculate Execution Time for Sequential and Parallel Streams:

java
Copy code
long startSeq = [Link]();
// Sum operation for Sequential Stream
long endSeq = [Link]();

long startPara = [Link]();


// Sum operation for Parallel Stream
long endPara = [Link]();

[Link]("Sequential Time: " + (endSeq - startSeq));


[Link]("Parallel Time: " + (endPara - startPara));

5. Observing Performance Differences

 Observation: Sequential streams are faster for simple operations due to the overhead of
managing threads in parallel streams.

6. Adding Delay for Testing

 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]();
}

 Re-run the Timing with Delay:


o The sequential stream will take longer (e.g., 13 seconds).
o The parallel stream will perform better (e.g., around 1.4 seconds) due to parallel
processing.

7. Key Takeaways

 Use Parallel Streams:


o Effective for independent operations.
o Not suitable for dependent operations (e.g., sorting).
 Best Practices:
o Use parallel streams wisely to avoid unnecessary complexity and potential bugs.
o Measure performance before and after implementing parallel streams.

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

1. Why Was Optional Introduced 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:

 Consider a list of names:

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".

3. Traditional Approach (Without Optional):

 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.

4. Solution with Optional:

 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>

 Optional provides methods to avoid NPE when the value is absent.

5. How to Handle Optional Values:

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():

 To provide a default value when the Optional is empty:

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.

c) Combining findFirst() and orElse():

 You can combine findFirst() and orElse() to simplify code:

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.

6. Full Example with Optional:


java
Copy code
import [Link];
import [Link];
import [Link];

public class OptionalEx {


public static void main(String[] args) {
List<String> names = [Link]("Navin", "Laxmi", "John",
"Kishor");

// Using Optional to find first name with 'x'


Optional<String> nameWithX = [Link]()
.filter(name ->
[Link]("x"))
.findFirst();

// Print the name if present, else print "Not Found"


[Link]([Link]("Not Found"));
}
}

7. Benefits of Using Optional:

 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:

 .isPresent(): Checks if a value is present in the Optional.


 .get(): Retrieves the value if present (risky to use without checking .isPresent()).
 .orElse(T other): Returns the value if present; otherwise returns the specified
default value.
 .orElseGet(Supplier<? extends T> other): Similar to orElse(), but lazy
evaluation (executes only when needed).
 .orElseThrow(Supplier<? extends X> exceptionSupplier): Throws an
exception if the value is not present.

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.

Method References in Java (Java 8 Feature)

Introduction to Method Reference:

 Method reference was introduced in Java 8.


 It allows us to refer to a method without explicitly invoking it.
 It’s a shorter way of writing code when a method can be reused.

Example Setup:

1. List of names:

java
Copy code
List<String> names = [Link]("Navin", "Harsh", "John");

2. Goal:
o Print all names in uppercase.

Traditional Approach (Before Method Reference):

1. Use streams to convert all names to uppercase:

java
Copy code
List<String> uNames = [Link]()
.map(name -> [Link]())
.collect([Link]());

o stream() creates a stream from the list.


o map() applies the transformation (here, converting to uppercase).
o toUpperCase() converts the string to uppercase.
o collect([Link]()) converts the stream back to a list.
2. Printing the names:

java
Copy code
[Link](i -> [Link](i));

o forEach() iterates over each element in uNames and prints it.

Introducing Method Reference:

1. What is Method Reference?


o Instead of passing a lambda expression, you pass the method name directly.
o It simplifies code when the lambda is only calling an existing method.
2. Syntax:
o ClassName::methodName or Object::methodName.
o Example: String::toUpperCase (Refers to the toUpperCase method of the
String class).

Code with Method Reference:

1. Simplifying the map() step using method reference:

java
Copy code
List<String> uNames = [Link]()
.map(String::toUpperCase)
.collect([Link]());

o String::toUpperCase refers to the method of the String class for each


element in the stream.
o The rest of the code remains the same.
2. Simplifying the forEach() step:
o Instead of using i -> [Link](i), we can use method
reference:

java
Copy code
[Link]([Link]::println);

o [Link]::println refers to the println method of [Link], which


prints each value.

Summary of Method Reference Usage:

 Method reference simplifies code by passing a method to another method.


 Types of Method References:
1. Static Method Reference: ClassName::staticMethodName
2. Instance Method Reference: object::instanceMethodName
3. Constructor Reference: ClassName::new

Conclusion:

 Method reference improves code readability and makes it more concise.


 It's useful in functional programming style, introduced in Java 8.

Method Reference Recap:

 Method Reference is used to refer to a method directly, without explicitly specifying


the variable or parameter names.
 Streams provide a way to process a collection of objects.
 If you want to convert every value in a stream to uppercase, you can:

Lambda expression:

java
Copy code
[Link]()
.map(name -> [Link]())
.collect([Link]());

Method reference (simplified):

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:

 Constructor Reference is a special type of method reference that refers to a


constructor instead of a regular method.
 It's used when you need to create a new instance of a class in a streamlined manner,
especially when working with streams.

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
}

// Getters, setters, and toString() method (for printing the


object)
}

2. Creating Student Objects:


o We have a list of student names, and we want to create student objects for
each name.

Traditional Way (without streams):

java
Copy code
List<Student> students = new ArrayList<>();
for (String name : names) {
[Link](new Student(name)); // Creates Student object with
name
}

3. Stream with Lambda Expression:


o Using the Stream API and map() to create Student objects from a list of
names:

java
Copy code
List<Student> students = [Link]()
.map(name -> new Student(name)) //
Lambda creating Student
.collect([Link]());

4. Using Constructor Reference:


o We can further simplify the lambda expression using constructor reference:

java
Copy code
List<Student> students = [Link]()
.map(Student::new) // Constructor
reference
.collect([Link]());

Explanation:

o Student::new refers to the constructor of the Student class.


o Every name in the stream is passed to the constructor to create a new Student
object.

3. Key Differences:

 Lambda Expression (Explicit):

[Link]().map(name -> new


Student(name)).collect([Link]());

 Constructor Reference (Simplified):

java
Copy code
[Link]().map(Student::new).collect([Link]());

4. Advantages of Constructor Reference:

 Cleaner and more readable code.


 Helps avoid boilerplate code by directly referring to the constructor.
 Useful when dealing with streams and collections where object creation is frequent.

5. General Syntax for Constructor Reference:


ClassName::new

This will invoke the constructor of the class specified.

Conclusion:

 Method Reference simplifies method calls inside streams.


 Constructor Reference is a type of method reference that allows us to create objects
more cleanly within streams.
 Both references make the code more concise and readable while leveraging the power
of Java 8 functional programming.

You might also like