Key Concepts
Directions: Fill in the blanks, this is a Popcorn HACK
Hashing
- HashMap uses a hash function to map **keys** to their respective **buckets(data structure)** .
- A good hash function generates a unique hash code for each key, but **collisions** can still occur.
- The hash map in Java does not maintain insertion order.
Performance
- HashMap provides constant-time performance (O(1)) for get() and put() operations.
- Performance can degrade to O(n) in the worst case, especially if there are many hash collisions.
Key and Value Types
- HashMap allows any **non-null** object as a key and any **object** (including null) as a value.
- For a class to be used as a key, it must implement the **equals()** and **hashCodes()** methods.
Iteration:
- HashMap provides methods like keySet(), values(), and entrySet() for iterating over key-value pairs.
- The entrySet() method returns a Set view of key-value pairs, allowing **iteration** and **modification**.
Thread Safety
- HashMap is not thread-safe. For thread-safe operations, use ConcurrentHashMap.
What is HashMap
A HashMap store items in “key/value” pairs, and you can access them by an index of another type (e.g. a String).
One object is used as a key (index) to another object (value). It can store different types: String keys and Integer values, or the same type, like: String keys and String values:
Creating HashMap in Java
import java.util.HashMap; // import the HashMap class
public class CreateHashMap{
public static void main(String[] args){
// Generating the HashMap
HashMap<String, String> capitalCities = new HashMap<String, String>();
// Adding key/value pairs tothe HashMap to store
capitalCities.put("America", "D.C");
capitalCities.put("Germany", "Berlin");
capitalCities.put("United Kingdom", "London");
capitalCities.put("India", "Delhi");
capitalCities.put("Afghanistan", "Delhi");
capitalCities.put("Bangladesh", "Dhaka");
System.out.println("Successfully created a HashMap which stores items in key/value pairs");
}
}
CreateHashMap.main(null);
Successfully created a HashMap which stores items in key/value pairs
Methods in HashMap
import java.util.HashMap;
public class ExampleHashMap {
public static void main(String[] args) {
// Create a HashMap
HashMap<String, Integer> hashMap = new HashMap<>();
// Add elements to the HashMap
hashMap.put("Shivansh", 25);
hashMap.put("Shaurya", 30);
hashMap.put("Patrick Mahomes", 28);
hashMap.put("Travis Kelce", 34);
hashMap.put("Tom Brady", 46);
// HashMap put() method in Java (Access elements in the HashMap)
System.out.println(hashMap.get("Shivansh"));
// HashMap remove() method in Java (Remove an element from the HashMap)
hashMap.remove("Tom Brady");
// HashMap size() method in Java (Get the size of the HashMap)
System.out.println(hashMap.size());
// HashMap entrySet() method in Java (Get the Entry Set)
System.out.println("The set is: " + hashMap.entrySet());
// HashMap containsKey() method in Java (check whether a particular key is being mapped into the HashMap or not)
System.out.println("Is the key 'Shivansh' present? " + hashMap.containsKey("Shivansh"));
}
}
ExampleHashMap.main(null);
25
4
The set is: [Travis Kelce=34, Shivansh=25, Shaurya=30, Patrick Mahomes=28]
Is the key 'Shivansh' present? true
Popcorn Hack 1
Declare a Hashmap, and then research 5 different HashMap method which were not listed above and use them in your code just like the one above.
**put, get, remove, keySet, and size.**
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class HashMapExample {
public static void main(String[] args) {
// Declare a HashMap with Integer keys and String values
Map<Integer, String> hashMap = new HashMap<>();
// 1. Put method to add key-value pairs to the HashMap
hashMap.put(1, "One");
hashMap.put(2, "Two");
hashMap.put(3, "Three");
// 2. Get method to retrieve a value based on a key
int keyToRetrieve = 2;
String value = hashMap.get(keyToRetrieve);
System.out.println("Value associated with key " + keyToRetrieve + ": " + value);
// 3. Remove method to remove a key-value pair
int keyToRemove = 1;
hashMap.remove(keyToRemove);
System.out.println("HashMap after removing key " + keyToRemove + ": " + hashMap);
// 4. keySet method to get a Set of all keys in the HashMap
Set<Integer> keySet = hashMap.keySet();
System.out.println("Keys in the HashMap: " + keySet);
// 5. Size method to get the number of key-value pairs in the HashMap
int size = hashMap.size();
System.out.println("Size of the HashMap: " + size);
}
}
HashMapExample.main(null)
Value associated with key 2: Two
HashMap after removing key 1: {2=Two, 3=Three}
Keys in the HashMap: [2, 3]
Size of the HashMap: 2
Traversing through HashMap
In the code below, hash_map.entrySet() is used to return a set view of the mapped elements. Now, getValue() and getKey() functions, key-value pairs can be iterated.
import java.util.HashMap;
public class TraverseHashMap{
public static void main(String[] args){
// Week 15 NFL Quarterback Rankings
HashMap<Integer, String> hash_map = new HashMap<>();
hash_map.put(1, "Jalen Hurts");
hash_map.put(2, "Dak Prescott");
hash_map.put(3, "Josh Allen");
hash_map.put(4, "Lamar Jackson");
hash_map.put(5, "Brock Purdy");
for (Map.Entry<Integer, String> set : hash_map.entrySet()) {
System.out.println(set.getKey() + " = " + set.getValue());
}
}
}
TraverseHashMap.main(null);
1 = Jalen Hurts
2 = Dak Prescott
3 = Josh Allen
4 = Lamar Jackson
5 = Brock Purdy
Popcorn Hack 2 (Extra Credit)
Try to find a different way to traverse a HashMap (Hint: try using a forEach function)
import java.util.HashMap;
import java.util.Map;
public class TraverseHashMap {
public static void main(String[] args) {
// Week 15 NFL Quarterback Rankings
HashMap<Integer, String> hash_map = new HashMap<>();
hash_map.put(1, "Jalen Hurts");
hash_map.put(2, "Dak Prescott");
hash_map.put(3, "Josh Allen");
hash_map.put(4, "Lamar Jackson");
hash_map.put(5, "Brock Purdy");
// Using forEach to traverse the HashMap
hash_map.forEach((key, value) -> System.out.println(key + " = " + value));
}
}
TraverseHashMap.main(null)
1 = Jalen Hurts
2 = Dak Prescott
3 = Josh Allen
4 = Lamar Jackson
5 = Brock Purdy
HashMaps in Java - Pet Registry Example
public class Pet {
private final String name;
private final int age;
private final String color;
public Pet(String name, int age, String color) {
this.name = name;
this.age = age;
this.color = color;
}
public String getName() {
return this.name;
}
public int getAge() {
return this.age;
}
public String getColor() {
return this.color;
}
}
public class PetsRegistry {
private HashMap<String, Pet> petRegistry = new HashMap<>(); // declares a private HashMap instance variable petRegistry
// Key Type String and Value Type Pet
public PetsRegistry() {
// Add some pets to the registry
petRegistry.put("Leo", new Pet("Lion", 8, "Gold"));
petRegistry.put("Porky", new Pet("Pig", 3, "Pink"));
petRegistry.put("Ro-Ro", new Pet("Robin", 7, "Red"));
petRegistry.put("Midnight", new Pet("Cat", 10, "Black"));
petRegistry.put("Hobbes", new Pet("Kitty", 1, "Calico"));
petRegistry.put("Duke", new Pet("Dog", 14, "Brown"));
}
public Pet removePet(String name) {
// Remove a pet by name
return petRegistry.remove(name);
}
public void printRegistry() {
// Iterate over the registry and print pet information
for (String name : petRegistry.keySet()) { // for each loop
Pet pet = petRegistry.get(name);
System.out.println(name + " is a " + pet.getColor() + " " + pet.getName() +
" and is " + pet.getAge() + " years old.");
}
System.out.println();
}
public static void main(String[] args) {
// Initialize the pet registry
PetsRegistry petsRegistry = new PetsRegistry();
petsRegistry.printRegistry();
// Remove a pet
String petNameToRemove = "Hobbes";
Pet removedPet = petsRegistry.removePet(petNameToRemove);
if (removedPet == null) {
System.out.println(petNameToRemove + " not found");
} else {
System.out.println("Removed: " + petNameToRemove + ", " + removedPet);
}
// Print the updated registry
petsRegistry.printRegistry();
}
}
PetsRegistry.main(null)
Hobbes is a Calico Kitty and is 1 years old.
Leo is a Gold Lion and is 8 years old.
Porky is a Pink Pig and is 3 years old.
Ro-Ro is a Red Robin and is 7 years old.
Duke is a Brown Dog and is 14 years old.
Midnight is a Black Cat and is 10 years old.
Removed: Hobbes, REPL.$JShell$13$Pet@41a890b3
Leo is a Gold Lion and is 8 years old.
Porky is a Pink Pig and is 3 years old.
Ro-Ro is a Red Robin and is 7 years old.
Duke is a Brown Dog and is 14 years old.
Midnight is a Black Cat and is 10 years old.
Popcorn HACK 3 (Shaurya)
import java.util.HashMap;
import java.util.Map;
public class HashMapTest {
public static void main(String[] args) {
// Create a new HashMap with Integer keys and String values
Map<Integer, String> myMap = new HashMap<>();
// Add some key-value pairs to the HashMap
myMap.put(1, "Apple");
myMap.put(2, "Banana");
myMap.put(3, "Cherry");
// Fill in the blanks: Retrieve and print the value for key 2
String valueForKey2 = myMap.get(2);
System.out.println("Value for key 2: " + valueForKey2);
// Fill in the blanks: Check if the HashMap contains key 4
boolean containsKey4 = myMap.containsKey(4);
System.out.println("Does the map contain key 4? " + containsKey4);
// Fill in the blanks: Remove the entry with key 1 from the HashMap
myMap.remove(1);
// Print the updated contents of the HashMap
System.out.println("Updated HashMap:");
for (Map.Entry<Integer, String> entry : myMap.entrySet()) {
System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
}
}
}
HashMapTest.main(null)
Value for key 2: Banana
Does the map contain key 4? false
Updated HashMap:
Key: 2, Value: Banana
Key: 3, Value: Cherry
Popcorn HACK 4 - Quiz (Shaurya)
Multiple Choice:
Question 1: Hashing in HashMap
Answer 1:
B) To map keys to corresponding buckets
The primary purpose of a hash function in a HashMap is to map keys to corresponding buckets. This helps in efficient storage and retrieval of key-value pairs by distributing them across different buckets based on their hash codes. This process allows for fast lookup times when retrieving values associated with a given key.
Answer 2:
C) O(1)
The time complexity of the get()
and put()
operations in a well-distributed HashMap is O(1), constant time. This is because, in an ideal scenario where hash codes are well distributed and collisions are minimal, the HashMap allows for direct access to the desired element or bucket, resulting in constant time complexity for these operations.
Answer 3:
In a HashMap:
-
Key Types: Any object can be used as a key, but for effective usage, the key should override
hashCode()
andequals()
methods. This ensures proper hashing and correct handling of key collisions. -
Value Types: Any object, including null values, can be used as a value.
To be used as a key, a class should implement the following methods:
hashCode()
: Returns an integer hash code for the object.equals(Object obj)
: Compares the current object with another for equality.
These methods are crucial for proper functioning of the HashMap, ensuring correct placement of key-value pairs and accurate retrieval.
Answer 4:
Two methods for iterating over key-value pairs in a HashMap:
-
Using entrySet(): The
entrySet()
method returns a set view of the key-value pairs. You can then iterate over this set using an enhanced for loop. This method provides direct access to both keys and values.for (Map.Entry<KeyType, ValueType> entry : hashMap.entrySet()) { // Access entry.getKey() and entry.getValue() here }
-
Using keySet(): The
keySet()
method returns a set of keys. You can then iterate over the set and use each key to retrieve the corresponding value.for (KeyType key : hashMap.keySet()) { // Access key and hashMap.get(key) to get the value }
Answer 5:
HashMap is not thread-safe because it is not synchronized. If multiple threads access a HashMap concurrently and at least one of the threads modifies the map structurally, it must be synchronized externally.
Issues that might arise:
-
Concurrent Modification Exception: If one thread is iterating over the HashMap while another modifies it, a
ConcurrentModificationException
can be thrown. -
Inconsistent State: Multiple threads might read and write the HashMap concurrently, leading to an inconsistent state and unexpected behavior.
Alternative for concurrent access: ConcurrentHashMap
is a class that provides thread-safety without the need for external synchronization. It allows concurrent access to different parts of the map, improving performance in scenarios with high concurrency.
HACKS (Shaurya)
1) Finish Popcorn HACKS 2) Develop a Java application that utilizes a HashMap to manage a sports team roster. Each player on the team should have attributes like name, position, and jersey number. The program should enable functionalities such as adding new players, updating player information, and searching for players based on their jersey numbers using the HashMap implementation. 3) Reflection (4-5 sentences)
**Reflection**
This Java application utilizes a HashMap to manage a sports team roster. It provides functionalities for adding new players, updating player information, and searching for players based on their jersey numbers. The program demonstrates the use of a HashMap to store player objects with jersey numbers as keys, enabling efficient retrieval and manipulation of player data. The modular design and user-friendly menu make it easy to interact with the roster. The use of a Player class encapsulates player attributes and enhances code readability. Overall, this application showcases the versatility and efficiency of HashMaps in managing and organizing data.
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
// Class to manage a sports team roster using a HashMap
public class SportsTeamRoster {
public static void main(String[] args) {
// HashMap to store player information with jersey numbers as keys
Map<Integer, Player> roster = new HashMap<>();
Scanner scanner = new Scanner(System.in);
// Sample data for demonstration
roster.put(10, new Player("John Doe", "Forward", 10));
roster.put(23, new Player("Jane Smith", "Guard", 23));
// Menu-driven program
while (true) {
System.out.println("\nMenu:");
System.out.println("1. Add new player");
System.out.println("2. Update player information");
System.out.println("3. Search for player by jersey number");
System.out.println("4. Exit");
System.out.print("Enter your choice: ");
int choice = scanner.nextInt();
// Switch statement to handle user choices
switch (choice) {
case 1:
addNewPlayer(roster, scanner);
break;
case 2:
updatePlayerInformation(roster, scanner);
break;
case 3:
searchPlayerByJerseyNumber(roster, scanner);
break;
case 4:
System.out.println("Exiting the program. Goodbye!");
System.exit(0);
default:
System.out.println("Invalid choice. Please try again.");
}
}
}
// Method to add a new player to the roster
private static void addNewPlayer(Map<Integer, Player> roster, Scanner scanner) {
System.out.println("Enter player details:");
System.out.print("Name: ");
String name = scanner.next();
System.out.print("Position: ");
String position = scanner.next();
System.out.print("Jersey Number: ");
int jerseyNumber = scanner.nextInt();
Player newPlayer = new Player(name, position, jerseyNumber);
roster.put(jerseyNumber, newPlayer);
System.out.println("Player added successfully!");
}
// Method to update player information in the roster
private static void updatePlayerInformation(Map<Integer, Player> roster, Scanner scanner) {
System.out.print("Enter the jersey number of the player to update: ");
int jerseyNumber = scanner.nextInt();
if (roster.containsKey(jerseyNumber)) {
System.out.println("Enter updated player details:");
System.out.print("Name: ");
String name = scanner.next();
System.out.print("Position: ");
String position = scanner.next();
Player updatedPlayer = new Player(name, position, jerseyNumber);
roster.put(jerseyNumber, updatedPlayer);
System.out.println("Player information updated successfully!");
} else {
System.out.println("Player not found with jersey number " + jerseyNumber);
}
}
// Method to search for a player by jersey number
private static void searchPlayerByJerseyNumber(Map<Integer, Player> roster, Scanner scanner) {
System.out.print("Enter the jersey number to search for: ");
int jerseyNumber = scanner.nextInt();
if (roster.containsKey(jerseyNumber)) {
Player player = roster.get(jerseyNumber);
System.out.println("Player found:");
System.out.println(player);
} else {
System.out.println("Player not found with jersey number " + jerseyNumber);
}
}
}
// Class representing a player with name, position, and jersey number
class Player {
private String name;
private String position;
private int jerseyNumber;
// Constructor to initialize player attributes
public Player(String name, String position, int jerseyNumber) {
this.name = name;
this.position = position;
this.jerseyNumber = jerseyNumber;
}
// Override toString method for better printing of Player objects
@Override
public String toString() {
return "Player{" +
"name='" + name + '\'' +
", position='" + position + '\'' +
", jerseyNumber=" + jerseyNumber +
'}';
}
}
SportsTeamRoster.main(null)
Lesson: Collections in Java and SQL
Introduction to Collections in Java
In Java, the Collection
interface is a member of the Java Collections Framework and extends the Iterable
interface. It includes methods for basic operations (such as add
, remove
, clear
), bulk operations (such as containsAll
, addAll
, retainAll
, removeAll
), and array operations (such as toArray
).
import java.util.*;
public class Main {
public static void main(String[] args) {
// Creating an ArrayList
List<String> list = new ArrayList<String>();
// Adding elements to the list
list.add("Apple");
list.add("Banana");
list.add("Cherry");
System.out.println("List: " + list);
}
}
Definition of Collections
In the context of SQL, collections refer to a group of related data items that can be treated as a whole. Common types of collections include arrays, lists, and sets.
Using Collections with SQL
When working with databases in Java, you can use the java.sql
` package. This package provides classes for connecting to a database and executing SQL queries.
import java.sql.*;
import java.util.*;
public class Main {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/mydatabase";
String user = "root";
String password = "password";
try {
Connection conn = DriverManager.getConnection(url, user, password);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM mytable");
// Creating a list to store the results
List<String> results = new ArrayList<String>();
while (rs.next()) {
results.add(rs.getString("mycolumn"));
}
System.out.println("Results: " + results);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
In this code, we’re connecting to a MySQL database and executing a SQL query. The results of the query are then stored in an ArrayList
Purpose of Collections
Collections are useful in a database because they allow you to store multiple values in a single column. This can be beneficial in scenarios where you have a one-to-many relationship. For example, a single product could have multiple colors, sizes, or other attributes.
Important terminology
- Elements: Individual items within a collection.
- Indexes: The position of an element within a collection.
- Scalar: A single value, as opposed to a collection which can hold multiple values.
Advanced usage in Collections
Nested Collections
Collections can be nested, creating a collection of collections, for more freeform control, such as representing a 2D map with a 2D array.
public class NestedArrays {
public static void print2Darray(int[][] arr){
// function for printing arrays
for (int i=0;i<arr.length;i++){
for (int j=0;j<arr[i].length;j++){
System.out.print(arr[i][j]+" ");
}
System.out.println();
}
}
public static void main(String[] args){
// Direct declaration of an array containing arrays
int[][] arr = {
{8,1,6},
{3,5,7},
{4,9,2}
};
print2Darray(arr);
System.out.println(arr[1][2]);//printing the value at [1][2] (7)
arr[1][2] = 0; //assigning a new value to inside the 2D array
System.out.println(arr[1][2]);
}
}
NestedArrays.main(null);
Popcorn hacks
Create a program that sums the columns and the rows of the given nested array (should all be 15), then create a copy of the original array by looping through the original array and assigning the values to a new array.
public class NestedArraysPopcorn {
// Function for printing arrays
public static void print2Darray(int[][] arr) {
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
}
public static void main(String[] args) {
int[][] arr = {
{8, 1, 6},
{3, 5, 7},
{4, 9, 2}
};
// Calculate the sums of rows and columns
int[] rowSums = new int[arr.length];
int[] colSums = new int[arr[0].length];
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
rowSums[i] += arr[i][j];
colSums[j] += arr[i][j];
}
}
// Print the original array
System.out.println("Original Array:");
print2Darray(arr);
// Print the sums of rows
System.out.println("\nSums of Rows:");
for (int i = 0; i < rowSums.length; i++) {
System.out.println("Row " + (i + 1) + ": " + rowSums[i]);
}
// Print the sums of columns
System.out.println("\nSums of Columns:");
for (int i = 0; i < colSums.length; i++) {
System.out.println("Column " + (i + 1) + ": " + colSums[i]);
}
// Create a copy of the original array
int[][] copyArray = new int[arr.length][arr[0].length];
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
copyArray[i][j] = arr[i][j];
}
}
// Print the copied array
System.out.println("\nCopied Array:");
print2Darray(copyArray);
}
}
NestedArraysPopcorn.main(null)
Original Array:
8 1 6
3 5 7
4 9 2
Sums of Rows:
Row 1: 15
Row 2: 15
Row 3: 15
Sums of Columns:
Column 1: 15
Column 2: 15
Column 3: 15
Copied Array:
8 1 6
3 5 7
4 9 2
Null values in collections
null values are placeholders that are implemented when there is not any value that is inputed, you see it when we call the main method in our programs. It is automatically created when a new reference variable (such as an Integer) is created but no values have been assigned to it yet. It can also be created directly.
Having null values in a collection will not immediately crash the program, however, it can cause a NullPointerException error if it is used carelessly. So it is important to learn how to identify and filter it.
import java.util.ArrayList;
public class NullValuesInArray {
public static void main(String[] args){
Integer[] arr = new Integer[10];//array of Integer
System.out.println(arr[3]);
// if the following line of code is ran, it will return a NullPointerException error
//System.out.println(1+arr[2]);
for (int i=0;i<arr.length;i++){
arr[i]=0;// sets the values in the arr to 0
}
System.out.println(1+arr[2]);
}
}
NullValuesInArray.main(null);//using null values in the main method
Popcorn hacks
The given array has certain values set to null, loop through to set all null values to 0, then sum every value in the array.
public class NullValuesArrayPopcorn {
public static void main(String[] args) {
Integer[] arr = { 4, 5, 6, null, 9, 10, null, 9, 3, 2, 5, null };
// Loop through to set null values to 0
for (int i = 0; i < arr.length; i++) {
if (arr[i] == null) {
arr[i] = 0;
}
}
// Sum every value in the array
int sum = 0;
for (Integer value : arr) {
sum += value;
}
// Print the modified array and the sum
System.out.println("Modified Array:");
for (Integer value : arr) {
System.out.print(value + " ");
}
System.out.println("\nSum of all values: " + sum);
}
}
NullValuesArrayPopcorn.main(null)
Modified Array:
4 5 6 0 9 10 0 9 3 2 5 0
Sum of all values: 53
Performance and Complexities
All of the functions used in collections takes a certain time complexity to do, and it may be sometimes better to use one value over the other. Here are some time complexities for commonly used methods
Method | Time Complexity |
---|---|
Initialization | O(n) |
Accessing (arr[i] get(i)) | O(1) |
Assignment (arr[i]=a, set(i,a)) | O(1) |
Sorting (Array.sort(arr), sort(Comparator)) | O(nlog(n)) |
Length (length, size()) | O(1) |
copy (clone(), arraycopy()) | O(n) |
The space complexity of a collection is its size.
Most of the time, the array is a versatile tool that can effeciently store and process values, however, sometimes we would want a different requirement. For example, when we want a storage to always be sorted, while we could use some sort of binary search method to find the best position to insert a value, there are just data structures, such as TreeSet, that maintains sorted status upon insertion. It’s important to use the data structure that best suits your need in the right context.
Real world applications of Collections
In the context of an application or a database, a collection can allow for large amounts of values to be stored efficiently without creating large amounts of variables, storing what’s usually a column of information in a single cell (I guess then, then that’s also a collection of collection in of itself). It can be used for when you don’t know how long that a list can be, you can modify the values in a collection easily also. However, the usage of many collections can add a lot of unnecessary weight on the database due to the extra spaces used, and it can be hard to keep track of what functions should be used for modifying certain values in a collection.
Usage of Collections in SQL
In SQL, collections are powerful data types that allow us to store multiple values. Let’s delve into declaring different types of collections.
-- Syntax for declaring an array
DECLARE TYPE Array_Type IS VARRAY(5) OF VARCHAR2(50);
-- Syntax for declaring a nested table
DECLARE TYPE Nested_Table_Type IS TABLE OF NUMBER;
-- Syntax for declaring an associative array
DECLARE TYPE Assoc_Array_Type IS TABLE OF VARCHAR2(50) INDEX BY PLS_INTEGER;
Explanation:
In SQL, we can declare different types of collections to store multiple values. An array is defined with a fixed size of 5, specifically designed to accommodate VARCHAR2 values. Simultaneously, a nested table is declared to store numeric values, offering flexibility in handling numerical data. Additionally, an associative array is declared with an index of PLS_INTEGER, providing a dynamic structure to hold VARCHAR2 values based on the specified index. These declarations showcase the versatility of collections in SQL, allowing for efficient management of various data types.
Initialization of Collections
Now, let’s initialize these collections using different methods.
-- Initializing an array
DECLARE
my_array Array_Type := Array_Type('Value1', 'Value2', 'Value3');
-- Initializing a nested table
DECLARE
my_table Nested_Table_Type := Nested_Table_Type(1, 2, 3);
-- Initializing an associative array
DECLARE
my_assoc_array Assoc_Array_Type;
BEGIN
my_assoc_array(1) := 'Item1';
my_assoc_array(2) := 'Item2';
END;
Explanation:
In the initialization phase, the array is populated with predefined values using its constructor, ensuring specific elements are set from the start. Meanwhile, the nested table is initialized with numeric values, establishing its initial content based on numerical data. In contrast, the associative array takes a more dynamic approach, as values are individually assigned within a BEGIN-END block, allowing for flexible and tailored initialization based on specific requirements or conditions.
Adding, Removing, and Modifying Elements
Now, let’s explore how to perform fundamental operations on collections.
-- Adding elements to an array
my_array.EXTEND;
my_array(4) := 'Value4';
-- Removing elements from a nested table
my_table.DELETE(2);
-- Modifying an element in an associative array
my_assoc_array(1) := 'UpdatedItem';
Explanation:
In this sequence of operations, the array undergoes extension to accommodate a new element, subsequently being assigned a specific value. Simultaneously, within the nested table, an element is removed. Additionally, in the associative array, a specific element undergoes modification, ensuring the dynamic adaptability of the collection to evolving data requirements.
Common Operations
Explore common operations like appending, deleting, and checking for element existence.
-- Appending elements to an array
my_array := my_array MULTISET UNION Array_Type('Value5', 'Value6');
-- Deleting all elements from a nested table
my_table := Nested_Table_Type();
-- Checking if an element exists in an associative array
IF my_assoc_array.EXISTS(1) THEN
-- Do something
END IF;
Explanation:
In the realm of SQL collections, various operations enhance their functionality. To enrich an array, additional elements can be seamlessly appended, ensuring dynamic and evolving data storage. For a nested table, a clean slate is achieved by effortlessly deleting all existing elements, offering a quick and efficient reset. The power of the EXISTS function comes into play with associative arrays, providing a means to verify the existence of a specific index, adding a layer of control and precision to the data management process.
Incorporating Collections in SQL Queries
Now, let’s leverage collections in SQL queries for more flexible and dynamic operations.
-- Using an array in a SELECT statement
SELECT * FROM employees WHERE employee_id IN (SELECT * FROM TABLE(my_array));
-- Using a nested table in a JOIN operation
SELECT e.employee_id, e.employee_name, d.department_name
FROM employees e
JOIN TABLE(my_table) t ON e.department_id = t.COLUMN_VALUE;
-- Using an associative array in a WHERE clause
FOR i IN 1..my_assoc_array.LIMIT
LOOP
Explanation:
In SQL queries, the array serves as a filtering mechanism within the SELECT statement, allowing for precise record retrieval. In JOIN operations, a nested table is harnessed to establish correlations between datasets, facilitating a more comprehensive analysis. Additionally, the versatility of associative arrays shines as they are seamlessly integrated into loops, enabling efficient iteration through their elements. This concise yet powerful utilization of collections enhances the flexibility and dynamism of SQL queries, showcasing their utility in various scenarios.
Hacks:
- Try declaring your own collection and initializing it with values of your choice.
- Perform basic operations like adding, removing, and modifying elements.
- Create a SQL query using your collection to filter or join data.