Friday, May 8, 2026

How to Loop Through a Map in Java

When working with collections, one common requirement is iterating over a Map implementation such as HashMap or Treemap in Java. Understanding how to loop through a Map in Java is essential for tasks like processing key‑value pairs, transforming data, or building efficient algorithms.

Methods for Iterating a Map

The Map interface provides three key methods to loop or iterate any Map implementation.

  • Set<Map.Entry<K, V>> entrySet()- This method returns a set of key‑value pairs. The entries in the set are actually object of type Map.Entry.
  • Set<K> keySet()- This method returns a set that contains all keys in the map.
  • Collection<V> values()- This method returns a Collection view of all values in the map.

These methods allow you to choose whether you want to iterate over entries, keys, or values. Let's see how these methods can be used to loop through a HashMap in Java.

  1. You can use either an iterator or a For-Each loop to iterate through a Map. See example.
  2. Java 8 onwards you can also use forEach statement. See example.

HashMap iteration using for-each and iterator Java example

In the example code HashMap is used to demonstrate traversal of a Map.

public class HashMapLooping {

 /**
  * @param args
  */
  public static void main(String[] args) {
     // Setting up a HashMap
  Map<String, String> cityMap = new HashMap<String, String>();
  cityMap.put("1","New York City" );
  cityMap.put("2", "New Delhi");
  cityMap.put("3", "Newark");
  cityMap.put("4", "Newport");
  
  System.out.println("Looping with keySet");
  // Loop through HashMap using Key Set
  Set<String> citySet =  cityMap.keySet();
  for(String key : citySet){
   System.out.println("Key is " + key + " Value is " + cityMap.get(key));
  }
  
  System.out.println("Looping HashMap using entrySet");
  // Second way with entrySet
  for(Map.Entry<String, String> entry:  cityMap.entrySet()){
   System.out.println("Key is " + entry.getKey() + " Value is " + entry.getValue());
  }
  
  System.out.println("Looping with entrySet using Iterator");
  //Third way with iterator
  Iterator<Entry<String, String>> itr = cityMap.entrySet().iterator();
  while(itr.hasNext()){
   Map.Entry<String, String> entry = itr.next();
   System.out.println("Key is " + entry.getKey() + " Value is " + entry.getValue());
  }

  System.out.println("Looping HashMap using values method");
  for(String value : cityMap.values()){
    System.out.println("Value is " + value);
  }
 }
}

It can be seen that the first iteration of the HashMap is done using the keySet() method which gives a set of keys in the map. Using those keys respective values are retrieved. Since another call is required to get the mapped values this way of looping a HashMap is less efficient in case you need both keys and values.

Second iteration of the map is done using the entrySet() method which returns a set containing the Map.Entry objects. From Map.Entry object key and value can be retrieved using getKey() and getValue() methods.

Third way of iteration is again using the entrySet() method, only difference is instead of using the For-Each loop, iterator is used here.

Fourth way of iterating a HashMap uses the values() method and gives all the values stored in the HashMap.

Output of the program

Looping with keySet
Key is 1 Value is New York City
Key is 2 Value is New Delhi
Key is 3 Value is Newark
Key is 4 Value is Newport
Looping HashMap using entrySet
Key is 1 Value is New York City
Key is 2 Value is New Delhi
Key is 3 Value is Newark
Key is 4 Value is Newport
Looping with entrySet using Iterator
Key is 1 Value is New York City
Key is 2 Value is New Delhi
Key is 3 Value is Newark
Key is 4 Value is Newport
Looping using values method
Value is New York City
Value is New Delhi
Value is Newark
Value is Newport
Value is Kolkata

Iterating HashMap using forEach in Java

From Java 8 onward, the forEach method was introduced as part of the Map interface, allowing developers to iterate over a HashMap in a clean, functional style. Combined with lambda expressions and method references, this approach reduces iteration to a single, expressive statement. With forEach statement you can even iterate a HashMap directly without getting a collection view of the Map.

public class HashMapLooping {

 /**
  * @param args
  */
 public static void main(String[] args) {
  // Setting up a HashMap
  Map<String, String> cityMap = new HashMap<String, String>();
  cityMap.put("1","New York City" );
  cityMap.put("2", "New Delhi");
  cityMap.put("3", "Newark");
  cityMap.put("4", "Newport");
  
  System.out.println("Looping with Lambda expression forEach stmt"); 
  Set<Map.Entry<String, String>> valueSet = cityMap.entrySet();
  valueSet.forEach((a)->System.out.println("Key is " + a.getKey() + 
           " Value is " + a.getValue()));
  
  System.out.println("Looping with method reference forEach");
  cityMap.entrySet().forEach(System.out::println);
  // Looping HashMap directly with forEach
  System.out.println("Looping HashMap with forEach statement");
  cityMap.forEach((K,V)->System.out.println("Key is " + K + " Value is " + V));
 }
}

Output

Looping with Lambda expression forEach stmt
Key is 1 Value is New York City
Key is 2 Value is New Delhi
Key is 3 Value is Newark
Key is 4 Value is Newport
Looping with method reference forEach
1=New York City
2=New Delhi
3=Newark
4=Newport
Looping HashMap with forEach statement
Key is 1 Value is New York City
Key is 2 Value is New Delhi
Key is 3 Value is Newark
Key is 4 Value is Newport
Key is 5 Value is Kolkata

đź’ĄPoints to note

  • A map can be iterated using entrySet() which returns a set containing objects of type Map.Entry.
  • Another way to iterate a map in Java is using keySet() method which returns a set containing keys of the map or values() method that returns a Collection view of the Map.
  • Map can be iterated either using iterator or for-each loop.
  • With Java 8 forEach statement provides a new way to loop a HashMap in Java.

That's all for this topic How to Loop Through a Map in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. How HashMap Works Internally in Java
  2. How to Loop or Iterate an Arraylist in Java
  3. LinkedHashMap in Java With Examples
  4. How to Sort elements in different order in TreeSet using Comparator
  5. Java Collections Interview Questions And Answers

You may also like-

  1. Fail-Fast Vs Fail-Safe Iterator in Java
  2. Functional interfaces in Java 8
  3. Race condition in Java multi-threading
  4. Synchronization in Java - Synchronized Method And Block
  5. Difference Between Checked And Unchecked Exceptions in Java
  6. Callable and Future in Java With Examples
  7. Java Stream API Tutorial
  8. Encapsulation in Java

JavaScript Array and Object Destructuring

JavaScript destructuring assignment is a concise way to unpack values from arrays or properties from objects directly into variables. Introduced in ES6, destructuring makes code cleaner, reduces redundancy, and improves readability compared to traditional assignment methods.

Array Destructuring in JavaScript

const [India, USA, Japan] = ['Rupee', 'Dollar', 'Yen'];
console.log("Indian Currency - " + India); // Indian Currency - Rupee
console.log("American Currency - " + USA);// American Currency - Dollar
console.log("Japanese Currency - " + Japan);// Japanese Currency - Yen

Which is equivalent to this older approach of assigning array elements to variables.

const currencies = ['Rupee', 'Dollar', 'Yen'];
const India = currencies[0];
const USA = currencies[1];
const Japan = currencies[2];
console.log("Indian Currency - " + India);
console.log("American Currency - " + USA);
console.log("Japanese Currency - " + Japan);

As you can see, destructuring makes the code shorter and more expressive.

Extracting specific elements of an array

You don’t always need every element. By leaving a blank space with a comma for skipped values, you can selectively extract. For example, assigning only Rupee and Yen.

const currencies = ['Rupee', 'Dollar', 'Yen'];
const [India, , Japan] = currencies;

Using Destructuring when function returns an array

You can use destructuring to assign an array returned from a function to variables. Infact that's one of the most common uses of destructuring which you'll see in React.

For example useState() hook in React returns an array with exactly two values; current state and set function. Assignment for these two returned values can be done like this-

const [prevCount, setPrevCount] = useState(count);

Object destructuring in JavaScript

Object destructuring lets you pull properties directly into variables.

const obj = {first: 'Ramesh', last: 'Sharma', age: 35 };
const {first, last, age} = obj;
console.log(first); // Ramesh
console.log(last); // Sharma
console.log(age); // 35

Which is equivalent to this older approach of assigning object properties to variables.

const obj = {first: 'Ramesh', last: 'Sharma', age: 35 };
   
var f = obj.first;
var l = obj.last;
var ag = obj.age;

Assigning different names

When destructuring an object you have to use the same name for the variable as the mapped object key. If you want to use different names then you have to specify those names explicitly.

//specify new name after colon
const { first: firstName, last: lastName, age} = obj;
console.log(firstName);
console.log(lastName);
console.log(age);

Extracting specific properties of an object

You can extract specific properties of an object by giving just the needed keys. For example, if you need only first and age.

const obj = {first: 'Ramesh', last: 'Sharma', age: 35 };
const {first, age} = obj;

Passing destructured object as function arguments

If you have a function that takes object as an argument then you can pass the destructured object as function arguments to make your function more readable.

// function taking params as destructuring
function displayPerson({first, last, age}){
  console.log("first ", first, "last ", last, "age ", age)
}

That's where you will see its usage in React, to destructure props object.

In calling component-

<Person first="Ramesh" last="Sharma" age=35 />

Person Component with props

const Person = (props) => {
  return(
    <h2>{props.first} {props.last} {props.age}</h2>
  );
}

Same thing with props destructuring

const Person = ({first, last, age}) => {
  return(
    <h2>{first} {last} {age}</h2>
  );
}

Why Use JavaScript Array and Object Destructuring

  1. Cleaner syntax- Requires fewer lines of code.
  2. Improved readability- It is instantly clear which value is being extracted.
  3. Flexibility- Provides flexibility to skip values, rename properties, set default values.
  4. Modern best practice- Widely used in frameworks like React, Node.js, and Next.js.

That's all for this topic JavaScript Array and Object Destructuring. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. JavaScript Spread Operator
  2. JavaScript let and const With Examples
  3. JavaScript Arrow Function With Examples
  4. React HelloWorld App - First React App
  5. React Declarative Approach

You may also like-

  1. What Are JVM, JRE And JDK in Java
  2. Java Record Class With Examples
  3. React Virtual DOM
  4. Controlled and Uncontrolled Components in React
  5. Angular Cross Component Communication Using Subject Observable
  6. Angular Property Binding With Examples
  7. First LangChain Program: Ask Me Anything
  8. Dependency Injection Using factory-method in Spring

Java DelayQueue With Examples

DelayQueue in Java is an implementation of BlockingQueue interface introduced in Java 5 as part of the java.util.concurrent package. Alongside other concurrent utilities like CyclicBarrier, Exchanger, ConcurentSkipListMap, CopyOnWriteArraySet, it provides developers with advanced concurrency tools for building scalable applications.

DelayQueue is Unbounded

The DelayQueue in Java is an unbounded implementation of BlockingQueue, that's where it is different from the other implementations of BlockingQueue like ArrayBlockingQueue (Always bounded) and LinkedBlockingQueue (both bounded and unbounded options). Though it is similar to PriorityBlockingQueue in this behaviour as PriorityBlockingQueue is also unbounded.

DelayQueue stores Delayed elements

DelayQueue in Java is a special implementation of BlockingQueue as it can only store elements of type Delayed and an element can only be retrieved from DelayQueue when its delay has expired.

Delayed interface which defines the type for the elements in the DelayQueue has one method of its own:

  1. getDelay(TimeUnit unit)- Returns the remaining delay associated with this object, in the given time unit.

Delayed interface also extends Comparable interface so compareTo(T o) method should also be implemented. This method implementation will decide whether you want to retrieve elements in ascending order of delay or descending.

According to JavaDocs "An implementation of this interface must define a compareTo method that provides an ordering consistent with its getDelay method."

So, just to sum it up; DelayQueue stores elements of type Delayed. When you implement Delayed interface two methods have to be implemented getDelay(TimeUnit unit) and compareTo(T o).

Ordering in Java DelayQueue

  1. DelayQueue orders its elements (of type Delayed) based on the remaining delay associated with the element as returned by the getDelay() method.
  2. The head of the queue is the Delayed element whose delay expired earliest.
  3. The tail of the queue is the Delayed element with the longest remaining delay.

This makes DelayQueue ideal for task scheduling, caching with expiration, and delayed message processing.

Producer Consumer Java example using DelayQueue

Let's create a producer consumer using the DelayQueue. There is also a class DelayClass which implements Delayed interface and implements the required methods- getDelay() and compareTo(). DelayQueue will store objects of DelayClass.

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

public class DelayQDemo {
  public static void main(String[] args) {
    // delay of 2 seconds
    final long delay = 2000;
    BlockingQueue<DelayClass> delayQ = new DelayQueue<DelayClass>();
      
    // Producer thread
    new Thread(){
      @Override
      public void run() {
        for(int i = 0; i < 5; i++){
          try {
            // putting elements in delay queue
            delayQ.put(new DelayClass("item"+i, delay));
            Thread.sleep(50);
          } catch (InterruptedException e) {
            System.out.println("Error while putting values in the Queue "
             + e.getMessage());
          }
        }
      }
    }.start();
      
    // Consumer thread
    new Thread(){
      @Override
      public void run() {
        for(int i = 0; i < 5; i++){
          try {
            // retrieving elements from delay queue
            System.out.println(" Consumer got - " + delayQ.take());
            Thread.sleep(500);
          } catch (InterruptedException e) {
            System.out.println("Error while retrieving value from the Queue "
             + e.getMessage());
          }
        }
      }
    }.start();
  }
}

// Delayed interface implementing class
class DelayClass implements Delayed{
  private String item;
  private long expireTime;
  DelayClass(String item, long delay){
    this.item = item;
    // Expiretime is currenttime+delay, so if delay of 2 sec is required
    // expiration from queue will hppn after
    // currenttime + 2 sec
    this.expireTime = System.currentTimeMillis() + delay;
  }
    
  @Override
  public long getDelay(TimeUnit unit) {
    long diff = expireTime - System.currentTimeMillis();
    return unit.convert(diff, TimeUnit.MILLISECONDS);
  }
    
  @Override
  public int compareTo(Delayed o) {
    if(this.getDelay(TimeUnit.MILLISECONDS) < o.getDelay(TimeUnit.MILLISECONDS)){
      return -1;
    }
    if(this.getDelay(TimeUnit.MILLISECONDS) > o.getDelay(TimeUnit.MILLISECONDS)){
      return 1;
    }
    return 0;        
  }
    
  public String toString(){
    return "item = " + item + " expireTime = " + expireTime;
  } 
}

Output

Consumer got - item = item0 expireTime = 1458998017469
Consumer got - item = item1 expireTime = 1458998017531
Consumer got - item = item2 expireTime = 1458998017594
Consumer got - item = item3 expireTime = 1458998017656
Consumer got - item = item4 expireTime = 1458998017719

Here it can be seen elements are retrieved from the queue only after the delay expires.

đź’ĄPoints to remember

  1. DelayQueue in Java stores element of type Delayed.
  2. Element is retrieved from DelayQueue only when its delay has expired.
  3. The head of the queue is that Delayed element whose delay expired furthest in the past.
  4. If no delay has expired there is no head and poll will return null.
  5. Expiration occurs when an element's getDelay(TimeUnit tu) method returns a value less than or equal to zero.

Reference: https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/concurrent/DelayQueue.html

That's all for this topic Java DelayQueue With Examples. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Java SynchronousQueue With Examples
  2. Java BlockingDeque With Examples
  3. Java LinkedTransferQueue With Examples
  4. Java ReentrantReadWriteLock With Examples
  5. Java Semaphore With Examples

You may also like-

  1. ConcurrentHashMap in Java With Examples
  2. Deadlock in Java Multi-Threading
  3. Synchronization in Java - Synchronized Method And Block
  4. Java Collections Interview Questions And Answers
  5. Java Lambda Expression And Variable Scope
  6. Autowiring in Spring Using @Autowired and @Inject Annotations
  7. Try-With-Resources in Java With Examples
  8. Java Program to Find The Longest Palindrome in a Given String

Thursday, May 7, 2026

pass Statement in Python

The pass statement in Python is a simple yet powerful tool that acts as a placeholder in your code. It performs no action when executed, but ensures that your program remains syntactically correct. This makes it especially useful when you want to define the structure of your code without implementing the logic right away.

Python pass statement

  • The pass statement is a null operation, when it is executed, nothing happens.
  • It is often used in places where a statement is required syntactically, but you don’t want to perform any operation yet.
  • Common use cases include empty functions, classes, loops, or conditional blocks that you plan to implement later.

Using pass in a Loop

If you have an array of numbers and you want to display only those numbers which are less than 100.

numbers = [89, 102, 45, 234, 67, 10, 333, 32]
for num in numbers:
  if num > 100:
    #do nothing
    pass
  else:
    print('number is', num)

Output

number is 89
number is 45
number is 67
number is 10
number is 32

In the above example, if-else statement checks whether each number in the list is greater than 100 or not. In case it is then you do nothing and that is explicitly indicated using the pass statement.

In most cases, you can write Python code without explicitly using the pass statement. However, including it often improves readability and makes your intent clear to other developers. The pass statement ensures that your code remains syntactically valid and prevents errors such as IndentationError when leaving a block empty.

Using pass in Classes

Suppose there is a Person class where you have a method to display Person data and retrieve person data. You are planning to implement retrieveData() method later, that will fetch Person details from DB, so you keep the method in place as a TODO reminder.

class Person:
    def __init__(self, name, age):
        print('init called')
        self.name = name
        self.age = age

    def display(self):
        print('in display')
        print("Name-", self.name)
        print("Age-", self.age)

    def retrieveData(self):
        #TODO has to be implemented to fetch details from DB

person = Person('John', 40)
person.display()

But running this class gives an error “IndentationError: expected an indented block

In such case adding pass statement with unimplemented method ensures that IndentationError is not thrown.

    def retrieveData(self):
        #TODO has to be implemented to fetch details from DB
        pass

So, you can see that Python pass statement can be used where you need a place holder be it with in a for loop, while loop or if-else statement, after def or even after class and in exception handling too.

pass statement with class Inheritance

If you are creating a user‑defined exception class by extending Python’s built‑in Exception class without adding new behavior, you can simply use pass statement.

class MyException(Exception):
    pass

pass Statement in Exception Handling

If you want to catch a specific exception but don't want to take any action after catching it, you can use pass statement to express that intent.

numbers = [89, 102, 0, 234, 67, 10, 333, 32]
for num in numbers:
    try:
        result = 1000/num
        print('Result is',result)
    except ZeroDivisionError:
        print('Division by Zero')
        result = 0
    except AttributeError:
        pass

That's all for this topic pass Statement in Python. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Python Tutorial Page


Related Topics

  1. Python assert Statement
  2. Python Exception Handling Tutorial
  3. Global Keyword in Python With Examples
  4. Abstraction in Python
  5. Difference Between Function and Method in Python

You may also like-

  1. Comparing Two Strings in Python
  2. Namespace And Variable Scope in Python
  3. Passing Object of The Class as Parameter in Python
  4. Python Program to Find Factorial of a Number
  5. What Are JVM, JRE And JDK in Java
  6. Java Program to Detect And Remove Loop in a Linked List
  7. How to Read Input From Console in Java
  8. Word Count MapReduce Program in Hadoop

Java split() Method - Splitting a String

The split() method in Java String class is used to split the string into one or more substring based on the given regular expression.

Java split() method has 2 variants-

  1. split(String regex)
    • Splits this string around matches of the given regular expression.
    • Returns an array of substrings of this string that matches the given expression.
  2. split(String regex, int limit)
    • The limit parameter controls the number of times the regex pattern is applied
    • If the limit is greater than zero then the pattern will be applied at most limit - 1 times, and the resulting array will have at most limit elements.
    • The last element of the array contains the remaining part of the string.

String's split() method examples

  1. If you have a string where one (or more) spaces are used and you want to split this String around those spaces. Here passed regex "\\s+" means one or more spaces.
    public class StringSearch {
     public static void main(String[] args) {
      String str1 = "split example    program";
      String[] strArray = str1.split("\\s+");
      System.out.println("Words in array- " + strArray.length);
      for(String w : strArray){
       System.out.println("words - " + w);
      }
     }
    }
    

    Output

    Words in array- 3
    words - split
    words - example
    words – program
    
  2. If you have a date in dd/mm/yyyy format and you want to split this date String into day, month and year.
    public class StringSearch {
     public static void main(String[] args) {
      String date = "20/01/2016";
      String[] dateArr = date.split("/");
      System.out.println("" + dateArr.length);
      System.out.println("day " + dateArr[0] + " Month " + dateArr[1] +
        " Year " + dateArr[2]);
     }
    }
    

    Output

    3
    day 20 Month 01 Year 2016
    

Using split() method with limit argument

Suppose you just want the day part of the date then you can use the split() method which also passes limit as argument-

public class StringSearch {

 public static void main(String[] args) {
  String date = "20/01/2016";
  String[] dateArr = date.split("/", 2);
  System.out.println("" + dateArr.length);
  System.out.println("day " + dateArr[0]);
 }
}

Output

2
day 20

That's all for this topic Java split() Method - Splitting a String. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Basics Tutorial Page


Related topics

  1. String Comparison in Java equals(), compareTo(), startsWith() Methods
  2. Java String substring() Method - Getting Substring
  3. String Vs StringBuffer Vs StringBuilder in Java
  4. Find All Permutations of a Given String Java Program
  5. Java String Interview Questions And Answers

You may also like-

  1. Count Number of Words in a String Java Program
  2. Java Program to Find The Longest Palindrome in a Given String
  3. Multi-Catch Statement in Java Exception Handling
  4. final Vs finally Vs finalize in Java
  5. Java Pass by Value or Pass by Reference
  6. finalize() Method in Java
  7. Difference Between HashMap And Hashtable in Java
  8. Callable and Future in Java With Examples

Multiple Catch Blocks in Java Exception Handling

Multiple catch blocks in Java allow developers to handle different types of exceptions that may occur within a single try block. When code inside the try block throws an exception, the JVM inspects each catch clause in order. The first block whose exception type matches the thrown exception is executed, and once a matching catch block runs, the remaining ones are skipped. Execution then continues after the entire try-catch block.

This mechanism of multiple catch blocks is especially useful when a program can fail in multiple ways, for example, due to invalid array access or arithmetic errors. By defining multiple catch blocks, you can provide tailored exception handling logic for each exception type, which improves code clarity and robustness.

👉 Since Java 7, developers also have the option to catch multiple exceptions in one catch block, which eliminates the duplicated code. Refer Multi catch statement in Java to read more about it.

Multiple catch blocks Java example

In this program there is an array with only one element which is zero. From main method when calculateValue method is called a parameter is passed which is used as an index of the array.

First time 0 is passed which will mean divide by a[0]. Since the value at that index is 0 thus it will result in divide by 0 and ArithmeticException will be thrown.

Next time 2 is passed but array has only one element so trying to access a[2] will result in ArrayIndexOutOfBoundsException.

In the code there are multiple catch blocks and both of these exceptions will be caught by separate catch blocks.

public class MultipleCatchDemo {
  private void calculateValue(int i){
    int a[] = {0};
    try{
      int b = 7/a[i];
    }catch(ArithmeticException aExp){
      aExp.printStackTrace();
    }catch(ArrayIndexOutOfBoundsException aiExp){
      aiExp.printStackTrace();
    }
  }

  public static void main(String[] args) {
    MultipleCatchDemo mcDemo = new MultipleCatchDemo();
    mcDemo.calculateValue(0);
    mcDemo.calculateValue(2);
  }
}

Output

java.lang.ArithmeticException: / by zero
 at org.netjs.examples.impl.MultipleCatchDemo.calculateValue(MultipleCatchDemo.java:11)
 at org.netjs.examples.impl.MultipleCatchDemo.main(MultipleCatchDemo.java:21)
java.lang.ArrayIndexOutOfBoundsException: 2
 at org.netjs.examples.impl.MultipleCatchDemo.calculateValue(MultipleCatchDemo.java:11)
 at org.netjs.examples.impl.MultipleCatchDemo.main(MultipleCatchDemo.java:22)

⛔Restrictions with Multiple catch blocks in Java

When using multiple catch blocks in Java, it is crucial to maintain the correct order of exception handling. Which means a catch block that catches a subclass of an exception must come before the catch clause that handles its exception super class.

If the superclass catch block is placed first, it will intercept all exceptions of that type, including its subclasses, making the subclass catch block unreachable. Since Java treats unreachable code as a compilation error, this ordering mistake will prevent your program from compiling.

For example, with in the Java exception handling hierarchy Exception class is super class and ArithmeticException is the child class so catch block for Exception class will catch an ArithmeticException too. Thus placing the catch block for Exception class before the catch block for ArithmeticException would mean that the catch block for ArithmeticException is never reached.

try {
    int result = 10 / 0; // ArithmeticException
} catch (Exception e) {
    System.out.println("Generic exception caught.");
} catch (ArithmeticException e) { // Unreachable Catch Block- Causes compile time error
    System.out.println("Arithmetic exception caught.");
}

In the same example as used above, if an additional catch block for Exception is placed at the beginning of the sequence, that will result in compiler error.

multiple catch blocks

That's all for this topic Multiple Catch Blocks in Java Exception Handling. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Best Practices For Exception Handling in Java
  2. Creating Custom Exception Class in Java
  3. throws Keyword in Java Exception Handling
  4. Try-With-Resources in Java With Examples
  5. Java Exception Handling Interview Questions And Answers

You may also like-

  1. Difference Between Abstract Class And Interface in Java
  2. Inheritance in Java
  3. How to Loop Through a Map in Java
  4. Fail-Fast Vs Fail-Safe Iterator in Java
  5. Difference Between Thread And Process in Java
  6. Thread Priority in Java Multi-Threading
  7. Why wait(), notify() And notifyAll() Methods Are in Object Class And Not in Thread Class
  8. Varargs (Variable-length Arguments) in Java

Wednesday, May 6, 2026

Python continue Statement With Examples

The Python continue Statement is a loop control keyword used inside for and while loops to skip the rest of the current iteration and jump directly to the next cycle of the loop. When continue is encountered, Python immediately transfers control back to the beginning of the loop, ignoring any statements that follow within that iteration.

The common use case for continue statement is to pair it with if condition with in the loop to selectively skip certain iterations. When the condition is true the continue statement is executed resulting in next iteration of the loop.

continue statement Python examples

1. Using continue statement with for loop in Python. In the example a for loop in range 1..10 is executed and it prints only odd numbers.

for i in range(1, 10):
    # Completely divisble by 2 means even number
    # in that case continue with next iteration
    if i%2 == 0:
        continue
    print(i)

print('after loop')

Output

1
3
5
7
9
after loop

2. Using continue statement with while loop in Python. In the example while loop is iterated to print numbers 1..10 except numbers 5 and 6. In that case you can have an if condition to continue to next iteration when i is greater than 4 and less than 7.

i = 0
while i < 10:
    i += 1
    if i > 4 and i < 7:
        continue
    print(i)

Output

1
2
3
4
7
8
9
10

3. Here is another example of using continue statement with infinite while loop. In the example there is an infinite while loop that is used to prompt user for an input. Condition here is that entered number should be greater than 10, if entered number is not greater than 10 then continue the loop else break out of the loop.

while True:
    num = int(input("Enter a number greater than 10: "))
    # condition to continue loop
    if num < 10:
        print("Please enter a number greater than 10...")
        continue
    else:
        break

print("Entered number is", num)

Output

Enter a number greater than 10: 5
Please enter a number greater than 10...
Enter a number greater than 10: 16
Entered number is 16

That's all for this topic Python continue Statement With Examples. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Python Tutorial Page


Related Topics

  1. Python break Statement With Examples
  2. Python return Statement With Examples
  3. pass Statement in Python
  4. Encapsulation in Python
  5. Namespace And Variable Scope in Python

You may also like-

  1. Constructor in Python - __init__() function
  2. Strings in Python With Method Examples
  3. List in Python With Examples
  4. What Are JVM, JRE And JDK in Java
  5. Equality And Relational Operators in Java
  6. Lambda Expressions in Java 8
  7. What is Hadoop Distributed File System (HDFS)
  8. Circular Dependency in Spring Framework

Method Overloading in Java

Method Overloading in Java occurs when two or more methods in the same class (or in a parent‑child class hierarchy) share the same method name but differ in their parameter list, either by the number of parameters or their types.

For example:

void test(int a, int b) { ... }
void test(float a, int b) { ... }
void test(int a, int b, int c) { ... }

Here, the method name test is reused, but the parameter signatures differ, making them valid overloaded methods.


Method Overloading and Polymorphism

Method overloading is a classic example of compile‑time polymorphism (also called static polymorphism) in Java. The compiler determines which overloaded method to invoke based on the method signature at compile time, ensuring type safety and performance.

How Java Decides Which Overloaded Method to Call

When you invoke an overloaded method, the Java compiler determines which version to execute at compile time itself. This resolution process is based on the method signature, specifically the number and types of parameters provided in the call.

  • Types of the parameters- For example test(int a, int b) and test(float a, int b). In these overloaded methods name is same but the types of the method parameters differ.
  • Number of the parameters- For example test(int a, int b) and test(int a, int b, int c). In these overloaded methods name is same but the number of parameters is different.

Please note that return type of the methods may be different but that alone is not sufficient to determine the method that has to be called.

Examples of method overloading in Java

1. Method overloading example with methods having different types of parameters. In the Java example there are two overloaded methods, one having two int parameters where as the other method has one int and one double parameter.

public class OverloadingExample {
 // overloaded Method
 void overloadedMethod(int i, int j){
  System.out.println("In overloadedMethod with both int parameters- " + i);
 }
 
 // overloaded Method
 void overloadedMethod(int i, double j){
  System.out.println("In overloadedMethod with int and double parameters " + i + " " + j);
 }
 
 
 public static void main(String args[]){ 
  OverloadingExample obj = new OverloadingExample();
  obj.overloadedMethod(5, 7);
  obj.overloadedMethod(5, 103.78);
 }
}

Output

In overloadedMethod with both int parameters- 5
In overloadedMethod with int and double parameters 5 103.78

2. Method overloading example with methods having different number of parameters. In the Java example there are two overloaded methods, one having a single int parameter where as the other method has one int and one String parameter.

public class OverloadingExample {
 // overloaded Method
 void overloadedMethod(int i){
  System.out.println("In overloadedMethod with int parameter- " + i);
 }
 
 // overloaded Method
 void overloadedMethod(int i, String s){
  System.out.println("In overloadedMethod with int and string parameters- " + i + " " + s);
 }
 
 
 public static void main(String args[]){ 
  OverloadingExample obj = new OverloadingExample();
  obj.overloadedMethod(5);
  obj.overloadedMethod(5, "Test");
 }
}

Output

In overloadedMethod with int parameter- 5
In overloadedMethod with int and string parameters- 5 Test

Method overloading in Java and automatic type conversion

In Java, automatic type promotion may happen and it does have a role in how overloaded methods are called, let's see it with an example to have clarity.

public class OverloadingExample {
 // overloaded Method with 1 int param
 void overloadedMethod(int i){
  System.out.println("In overloadedMethod with one int parameter " + i);
 }
 
 // overloaded Method with 2 double params
 void overloadedMethod(double i, double j){
  System.out.println("In overloadedMethod with 2 double parameters " + i + " " + j);
 }
 
 
 public static void main(String args[]){ 
  OverloadingExample obj = new OverloadingExample();
  obj.overloadedMethod(5);
  obj.overloadedMethod(5.7, 103.78);
  obj.overloadedMethod(5, 10);
 }
}

Here notice the third call to the method
obj.overloadedMethod(5, 10);

It has 2 int params, but there is no overloaded method with 2 int params, in this case automatic type conversion happens and java promotes these 2 int parameters to double and calls overloadedMethod(double i, double j) instead.

Method Overloading in Java and Inheritance

In Java, when dealing with a parent‑child relationship (inheritance), the distinction between method overloading and method overriding becomes important.

  • Method Overriding occurs when the child class defines a method with the same name, same parameter list (number and types), and same return type (or a covariant type) as the parent class. In this case, the child's method overrides the parent's implementation, and the decision of which method to call is made at runtime (dynamic polymorphism).
  • Method Overloading, on the other hand, happens when the child class defines a method with the same name but a different parameter list (either in number or types) compared to the parent class. Here, the compiler treats them as distinct methods, and the resolution is done at compile time (static polymorphism).
class Parent {
 private int i;
 // Constructor
 Parent(int i){
  this.i = i;
 }
 // Method with no param
 public void dispayData(){
  System.out.println("Value of i " + i);
 } 
}

class Child extends Parent{
 private int j;
 // Constructor
 Child(int i, int j){
  // Calling parent class constructor
  super(i);
  this.j = j;
 }
 // Overloaded Method with String param
 public void dispayData(String showMsg){
  System.out.println(showMsg + "Value of j " + j);
 } 
}

class OverloadDemo{
 public static void main(String args[]){ 
  Child childObj = new Child(5, 10);
  // This call will invoke the child class method
  childObj.dispayData("in Child class displayData ");
  // This call will invoke the parent class method
  childObj.dispayData();
 }
}

Output of the program would be

in Child class displayData Value of j 10
Value of i 5

Benefits of Method Overloading

One of the biggest advantages of Method Overloading in Java is improved readability and code maintainability. Without overloading, developers would need to create multiple methods with different names for similar functionality, which quickly becomes confusing and clutters the code.

  1. Cleaner Code: Instead of writing separate methods like addInt(int a, int b) or addLong(long a, long b), you can simply use one method name add() with different parameter signatures.
  2. Improved Readability: Overloading allows logically related operations to share the same name, making the code easier to understand at a glance.
  3. Polymorphism Support: Method overloading is a form of compile‑time polymorphism, enabling the compiler to choose the correct method based on the arguments passed.

That's all for this topic Method Overloading in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Basics Tutorial Page


Related Topics

  1. Method Overriding in Java
  2. Polymorphism in Java
  3. Inheritance in Java
  4. Difference Between Encapsulation And Abstraction in Java
  5. Java OOP Interview Questions And Answers

You may also like-

  1. Object Creation Using new Operator in Java
  2. final Keyword in Java With Examples
  3. Java Abstract Class and Abstract Method
  4. Inter-thread Communication Using wait(), notify() And notifyAll() in Java
  5. How HashMap Works Internally in Java
  6. final Vs finally Vs finalize in Java
  7. Method Overloading in Python
  8. Dependency Injection in Spring Framework

StringBuilder Class in Java With Examples

The StringBuilder class in Java, introduced in Java 5, is a mutable (modifiable) sequence of characters just like StringBuffer class. Unlike the immutable String class in Java, where every modification creates a new object, StringBuilder allows in‑place changes to its content and length through various method calls. This makes it ideal for scenarios involving frequent string modifications.

Internally, a StringBuilder class object works like a dynamic, variable‑length array of characters.

StringBuilder vs StringBuffer

Both StringBuilder and StringBuffer share a similar API, but the key difference lies in thread safety:

  • StringBuffer is synchronized and thread‑safe, making it suitable for multi‑threaded environments.
  • StringBuilder is not thread‑safe, but this trade‑off delivers significantly better performance in single‑threaded applications.

As per the official Java documentation– StringBuilder class is designed for use as a drop-in replacement for StringBuffer in places where the string buffer was being used by a single thread (as is generally the case). Where possible, it is recommended that this class be used in preference to StringBuffer as it will be faster under most implementations.


Constructors in Java StringBuilder class

  • StringBuilder()- Creates an empty builder with a default capacity of 16.
  • StringBuilder(CharSequence seq)- Constructs a string builder that contains the same characters as the specified CharSequence.
  • StringBuilder(int capacity)- Creates an empty builder with the specified initial capacity.
  • StringBuilder(String str)- Constructs a string builder initialized to the contents of the specified string.

Tuesday, May 5, 2026

CopyOnWriteArrayList in Java With Examples

This post talks about CopyOnWriteArrayList in Java which is part of the java.util.concurrent package. It is a specialized thread safe implementation of the List interface.


Synchronized List options in Java

Though we have an option to synchronize the collections like List or Set using Collections.synchronizedList() or Collections.synchronizedSet() methods of the Collections class but there is a drawback to this synchronization; very poor performance because-

  • The entire collection is locked during access using a single lock.
  • Only a single thread can access it at a given time leading to significant performance bottlenecks under heavy concurrency.

Java also has a legacy Vector class as a thread-safe alternative to List but that thread safety is achieved by synchronizing all the methods of the Vector class, which again results in poor performance.

CopyOnWriteArrayList in Java

Java 5 onwards, CopyOnWriteArrayList is introduced as a thread-safe variant of ArrayList. It is designed for concurrent access from multiple threads. CopyOnWriteArrayList provides a thread-safe alternative for ArrayList, same way ConcurrentHashMap provides a thread-safe alternative for HashMap and CopyOnWriteArraySet for HashSet.

Thread safety in CopyOnWriteArrayList

Thread safety in CopyOnWriteArrayList lies in its "copy-on-write" strategy:

  • Every mutative operation (add, set, remove) creates a new copy of the underlying array.
  • Readers always see a consistent snapshot of the list, unaffected by concurrent modifications.
  • This ensures lock-free reads and predictable iteration behavior.

You may argue that this way of creating a fresh copy whenever any mutative operation is performed must be very costly. Yes it is, that is why using CopyOnWriteArrayList provides better performance in use cases with frequent reads but infrequent writes.

That brings us to the second point "snapshot style" iterator in CopyOnWriteArrayList.

CopyOnWriteArrayList has a fail-safe iterator

The iterator returned by Java CopyOnWriteArrayList is fail-safe, it uses a reference to the state of the array at the point that the iterator was created. You know by now any mutation will result in a fresh copy of the underlying array. Thus the array that the iterator has a reference to never changes during the lifetime of the iterator, so interference is impossible and the iterator is guaranteed not to throw ConcurrentModificationException.

The iterator will not reflect additions, removals, or changes to the list since the iterator was created thus it is also known as "snapshot style" iterator.

Element-changing operations on iterators themselves (remove, set, and add) are not supported. These methods throw UnsupportedOperationException.

Since iterator is not affected by the mutations thus multiple threads can iterate the collection without interference from one another or from threads wanting to modify the collection.

Java CopyOnWriteArrayList constructors

  • CopyOnWriteArrayList()- This constructor Creates an empty list.
  • CopyOnWriteArrayList​(E[] toCopyIn)- Creates a list holding a copy of the given array.
  • CopyOnWriteArrayList​(Collection<? extends E> c)- Creates a list containing the elements of the specified collection, in the order they are returned by the collection's iterator.

CopyOnWriteArrayList Java Example

Let's see a simple Java example creating CopyOnWriteArrayList and adding elements to it.

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

public class CopyOnWriteALDemo {
  public static void main(String[] args) {
    List<String> numList = new CopyOnWriteArrayList<String>();
    numList.add("1");
    numList.add("2");
    numList.add("3");
    numList.add("4");
    // Displaying CopyOnWriteArrayList elements
    for(String num : numList){
      System.out.println("Number- " + num);
    }
  }
}

Output

Number- 1
Number- 2
Number- 3
Number- 4

Java CopyOnWriteArrayList iterator Example

Let's see "snapshot style" iterator concept of CopyOnWriteArrayList in Java with an example.

First let's use ArrayList with 2 threads accessing it concurrently. One of the thread tries to structurally modified the ArrayList while second thread is iterating it. This should result in a ConcurrentModificationException.

public class FailFastDemo {
  public static void main(String[] args) {
    List<String> numList = new ArrayList<String>();
    numList.add("1");
    numList.add("2");
    numList.add("3");
    numList.add("4");
        
    //This thread will iterate the list
    Thread thread1 = new Thread(){ 
      public void run(){ 
        try{ 
          Iterator<String> i = numList.iterator(); 
          while (i.hasNext()){ 
            System.out.println(i.next()); 
            // Using sleep to simulate concurrency
            Thread.sleep(1000); 
          }     
        }catch(ConcurrentModificationException e){ 
          System.out.println("thread1 : Concurrent modification detected 
            on this list"); 
          e.printStackTrace();
        }catch(InterruptedException e){
          
        } 
      } 
    }; 
    thread1.start(); 
        
    // This thread will try to add to the collection,
    // while the collection is iterated by another thread.
    Thread thread2 = new Thread(){ 
      public void run(){ 
        try{ 
          // Using sleep to simulate concurrency
          Thread.sleep(2000);
          // adding new value to the shared list
          numList.add("5"); 
          System.out.println("new value added to the list"); 
        }catch(ConcurrentModificationException e){ 
          System.out.println("thread2 : Concurrent modification detected 
                  on the List"); 
        } catch(InterruptedException e){}
      } 
    }; 
    thread2.start(); 
  }
}

Output

1
2
new value added to the list
thread1 : Concurrent modification detected on this list
java.util.ConcurrentModificationException
 at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
 at java.util.ArrayList$Itr.next(Unknown Source)
 at org.netjs.prog.FailFastDemo$1.run(FailFastDemo.java:24)

Here it can be seen that the ConcurrentModificationException is thrown because the list is changed by a thread while it has been iterated by another thread.

Now in the same code change the ArrayList to CopyOnWriteArrayList. Also added one sysout after adding new element to the list.

public class FailFastDemo {
  public static void main(String[] args) {
    List<String> numList = new CopyOnWriteArrayList<String>();
    numList.add("1");
    numList.add("2");
    numList.add("3");
    numList.add("4");
        
    //This thread will iterate the list
    Thread thread1 = new Thread(){ 
      public void run(){ 
        try{ 
          Iterator<String> i = numList.iterator(); 
          while (i.hasNext()){ 
            System.out.println(i.next()); 
            // Using sleep to simulate concurrency
            Thread.sleep(1000); 
          }     
        }catch(ConcurrentModificationException e){ 
          System.out.println("thread1 : Concurrent modification detected 
            on this list"); 
          e.printStackTrace();
        }catch(InterruptedException e){
                    
        } 
      } 
    }; 
    thread1.start(); 
        
    // This thread will try to add to the collection,
    // while the collection is iterated by another thread.
    Thread thread2 = new Thread(){ 
      public void run(){ 
        try{ 
          // Using sleep to simulate concurrency
          Thread.sleep(2000);
          // adding new value to the shared list
          numList.add("5"); 
          System.out.println("new value added to the list"); 
          System.out.println("List " + numList);
        }catch(ConcurrentModificationException e){ 
          System.out.println("thread2 : Concurrent modification detected 
           on the List"); 
        } catch(InterruptedException e){}
      } 
    }; 
    thread2.start();    
  }
}

Output

1
2
3
new value added to the list
List [1, 2, 3, 4, 5]
4

Here ConcurrentModificationException is not thrown as CopyOnWriteArrayList is used now. Also note that, though one of the thread adds a new element and at that time the list prints all the elements from 1-5. But the iterator has the reference to the old copy of the list and it prints from 1-4.

Points to note

  • CopyOnWriteArrayList in Java provides a thread-safe alternative to the normal ArrayList.
  • In CopyOnWriteArrayList thread safety is achieved in a different way from a thread safe collection like Vector. In CopyOnWriteArrayList fresh copy of the underlying array is created with every mutative operations (add, set, and so on).
  • Because of this approach CopyOnWriteArrayList gives better performance in case there are more threads iterating the list than mutating it. Several threads can iterate CopyOnWriteArrayList concurrently.
  • CopyOnWriteArrayList's iterator is fail-safe and guaranteed not to throw ConcurrentModificationException.
  • CopyOnWriteArrayList's iterator uses a reference to the state of the array at the point that the iterator was created.
  • The iterator will not reflect additions, removals, or changes to the list since the iterator was created thus it is also known as "snapshot style" iterator.
  • All elements are permitted, including null.

That's all for this topic CopyOnWriteArrayList in Java With Examples. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. ConcurrentHashMap in Java With Examples
  2. Java CyclicBarrier With Examples
  3. Difference Between ArrayList And CopyOnWriteArrayList in Java
  4. Fail-Fast Vs Fail-Safe Iterator in Java
  5. Java Concurrency Interview Questions And Answers

You may also like-

  1. How ArrayList Works Internally in Java
  2. Java Collections Interview Questions And Answers
  3. How to Iterate a HashMap of ArrayLists of String in Java
  4. Java Program to Convert a File to Byte Array
  5. static reference to the non-static method or field error
  6. Race Condition in Java Multi-Threading
  7. Java ThreadLocal Class With Examples
  8. Interface Default Methods in Java

Tool Calling in LangChain

In the previous article Tools in LangChain With Examples we saw how you can create tools in LangChain and how to invoke those tools using invoke() method of the tool as every tool is a Runnable in LangChain which means it automatically inherits the .invoke() method from the Runnable interface. That works great when you are the one calling the tool. But the real magic happens when you let the LLM itself decide which tool to use, that’s where tool calling in LangChain comes into picture.

LangChain’s tool calling

Tools aren’t just standalone functions which you will execute manually, they become extensions of the LLM’s reasoning. You bind tools with the model so it can choose the appropriate tool call to get the result.

Integrating tools with the LLM

In LangChain you can use bind_tools() method to integrate your custom tools with the LLM. With bind_tools() method you can pass the list of tools to bind to the model.

By passing a list of tools to bind_tools(), you expose their name, description, and input schema to the model. This allows the LLM to recognize when a user query matches a tool’s purpose and respond with a structured ToolMessage, essentially a request to execute that tool.

It’s important to understand that the LLM does not read or execute your code directly. When it recognizes that a user request matches a tool’s purpose, it sends back a ToolMessage like:

{"name": "multiply", "args": {"a": 7, "b": 8}}

This is a signal that the tool should be run, but the execution itself is your responsibility.

Developer’s Role:

After receiving the tool call, following are the activities that needs to be done manually:

  1. Parsing the ToolMessage from the LLM’s response.
  2. Executing the tool with the provided arguments.
  3. Returning the result back to the model so it can continue reasoning and produce a polished answer.

If you want the orchestration to happen automatically, you’ll need to use an agent. Agents handle the loop of:

  1. Detecting tool calls,
  2. Running the tools,
  3. Feeding results back into the LLM,
  4. Continuing the conversation seamlessly.

In this article we’ll stick to manual bind_tools() workflow where the developer explicitly handles tool execution after the LLM emits a tool call. This approach helps you understand what’s happening under the hood before moving on to full agent automation.

Let’s try to make bind_tools() workflow clear with an example, we’ll use a multiply tool that multiplies two numbers.

from langchain_core.prompts import ChatPromptTemplate
from langchain_core.tools import tool
from langchain_groq import ChatGroq
from dotenv import load_dotenv

load_dotenv()  # Load environment variables from .env file

# Multiplication tool
@tool
def multiply(a: int, b: int) -> int:
    """Multiply two integers and return the result."""
    return a * b

# Initialize model
llm = ChatGroq(model="llama-3.3-70b-versatile", temperature=0.5)

llm_with_tools = llm.bind_tools([multiply])

# Now the LLM can decide when to call the tool
response = llm_with_tools.invoke("What is 3 times 7?")
print(response)

Full Output

content='' additional_kwargs={'tool_calls': [{'id': 'kj0h3cwtm', 'function': {'arguments': '{"a":3,"b":7}', 'name': 'multiply'}, 
'type': 'function'}]} response_metadata={'token_usage': {'completion_tokens': 19, 'prompt_tokens': 228, 'total_tokens': 247,
'completion_time': 0.058486455, 'completion_tokens_details': None, 'prompt_time': 0.034593443, 'prompt_tokens_details': None,
'queue_time': 0.159857826, 'total_time': 0.093079898}, 'model_name': 'llama-3.3-70b-versatile', 'system_fingerprint': 'fp_45180df409', 'service_tier': 'on_demand', 'finish_reason': 'tool_calls', 'logprobs': None, 'model_provider': 'groq'} id='lc_run--019df212-a97c-7ab3-b5be-a48bdeb26b31-0' 
tool_calls=[{'name': 'multiply', 'args': {'a': 3, 'b': 7}, 'id': 'kj0h3cwtm', 'type': 'tool_call'}] invalid_tool_calls=[] usage_metadata={'input_tokens': 228, 'output_tokens': 19, 'total_tokens': 247}

If you inspect the output you will see a tool call, with name and args, is returned by the model.

tool_calls=[{'name': 'multiply', 'args': {'a': 3, 'b': 7}, 'id': 'kj0h3cwtm', 'type': 'tool_call'}]

But LangChain won’t automatically execute the tool for you, as LLM doesn’t actually read your code. You, as a developer need to parse this tools call and invoke the required tool.

Given below is the complete code.

from langchain_core.prompts import ChatPromptTemplate
from langchain_core.tools import tool
from langchain_groq import ChatGroq
from dotenv import load_dotenv

load_dotenv()  # Load environment variables from .env file

# Multiplication tool
@tool
def multiply(a: int, b: int) -> int:
    """Multiply two integers and return the result."""
    return a * b

# Initialize model
llm = ChatGroq(model="llama-3.3-70b-versatile", temperature=0.5)

llm_with_tools = llm.bind_tools([multiply])

# Now the LLM can decide when to call the tool
response = llm_with_tools.invoke("What is 3 times 7?")
print(response)

# if tool call is requested, it will be in response.tool_calls
if response.tool_calls:
    # loop through tool calls and execute them
    for tc in response.tool_calls:
        if tc["name"] == "multiply":
            result = multiply.invoke(tc["args"])
            print("Tool result:", result)

Output

Tool result: 21

Tool Calling with multiple tools

Here is another example, where we’ll see the workflow with multiple tool calls. Let’s say we have two different tools for addition and multiplication and tool call may contain both tools or any one of them. Workflow is as given below.

  1. LLM receives the user’s query.
  2. It decides whether the query needs external help (tool calling).
  3. If yes, appropriate ToolMessage is returned (tool call with name and args).
  4. The tool executes and returns a Result (e.g., live data, calculation, API response).
  5. That result is sent back to the LLM, which integrates it with the conversation.
  6. Finally, the LLM produces a polished, conversational answer for the user.

If you want to use a simple loop as shown in the previous example, then the code would be as given below.

from langchain_core.prompts import ChatPromptTemplate
from langchain_core.tools import tool
from langchain_groq import ChatGroq
from dotenv import load_dotenv

load_dotenv()  # Load environment variables from .env file

# Multiplication tool
@tool
def multiply(a: int, b: int) -> int:
    """Multiply two integers and return the result."""
    return a * b

# Addition tool
@tool
def add(a: int, b: int) -> int:
    """Add two integers and return the result."""
    return a + b

# Initialize model
llm = ChatGroq(model="llama-3.3-70b-versatile", temperature=0.5)

# Bind tools
llm_with_tools = llm.bind_tools([multiply, add])

# System prompt template
system_prompt = """
You are an AI assistant with access to external tools.
Your job is to decide when to call a tool, execute it correctly,
and then provide a polished, conversational answer to the user.

Available tools:
- multiply(a: int, b: int): returns the product of two integers
- add(a: int, b: int): returns the sum of two integers

Guidelines:
1. Think step by step about whether a tool is needed.
2. When calling a tool, output a structured tool call in JSON.
3. If no tool is needed, answer directly
4. Do not expose internal reasoning or chain-of-thought.
5. Only output either a tool call or a final user-friendly answer.
"""

# Build prompt template
prompt = ChatPromptTemplate.from_messages([
    ("system", system_prompt),
    ("user", "{input}")
])

def multi_tool_feedback(query: str):
    # First LLM call: decide tool usage
    first_response = llm_with_tools.invoke(query)
    print("First response:", first_response)
    results = []
    if first_response.tool_calls:
        print("Tool calls:", first_response.tool_calls)
        for tool_call in first_response.tool_calls:
            tool_name = tool_call["name"]
            args = tool_call["args"]

            # Execute each tool
            if tool_name == "multiply":
                result = multiply.invoke(args)
            elif tool_name == "add":
                result = add.invoke(args)
            else:
                result = "Unknown tool"

            results.append(result)

        print("Tool results:", results)
        # Second LLM call: feed all results back
        final_answer = llm.invoke(
            f"User asked: {query}. The tools returned: {results}. "
            "Please combine these into a natural language answer."
        )
        return final_answer
    else:
        # No tool calls, just return the model’s text
        return first_response

response = multi_tool_feedback("Please multiply 5 and 3, then add 10 to the result.")
print("Final response:", response)  
print("Final Answer:", response.content)

Output

First response: content='' additional_kwargs={'tool_calls': [{'id': '1e8aj5waj', 'function': {'arguments': '{"a":5,"b":3}', 'name': 'multiply'}, 'type': 'function'}, 
{'id': 'dbpynva42', 'function': {'arguments': '{"a":15,"b":10}', 'name': 'add'}, 'type': 'function'}]} 
response_metadata={'token_usage': {'completion_tokens': 36, 'prompt_tokens': 295, 'total_tokens': 331, 'completion_time': 0.076297873, 'completion_tokens_details': None, 'prompt_time': 0.014930285, 'prompt_tokens_details': None, 'queue_time': 0.157809024, 'total_time': 0.091228158}, 'model_name': 'llama-3.3-70b-versatile', 'system_fingerprint': 'fp_3272ea2d91', 'service_tier': 'on_demand', 'finish_reason': 'tool_calls', 'logprobs': None, 'model_provider': 'groq'} id='lc_run--019df1cb-134e-7232-b741-b9e941c64389-0'
tool_calls=[{'name': 'multiply', 'args': {'a': 5, 'b': 3}, 'id': '1e8aj5waj', 'type': 'tool_call'}, {'name': 'add', 'args': {'a': 15, 'b': 10}, 'id': 'dbpynva42', 'type': 'tool_call'}] invalid_tool_calls=[] usage_metadata={'input_tokens': 295, 'output_tokens': 36, 'total_tokens': 331}
Tool calls: [{'name': 'multiply', 'args': {'a': 5, 'b': 3}, 'id': '1e8aj5waj', 'type': 'tool_call'}, {'name': 'add', 'args': {'a': 15, 'b': 10}, 'id': 'dbpynva42', 'type': 'tool_call'}]
Tool results: [15, 25]
Final response: content='To solve the problem, we first multiply 5 and 3, which equals 15. Then, we add 10 to the result, giving us a final answer of 25.' additional_kwargs={} response_metadata={'token_usage': {'completion_tokens': 39, 'prompt_tokens': 73, 'total_tokens': 112, 'completion_time': 0.124071334, 'completion_tokens_details': None, 'prompt_time': 0.006693922, 'prompt_tokens_details': None, 'queue_time': 0.063180878, 'total_time': 0.130765256}, 'model_name': 'llama-3.3-70b-versatile', 'system_fingerprint': 'fp_dae98b5ecb', 'service_tier': 'on_demand', 'finish_reason': 'stop', 'logprobs': None, 'model_provider': 'groq'} id='lc_run--019df1cb-1507-7a33-aa60-6a5bd288b607-0' tool_calls=[] invalid_tool_calls=[] usage_metadata={'input_tokens': 73, 'output_tokens': 39, 'total_tokens': 112}
Final Answer: To solve the problem, we first multiply 5 and 3, which equals 15. Then, we add 10 to the result, giving us a final answer of 25.

Points to Note

  • The system message is made more descriptive to give clarity to the LLM about the tools and their arguments.
  • While executing the tools, their results are appended to a list.
  • That list and the original query is sent again to the LLM to get a final, polished answer.

Multi- tool calling with chain.

Same example can be done in a more professional way by creating a chain and using RunnableLambda to execute functions.

from langchain_groq import ChatGroq
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.tools import tool
from langchain_core.runnables import RunnableLambda
from dotenv import load_dotenv

load_dotenv()  # Load environment variables from .env file
# Define tools
@tool
def multiply(a: int, b: int) -> int:
    """Multiply two integers and return the result."""
    return a * b

@tool
def add(a: int, b: int) -> int:
    """Add two integers and return the result."""
    return a + b

# Initialize model
llm = ChatGroq(model="llama-3.3-70b-versatile", temperature=0.5)

# Bind tools
llm_with_tools = llm.bind_tools([multiply, add])

# 4. System prompt template
system_prompt = """
You are an AI assistant with access to external tools.
Your job is to decide when to call a tool, execute it correctly,
and then provide a polished, conversational answer to the user.

Available tools:
- multiply(a: int, b: int): returns the product of two integers
- add(a: int, b: int): returns the sum of two integers

Guidelines:
1. Think step by step about whether a tool is needed.
2. When calling a tool, output a structured tool call in JSON.
3. If no tool is needed, answer directly
4. Do not expose internal reasoning or chain-of-thought.
5. Only output either a tool call or a final user-friendly answer.
"""

# Build prompt template
prompt = ChatPromptTemplate.from_messages([
    ("system", system_prompt),
    ("user", "{input}")
])

# Define tool executor
def execute_tools(output):
    print("LLM output after first call:", output)
    results = []
    if output.tool_calls:
        for tc in output.tool_calls:
            if tc["name"] == "add":
                results.append(add.invoke(tc["args"]))
            elif tc["name"] == "multiply":
                results.append(multiply.invoke(tc["args"]))
            
    return {"tool_results": results, "query": output.content}

# Feed results back into LLM
def final_answer(data):
    return llm.invoke(
        f"User asked: {data['query']}. Tools returned: {data['tool_results']}. "
        "Please combine these into a natural language answer."
    )

# Chain
chain = (prompt 
        | llm_with_tools 
        | RunnableLambda(execute_tools) 
        | RunnableLambda(final_answer)
)

response = chain.invoke({"input": "Please add 5 and 3, then multiply the result by 2."})
print("Final response:", response)  
print("Final Answer:", response.content)

Output

LLM output after first call: content='' additional_kwargs={'tool_calls': [{'id': 'vz71y3drr', 'function': {'arguments': '{"a":5,"b":3}', 'name': 'add'}, 'type': 'function'}, {'id': '14hvbadej', 'function': {'arguments': '{"a":8,"b":2}', 'name': 'multiply'}, 'type': 'function'}]} 
response_metadata={'token_usage': {'completion_tokens': 36, 'prompt_tokens': 441, 'total_tokens': 477, 'completion_time': 0.092313015, 'completion_tokens_details': None, 'prompt_time': 0.022607, 'prompt_tokens_details': None, 'queue_time': 0.04985095, 'total_time': 0.114920015}, 'model_name': 'llama-3.3-70b-versatile', 'system_fingerprint': 'fp_dae98b5ecb', 'service_tier': 'on_demand', 'finish_reason': 'tool_calls', 'logprobs': None, 'model_provider': 'groq'} id='lc_run--019df260-48af-7080-9360-37fc5caad39c-0'
tool_calls=[{'name': 'add', 'args': {'a': 5, 'b': 3}, 'id': 'vz71y3drr', 'type': 'tool_call'}, {'name': 'multiply', 'args': {'a': 8, 'b': 2}, 'id': '14hvbadej', 'type': 'tool_call'}] invalid_tool_calls=[] usage_metadata={'input_tokens': 441, 'output_tokens': 36, 'total_tokens': 477}
Final response: content='The tools returned two values: 8 and 16.' additional_kwargs={} response_metadata={'token_usage': {'completion_tokens': 13, 'prompt_tokens': 57, 'total_tokens': 70, 'completion_time': 0.034086635, 'completion_tokens_details': None, 'prompt_time': 0.003220668, 'prompt_tokens_details': None, 'queue_time': 0.161129671, 'total_time': 0.037307303}, 'model_name': 'llama-3.3-70b-versatile', 'system_fingerprint': 'fp_3272ea2d91', 'service_tier': 'on_demand', 'finish_reason': 'stop', 'logprobs': None, 'model_provider': 'groq'} id='lc_run--019df260-4b3a-73d2-b4ce-79a0fae5297a-0' tool_calls=[] invalid_tool_calls=[] usage_metadata={'input_tokens': 57, 'output_tokens': 13, 'total_tokens': 70}
Final Answer: The tools returned two values: 8 and 16.

InjectedToolArg in Langchain tools

When building tools in LangChain, not every argument should come from the LLM. Some values, like session IDs, user tokens, timestamps, or database handles, are sensitive or system specific and must be injected at runtime. That’s exactly what InjectedToolArg in LangChain is designed for.

InjectedToolArg is a LangChain Core annotation that marks tool arguments as injected at runtime rather than generated by the LLM.

Arguments marked with InjectedToolArg are excluded from the schema sent to the model. The LLM never sees or generates them. That prevents the LLM from guessing or hallucinating values that should come from the environment (e.g., conversation IDs, request metadata, API keys).

Arguments marked with InjectedToolArg are provided by the developer, agent executor, or system context during tool execution.

InjectedToolArg Langchain example

Here is a simple example where Customer ID argument is marked as a InjectedToolArg, which means LLM won’t see it and even won’t try to guess it on its own. It has to be injected at runtime.

from typing import Annotated
from langchain_core.tools import tool, InjectedToolArg
from langchain_google_genai import ChatGoogleGenerativeAI
from dotenv import load_dotenv

load_dotenv()

# Define a tool with one normal arg (LLM-supplied) and one 
# injected arg (runtime-supplied)
@tool
def escalate_to_human(
    reason: str,
    customer_id: Annotated[int, InjectedToolArg]
) -> str:
    """Escalate the conversation to a human operator."""
    return f"Escalating: {reason} (Customer ID: {customer_id})"

# Create the LLM
llm = ChatGoogleGenerativeAI(model="gemini-3.1-flash-lite-preview", temperature=0.2)

# Bind the tool to the LLM
llm_with_tools = llm.bind_tools([escalate_to_human])

query = "The customer is very upset, escalate this."

# LLM processes the query and emits a tool call
response = llm_with_tools.invoke(query)

print("LLM raw response:", response)

if response.tool_calls:
    for tc in response.tool_calls:
        # Inject runtime context (customer_id from your system/session)
        # hardcodinhg customer_id=12345 for demo purposes
        runtime_context = {"customer_id": 12345}
        merged_args = {**tc["args"], **runtime_context}
        result = escalate_to_human.invoke(merged_args)
        print("Tool execution result:", result)
        # Feed the tool result back into the LLM to get final response
        response = llm.invoke(
            f"""
            Greet the customer using Customer ID (get from context) and inquire about the issue. 
            Context: {result}
            """
        )

print("Final LLM Response:", response)

print("Final LLM answer:", response.content[0].get("text"))

Output

LLM raw response: content=[] additional_kwargs={'function_call': {'name': 'escalate_to_human', 'arguments': '{"reason": "The customer is very upset and has requested an escalation."}'}, '__gemini_function_call_thought_signatures__': {'312283e6-b7ba-4149-97dd-1c93e5e97d8a': 'EjQKMgEMOdbHi4YjgRE760fr4+mtE0xB7dY5NZ3b3Dw6aZy70QE9eyXU9eDGgGKvMN8yu5z2'}} response_metadata={'finish_reason': 'STOP', 'model_name': 'gemini-3.1-flash-lite-preview', 'safety_ratings': [], 'model_provider': 'google_genai'} id='lc_run--019df2d2-81f9-75f3-9a97-f44e2ab3e660-0' 
tool_calls=[{'name': 'escalate_to_human', 'args': {'reason': 'The customer is very upset and has requested an escalation.'}, 'id': '312283e6-b7ba-4149-97dd-1c93e5e97d8a', 'type': 'tool_call'}] invalid_tool_calls=[] usage_metadata={'input_tokens': 59, 'output_tokens': 29, 'total_tokens': 88, 'input_token_details': {'cache_read': 0}}
Tool execution result: Escalating: The customer is very upset and has requested an escalation. (Customer ID: 12345)
Final LLM Response: content=[{'type': 'text', 'text': 'Hello, Customer 12345. I understand that you are very upset and have requested an escalation. I am here to assist you—could you please tell me more about the issue you are experiencing so I can address your concerns immediately?', 'extras': {'signature': 'EjQKMgEMOdbHAXp2AIc7nJffkQs5eevUxSKQmBMqsO/cAn089Zu+2eOdbvLIF6uunch0lbwA'}}] additional_kwargs={} response_metadata={'finish_reason': 'STOP', 'model_name': 'gemini-3.1-flash-lite-preview', 'safety_ratings': [], 'model_provider': 'google_genai'} id='lc_run--019df2d2-870d-71d3-9b4b-56ad10346d96-0' tool_calls=[] invalid_tool_calls=[] usage_metadata={'input_tokens': 52, 'output_tokens': 50, 'total_tokens': 102, 'input_token_details': {'cache_read': 0}}
Final LLM answer: Hello, Customer 12345. I understand that you are very upset and have requested an escalation. I am here to assist you—could you please tell me more about the issue you are experiencing so I can address your concerns immediately?

That’s all for this topic Tool Calling in LangChain. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Citation Aware RAG Application in LangChain
  2. LangChain Conversational RAG with Multi-user Sessions
  3. RunnableBranch in LangChain With Examples
  4. Structured Output In LangChain
  5. Messages in LangChain

You may also like-

  1. Chatbot With Chat History - LangChain MessagesPlaceHolder
  2. Document Loaders in LangChain With Examples
  3. Array in Java With Examples
  4. Java CyclicBarrier With Examples
  5. Python assert Statement
  6. Multiple Inheritance in Python
  7. Spring Boot REST API Documentation - OpenAPI, Swagger
  8. Bean Scopes in Spring With Examples