Saturday, March 28, 2026

Support Vector Regression With Example

In this post we'll see how to use Support Vector Regression (SVR) which extends Support Vector Machine (SVM) to regression tasks. Since SVR is a regression model that means it is used for predicting continuous values where as SVM is a classification model which predicts a category or class label.

SVR is particularly useful when relationship between features and target may be non-linear or complex, when traditional linear regression struggles.

How does SVR work

Support vector regression works on the concept of hyperplane and support vectors. It also has a margin of error, called epsilon (ε). Let's try to understand these concepts.

1. Hyperplane- SVR model works by finding a function (hyperplane) that fits most data points within a defined margin of error (ε-tube).

In the case of linear relationship (Linear SVR) this hyperplane can be thought of as a straight line in 2D space.

In case of non-linear relationship this hyperplane can be thought of as existing in a higher dimensional space but in 2D space it manifests as a best fitting curved function.

2. Kernel trick- This ability of SVR to work in higher dimensional spaces is achieved by "kernel trick". A non-linear relationship is very difficult (actually impossible) to represent with a straight line. By mapping the data into a higher-dimensional feature space, the relationship may become linear in that space. That transformation is not done explicitly as it can be very expensive.

Using kernel trick this computation becomes easier, this lets SVR work in high-dimensional spaces implicitly, without ever explicitly constructing the transformed features.

Common kernel functions used in SVR are linear, polynomial, radial basis function (RBF), and sigmoid.

3. Margin of error- SVR has some tolerance for error. It gives a margin of error (ε) and data points that reside with in that margin are considered to have no error. You can think of this margin as a tube that goes on both sides of the fitted line (or curve). That tube is known as ε-insensitive tube because it makes the model insensitive to minor fluctuations.

SVR tries to fit a function such that most points lie within an ε-tube around the regression line.

4. Support vectors- These are the points that fall outside the ε-tube or lie on the edge of it. These support vectors determine the position of the hyperplane. These are the only points that influence the regression function because points falling with in the ε-tube are considered to have no error.

5. Slack Variables- Numerical values assigned to the variables representing the distance of the points outside the tube from the ε-tube. These slack variables are represented using the symbol \(\xi\).

Following images try to clarify all the above nomenclatures.

Support Vector Regression

SVR equation

In SVR there is an objective function and the goal is to minimize that function-

$$\frac{1}{2}\| w\| ^2+C\sum _{i=1}^n(\xi _i+\xi _i^*) $$

1. Here w is the weight vector which is computed from the support vectors:

$$w=\sum _{i=1}^n(\alpha _i -\alpha _i^*)x_i$$

where

  • xi are the support vectors (training points that lie outside the ε-tube)
  • \(\alpha _i, \alpha _i^*\) are Lagrange multipliers from the optimization problem

Note that Lagrange multipliers are used here in finding the maximum or minimum of a function when certain conditions (constraints) must be satisfied.

Constraints here are; for each data point (xi,yi):

$$y_i-(w\cdot x_i+b)\leq \varepsilon +\xi _i$$ $$(w\cdot x_i+b)-y_i\leq \varepsilon +\xi _i^*$$ $$\xi _i,\xi _i^*\geq 0$$

Note that in linear SVR, w is the weight vector defining the regression hyperplane.
In non-linear SVR, the kernel trick replaces direct inner products (xi, xj) with a kernel function K(xi, xj) and w is not computed explicitly.

minimizing \(\frac{1}{2}\| w\| ^2\) (norm of the weight vector) ensures the function is as flat as possible. Benefit of doing that is improved generalization of the model to new data and increased robustness against outliers.

2. \((\xi _i, \xi _i^*)\) are slack variables that measure deviations outside the ε-insensitive tube.

3. C is the regularization parameter controlling trade-off between flatness and total deviations outside the ε-insensitive tube. A large C value fits data closely which may risk overfitting, a smaller C value means simpler model which may mean risk of underfitting.

SVR tries to minimize the objective function during training. It finds the best \(w, b, \alpha _i, \alpha _i^*\) that minimize this objective function.

Once the optimized values are calculated, the regression function is defined as:

$$f(x)=\sum _{i=1}^n(\alpha _i-\alpha _i^*)K(x_i,x)+b$$

This is the actual function you use to make predictions.

Where:

  • xi = training data points
  • K(xi, x) = kernel function (linear, polynomial, RBF, etc.)
  • \(\alpha _i,\alpha _i^*\) = Lagrange multipliers from optimization
  • b = bias term

If you use a linear kernel, the equation simplifies to:

$$f(x)=w\cdot x+b$$

In case kernel is RBF (Radial Basis Function), the SVR prediction equation takes the form:

$$f(x)=\sum _{i=1}^n(\alpha _i-\alpha _i^*)\, \exp \left( -\gamma \| x-x_i\| ^2\right) +b$$

When SVR with Polynomial Kernel is used then the regression function becomes:

$$f(x)=\sum _{i=1}^n(\alpha _i-\alpha _i^*)\, (\gamma \cdot (x_i\cdot x)+r)^d+b$$

Support Vector Regression using scikit-learn Python library

Dataset used here can be downloaded from- https://www.kaggle.com/datasets/mariospirito/position-salariescsv

Goal is to predict the salary based on the position level.

In the implementation code is broken into several smaller units with some explanation in between for data pre-processing steps.

1. Importing libraries and reading CSV file

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
df = pd.read_csv('./Position_Salaries.csv')

Position_Salaries.csv file is in the current directory.

2. Getting info about the data.

print(df.info())

Output


RangeIndex: 10 entries, 0 to 9
Data columns (total 3 columns):
 #   Column    Non-Null Count  	  Dtype 
---  ------    -------------- 	 ----- 
 0   Position 	10 non-null     object
 1   Level      10 non-null     int64 
 2   Salary     10 non-null     int64 

As you can see count of records is 10 only. Since dataset is already small so splitting is not done. Also, it is evident from one look at the small number of records that there are no duplicates and null values.

3. Feature and label selection

X = df.iloc[:, 1:-1]
y = df.iloc[:, -1]

Explanation- X = df.iloc[:, 1:-1]

  • : means "select all rows."
  • 1:-1 means "from column index 1 up to (but not including) the last column"

y = df.iloc[:, -1]

  • : means select all rows.
  • -1 means select the last column, uses negative indexing

"Position" column has been dropped as "level" column is also signifying the same thing in numerical values.

4.
print(X)
print(y)

On printing these two variables you can see that X is a 2D array where as y is a 1D array. Printing here just to make you understand that y may need conversion to 2D array as some of the functions need 2D array as parameter.

5. Scaling data

SVR relies on kernel functions (like RBF, polynomial) that compute distances between points. If features are on different scales, one feature can dominate the distance metric, skewing the model. So, standardizing the features is required.

With SVR target scaling is also required because the ε-insensitive tube and penalty parameter C are defined relative to the scale of y. Scaling y ensures that ε and C operate in a normalized space

from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVR
from sklearn.metrics import r2_score, mean_squared_error
scaler_X = StandardScaler()
scaler_y = StandardScaler()
X_scaled = scaler_X.fit_transform(X)
y_scaled = scaler_y.fit_transform(y.reshape(-1, 1)).ravel()

Dependent variable y needs to be changed to a 2D array for that reshape is used. Note that with reshape() one of the dimensions can be -1. In that case, the value is inferred from the length of the array. Here row is passed as -1 so NumPy will infer how many rows are needed based on array size.

ravel() is used to flatten the 2D array again. Otherwise, fit() method will give problem as that expects dependent variable to be a 1D array.

6. Fitting the model

reg = SVR(kernel='rbf')
reg.fit(X_scaled, y_scaled)

An object of class SVR is created, kernel is passed as 'rbf' which is also a default. For C and epsilon default values are used which are 1 and 0.1 respectively. Note that y_scaled was already changed to a 1D array using ravel(), if not done you'll get the following error.

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

7. Predicting values

First a single value is predicted.

#prediciting salary by passing level
y_pred_scaled = reg.predict(scaler_X.transform([[6]]))
# prediction will also be scaled, so need to do inverse transformation
y_pred = scaler_y.inverse_transform(y_pred_scaled.reshape(-1,1))
print("Prediction in original scale:", y_pred.ravel()) #145503.10688572

Note that X value has to be scaled as model is trained with scaled values. Also, predicted value has be inversely transformed to bring it back to original scale.

Predicting for the whole data. Since splitting is not done and there is no train and test data so X_scaled is used to predict values.

y_pred = scaler_y.inverse_transform(reg.predict(X_scaled).reshape(-1,1)).ravel()

8. Comparing test and predicted values

A dataframe is created and printed to display original and predicted values side-by-side.

df_results = pd.DataFrame({'Target':y, 'Predictions':y_pred})
print(df_results)

Output

	 Target	Predictions
0	45000	73416.856829
1	50000	78362.982831
2	60000	88372.122821
3	80000	108481.435811
4	110000	138403.075511
5	150000	178332.360333
6	200000	225797.711581
7	300000	271569.924155
8	500000	471665.638386
9	1000000	495411.293695

As you can see, model has lots of room for improvement, lack of proper data is one of the main reason here. For 1 million, prediction is way off the mark.

9. Seeing the model metrics such as R squared, mean squared error and root mean squared error.

#Metrics - R-Squared, MSE, RMSE
print("R2 score", r2_score(y, y_pred)) 
mse = mean_squared_error(y, y_pred)
print("Mean Squared Error", mse)
print("Root Mean Squared Error", np.sqrt(mse))

Output

R2 score 0.7516001070620797
Mean Squared Error 20036494264.13176
Root Mean Squared Error 141550.3241399742

10. Visualize the result

plt.scatter(X, y, color='red')
plt.plot(X, scaler_y.inverse_transform(reg.predict(X_scaled).reshape(-1,1)), color='blue')
plt.xlabel('Level')
plt.ylabel('Salary')
plt.title("SVR")
Support Vector Regression plot

That's all for this topic Support Vector Regression With Example. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Python Tutorial Page


Related Topics

  1. Simple Linear Regression With Example
  2. Multiple Linear Regression With Example
  3. Polynomial Regression With Example
  4. R-squared - Coefficient of Determination
  5. Mean Squared Error (MSE) With Python Examples

You may also like-

  1. What is LangChain - An Introduction
  2. Local, Nonlocal And Global Variables in Python
  3. Python count() method - Counting Substrings
  4. Python Functions : Returning Multiple Values
  5. Marker Interface in Java
  6. Functional Interfaces in Java
  7. Difference Between Checked And Unchecked Exceptions in Java
  8. Race Condition in Java Multi-Threading

First LangChain Program: Ask Me Anything

In this tutorial we’ll try to write few programs to connect to different LLMs using LangChain. In the post What is LangChain - An Introduction one of the points discussed was the standard interface provided by LangChain to integrate to any LLM.

Options to connect to the LLM using LangChain

There are two options to connect to the LLM using LangChain-

  • Using the init_chat_model function
  • Using the LLM specific model classes like ChatAnthropic, ChatOpenAI, ChatGoogleGenerativeAI, ChatOllama and so on.

Langchain init_chat_model function example

For the examples I am going to use OpenAI’s Gpt model, Google’s Gemini model and qwen3-32b through Groq inference provider. For another example, I’ll also use "llama3.1" through Ollama.

In the examples user's query is send to the model which responds with the answer to that query.

  • Packages needed are-

    • python-dotenv
    • langchain
    • langchain-openai
    • langchain-google-genai
    • langchain-groq
    • langchain-ollama

    You can install them individually using pip install PACKAGE_NAME or, if you are creating a Python program then you can create a requirements.txt file and put all the above mentioned external package dependencies in that file and provide that file to pip install commamd.

    pip install -r requirements.txt
    
  • Getting and setting the API key

    For using OpenAI models, Gemini models and Groq you must first obtain API key from the respective API provider. You can create an .env file in your Python project and store the generated API keys there.

    • GEMINI_API_KEY = “YOUR_GOOGLE_GEMINI_KEY”
    • GROQ_API_KEY = “YOUR_GROQ_API_KEY”
    • OPENAI_API_KEY = “YOUR_ OPENAI_API_KEY”

    This .env file can then be loaded using load_dotenv() function.

1. Connecting to Gemini

You can initialize the model by specifying the model name and optionally, the model_provider in init_chat_model() function. The temperature parameter is used to control the randomness, creativity, and determinism of the model's output.

  • Low Temperature (e.g., 0.0 to 0.3)

    Makes the model deterministic and focused. You'll get a "to the point" answer.

  • High Temperature (e.g., 0.7 to 1.0+)

    Makes the model creative and more diverse.

from langchain.chat_models import init_chat_model
from dotenv import load_dotenv

load_dotenv()
model = init_chat_model(    
  model="google_genai:gemini-3.1-flash-lite-preview",
  temperature=0.3
)
response = model.invoke("Explain Agentic AI in 5 lines")
print(response)

Output

content=[{'type': 'text', 'text': 'Agentic AI refers to autonomous systems capable of setting their own goals, breaking them 
into tasks, and executing them with minimal human intervention. Unlike traditional AI that simply responds to prompts, these 
agents use reasoning and tools to navigate complex environments. They actively monitor progress, adapt their strategies in 
real-time, and make decisions to achieve a desired outcome. Essentially, they shift the paradigm from "AI as a tool" to 
"AI as a collaborative partner" that gets work done.', 'extras': {'signature': 
'EjQKMgG+Pvb7ue1hvNYKCnERjPRv7v99o5JJsdZbRGGB3ce3fntMxKjz0D2dXa5GBv3l5myR'}}] additional_kwargs={} response_metadata=
{'finish_reason': 'STOP', 'model_name': 'gemini-3.1-flash-lite-preview', 'safety_ratings': [], 'model_provider': 'google_genai'} 
id='lc_run--019d2edb-3426-7033-a08d-d6d29fc97de5-0' tool_calls=[] invalid_tool_calls=[] usage_metadata={'input_tokens': 9, 
'output_tokens': 95, 'total_tokens': 104, 'input_token_details': {'cache_read': 0}}

As you can see response contains lot of other information along with actual content. You can extract the content part using response.content.

2. Connecting to OpenAI

from langchain.chat_models import init_chat_model
from dotenv import load_dotenv

load_dotenv()
model = init_chat_model(    
    model="gpt-5.2",
    temperature=0.3
)

response = model.invoke("Explain Agentic AI in 5 lines")
print(response.content)

3. Using qwen3-32b model through Groq

Since Groq is the model provider here so you need to explicitly mention it using model_provider parameter.

from langchain.chat_models import init_chat_model
from dotenv import load_dotenv

load_dotenv()
model = init_chat_model(    
    model="qwen/qwen3-32b",
    model_provider="groq",
    temperature=0.3
)

response = model.invoke("Explain Agentic AI in 5 lines")
print(response.content)

Configuration with init_chat_model

Above example used the fixed model initialization but you can also configure models at runtime using init_chat_model. That makes it easy to switch providers without changing code.

You need to set the following parameters for that-

  • configurable_fields: Defines which fields can be changed at runtime (e.g., 'any' for all fields, or a list like ("model", "temperature")).
  • config_prefix: If set, allows runtime configuration via config["configurable"]["{prefix}_{param}"]

in the following code initially "gpt-5.2" is selected as the model but later using the config_prefix "llama3.1" is set as the model.

from langchain.chat_models import init_chat_model
from dotenv import load_dotenv

load_dotenv()
configurable_model = init_chat_model(    
    model="gpt-5.2",
    temperature=0.3,
    configurable_fields="any", # Allows all fields to be configurable
    config_prefix="my_config" # Prefix for environment variables to override defaults
)

response = configurable_model.invoke("What is the role of GPU in the rise of AI?", 
        config={
        	"configurable": { "my_config_temperature": 0.7, # Override temperature for this invocation
                          "my_config_model": "llama3.1", # Override model for this invocation
                          "my_config_model_provider": "ollama" # Override model provider for this invocation
                        }
     	})
print(response.content)

You’ll get the output through Ollama not through GPT, because of the configuration settings.

Using Chat model classes in LangChain

LangChain provides chat model classes too for integrating with various models, enabling developers to build intelligent conversational AI applications with seamless support for OpenAI, Anthropic, Hugging Face, and other large language models.

These classes wrap various model providers, allowing developers to switch between them with minimal code changes.

Core classes for chat models are usually prefixed with Chat and imported from their integration packages, such as langchain_openai and langchain_anthropic. For example,

  • ChatOpenAI: For OpenAI models.
  • ChatAnthropic: For Anthropic models.
LangChain ChatModel Classes

Examples using Chat model classes

  1. Using qwen3-32b model through ChatGroq
  2. from langchain_groq import ChatGroq
    from dotenv import load_dotenv
    
    load_dotenv()
    model = ChatGroq(    
        model="qwen/qwen3-32b",
        temperature=0.3
    )
    
    response = model.invoke("What is the role of GPU in deep learning, explain in 5 lines?")
    print(response.content)
    
  3. Using ChatGoogleGenerativeAI to connect to Gemini
  4. from langchain_google_genai import ChatGoogleGenerativeAI
    from dotenv import load_dotenv
    
    load_dotenv()
    model = ChatGoogleGenerativeAI(    
        model="gemini-3.1-flash-lite-preview",
        temperature=0.3
    )
    
    response = model.invoke("What is the role of GPU in deep learning, explain in 5 lines?")
    print(response.content)
    

That's all for this topic Using qwen3-32b model through Groq. If you have any doubt or any suggestions to make please drop a comment. Thanks!

That's all for this topic First LangChain Program: Ask Me Anything. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Java is a Strongly Typed Language
  2. Primitive Data Types in Java
  3. Access Modifiers in Java - Public, Private, Protected and Default
  4. What Are JVM, JRE And JDK in Java
  5. Object Creation Using new Operator in Java

You may also like-

  1. String in Java Tutorial
  2. Array in Java
  3. Count Number of Words in a String Java Program
  4. Ternary Operator in Java With Examples
  5. Java Multithreading Interview Questions And Answers
  6. Java Exception Handling Tutorial
  7. ConcurrentHashMap in Java With Examples
  8. TreeMap in Java With Examples

Thursday, March 26, 2026

Java Variable Types With Examples

In this guide, we’ll explore the different types of variables in Java, their scopes, visibility, and practical examples to help you master the concept.

We’ll also see what is meant by declaring a variable and what is meant by initialization of a variable in Java.

Declaring and Initializing a variable in Java

In Java, every variable must be declared before use. Declaration specifies the type of the variable, which can be either a primitive data type (such as int, double, char), or having class or interface as type (reference variable).

Examples of variable declaration

int age, number; // two int variables declared

double amount; // a double variable declared

Person person; // reference type variable declared

As you see here, in the first statement two variables of type int are declared. Note that you can declare two or more variables of same type as a comma separated list.

In the third statement a variable person is declared which is of type Person. Here Person is a class.

Java 10 introduced a new feature called local variable type inference where the type of the variable is inferred from the variable initializer. A new reserved type name “var” is added in Java to define and initialize local variables, read more about var type here- Var type in Java - Local Variable Type Inference

Initialization of a variable in Java

Initialization means providing initial value of the variable. Generally, both declaration and initialization are done in a single statement.

 
int age = 30;

char grade = 'A';

But that is not necessary, you can also declare a variable first and initialize it later.

 
int age;

...... 
......
age = 50;

Variables can also be initialized using expressions:

 
double amount;

amount = 67/9;

Here amount will have the value of 67 divided by 9.

Types of variables in Java

The Java programming language defines the following kinds of variables:

  1. Instance Variables (Non-Static Fields)–Instance variables are declared inside a class but outside any method, constructor, or block, and they are not marked as static. Each object of the class gets its own copy of these variables, meaning their values are unique to each instance.

    For example, if you have a class Person and two objects of it person1 and person2 then the instance variables of these two objects will have independent values.

    public class Person {
     private String firstName;
     private String lastName;
     private int age;
     private char gender;
     public Person(String firstName, String lastName, int age, char gender){
      this.firstName = firstName;
      this.lastName = lastName;
      this.age = age;
      this.gender = gender;
     }
     
     public String getFirstName() {
      return firstName;
     }
    
     public String getLastName() {
      return lastName;
     }
    
     public int getAge() {
      return age;
     }
     public char getGender() {
      return gender;
     }
    }
    
    public class InstanceDemo {
    
     public static void main(String[] args) {
      Person person1 = new Person("Ram", "Mishra", 23, 'M');
      Person person2 = new Person("Amita", "Chopra", 21, 'F');
      
      System.out.println("Values in object person1 - " + 
        person1.getAge() + " " + person1.getFirstName() + " " + 
        person1.getLastName()+ " " + person1.getGender());
      System.out.println("Values in object person2 - " + 
        person2.getAge() + " " + person2.getFirstName() + " " + 
        person2.getLastName()+ " " + person2.getGender());
    
     }
    
    }
    

    Output

    Values in object person1 - 23 Ram Mishra M
    Values in object person2 - 21 Amita Chopra F
    

    Here you can see how using the constructor of the class, variables are initialized for both the objects and output shows that each instance of the class has its own values for the fields.

  2. Class Variables (Static Fields)- A class variable in Java is any field declared with the static modifier. As the name suggests class variable is at the class level. Unlike instance variables, there is only one copy of a static variable per class, shared across all objects. Doesn’t matter how many instances (objects) of the class you have, the class variable will have the same value. You can access class variables directly using the class name, without creating an object.

    Java class variables example

    One common use of static fields is to create a constant value that's at a class level and applicable to all created objects.

    public class Employee {
     int empId;
     String name;
     String dept;
     // static constant
     static final String COMPANY_NAME = "XYZ";
     Employee(int empId, String name, String dept){
      this.empId = empId;
      this.name = name;
      this.dept = dept;
     }
     
     public void displayData(){
      System.out.println("EmpId = " + empId + " name= " + name + " dept = " + 
      dept + " company = " + COMPANY_NAME);
     }
     public static void main(String args[]){  
      Employee emp1 = new Employee(1, "Ram", "IT");
      Employee emp2 = new Employee(2, "Krishna", "IT");
      emp1.displayData();
      emp2.displayData();
     }
    }
    

    Output

    EmpId = 1 name= Ram dept = IT company = XYZ
    EmpId = 2 name= Krishna dept = IT company = XYZ
    
  3. Local Variables– Local variables are variables declared within a method, constructor, or block. They represent the temporary state of a method and exist only during the execution of that method. Once the method finishes, the local variables are destroyed, and their values are no longer accessible.

    Scope of Local Variables

    The scope of a local variable is limited to the block of code enclosed by curly braces {} where it is declared. This means:
    • A local variable declared inside a method is accessible only within that method.
    • If you declare a variable inside a nested block (such as an if statement or loop), its scope is restricted to that block.

    One more thing to note is that you can have a local variable with the same name as class level variable in the method, with in the method the local variable will take priority.

    Java local variables example

    public class InstanceDemo {
     // class level variable
     int x = 8;
     public static void main(String[] args) {
      
      InstanceDemo id = new InstanceDemo();
      
      id.display();
      System.out.println("value of class level variable x " + id.x);
     }
     
     public void display(){
      int x = 5;  // local variable
      boolean flag = true;
      System.out.println("value of local variable x " + x);
      if (flag){
       int y = 10; // nested scope variable
       System.out.println("value of local variable y inside if " + y);
      }
      // This will cause compile-time error
      //System.out.println("value of local variable y inside if " + y); 
     }
     
    }
    

    Output

    value of local variable x 5
    value of local variable y inside if 10
    value of class level variable x 8
    

    Here you see there is a class level variable and again it the method display() there is a variable with the same name x. With in the method value of local variable x takes priority and that is printed. Once out of the method, x that is recognized is the class level variable x.

    Another thing to note is the nested scope created by the if condition with in the display() method. Scope of variable y is in between the starting and closing braces of the if condition. Once you are out of if condition y won’t be recognized. Any attempt to print value of y outside the if condition scope will result in compile-time error.

  4. Parameters- Variables passed to any method are known as parameters. Any changes made to the primitive types parameter won’t change the original value.

    Java parameters example

    public class InstanceDemo {
     public static void main(String[] args) {
      
      InstanceDemo id = new InstanceDemo();
      int x = 10;
      id.display(x);
      System.out.println("value of x after method call " + x);
     }
     
     public void display(int x){
      
      x++;
      System.out.println("value of local variable x " + x);
     }
     
    }
    

    Output

    value of local variable x 11
    value of x after method call 10
    

    Here you have a variable x that is passed to display method as an int parameter. With in the method display() value of x is changed. But that change is local only and doesn’t change the original value of x. This is because copy of a variable is passed as a method parameter.

    If an object is passed as a parameter and any of that object’s field is changed, that change will be visible in other scopes too.

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

>>>Return to Java Basics Tutorial Page


Related Topics

  1. Java is a Strongly Typed Language
  2. Primitive Data Types in Java
  3. Access Modifiers in Java - Public, Private, Protected and Default
  4. What Are JVM, JRE And JDK in Java
  5. Object Creation Using new Operator in Java

You may also like-

  1. String in Java Tutorial
  2. Array in Java
  3. Count Number of Words in a String Java Program
  4. Ternary Operator in Java With Examples
  5. Java Multithreading Interview Questions And Answers
  6. Java Exception Handling Tutorial
  7. ConcurrentHashMap in Java With Examples
  8. TreeMap in Java With Examples

What is LangChain - An Introduction

LangChain is an open-source framework which is designed to simplify the creation of LLM powered applications. Through its tools and APIs, it allows you to refine and customize information, making LLM generated responses more precise and contextually meaningful. For example, using LangChain you can link LLMs to external data sources and computation to enhance LLM model’s capabilities. By leveraging these capabilities, developers can build powerful AI applications like smart chatbots, advanced Q&A systems, summarization services.

LangChain Installation

LangChain framework is available as libraries in Python and JavaScript.

  • To install the LangChain package in Python you can use the following command
  • pip install -U langchain
        

    Prerequisite is Python 3.10+ installation for the LangChain version 1.2.13

  • For Typescript installation, you can use the following command
  • npm install langchain @langchain/core
        

    Prerequisite is Node.js 20+ installation for the LangChain version 1.2.13

Core components of LangChain

  1. Models

    LangChain’s standard model interfaces give you access to many different provider integrations. LangChain provides integration to nearly all the LLMs through a standard interface, including OpenAI, Anthropic, Google, to many open source models (like Meta AI’s LLaMa, Deepseek's Deepseek-LLM, Mistral) through HuggingFace, to locally downloaded LLMs through Ollama.

    Note that many LLM providers require an API key and you need to create an account in order to receive an API key.

    The simplest way to connect to any LLM is using the init_chat_model function in LangChain or you can use the LLM specific model classes like ChatAnthropic, ChatOpenAI, ChatGoogleGenerativeAI, ChatOllama and so on.

    Only thing you need is the integration package for the chosen model provider to be installed which is generally in the format langchain-LLM_PROVIDER_NAME. So, if you are using OpenAI then you need to install langchain-openai package.

    Refer this post- First LangChain Program: Ask Me Anything to see how to connect to different models programmatically using LangChain.

  2. Prompt Template

    LangChain provides a PromptTemplate class to create a prompt template- a dynamic prompt with some placeholders that can be given actual values later. There is also a ChatPromptTemplate class which acts as a prompt template for chat models.

  3. Tools

    LLMs have some limitations, firstly these models are trained up to some cutoff date and they have data up to that time only. Though many LLMs now have web browsing capability to bypass their training data cutoff. Another problem is not have domain data or company specific data.

    Langchain tools can give that functionality to agents by letting them fetch real-time data, execute code, query external databases, and take actions in the world. Under the hood, tools are callable functions with well-defined inputs and outputs that get passed to a chat model. The model decides when to invoke a tool based on the conversation context, and what input arguments to provide.

  4. Agents

    LangChain agents combine LLMs with tools to create systems that can complete complex tasks step by step. Unlike a basic application where you send a prompt and get a response from an LLM, LangChain agents can think, plan, and adapt.

    They integrate language models with tools to reason about tasks and choose the right actions.

    This allows them to iteratively work toward solutions with greater intelligence and flexibility.

  5. Chains

    As the name LangChain itself suggests, chains are the main concept of LangChain. They allow developers to link multiple components together into a single workflow. Each link in the chain can handle a specific task, from prompt formatting to retrieval and reasoning. This modular design makes it easy to build complex AI applications step by step.

    With the LangChain Expression Language (LCEL), you can define these chains declaratively, using the pipe (|) symbol to connect prompts, models, retrievers, and output parsers.

  6. Memory

    For many AI applications you may need to retain information about previous interactions. For AI agents, memory is crucial because it lets them remember previous interactions, learn from feedback, and adapt to user preferences. LangChain provides both short term memory and long term memory.

    1. Short term memory- It lets your application remember previous interactions within a single thread or conversation.
    2. Long-term memory- It lets your agent store and recall information across different conversations and sessions. Long-term memory persists across threads and can be recalled at any time.

How does LangChain work

Now, when you have some idea about the components of LangChain, let us try to understand how LangChain can actually chain together different components to create a workflow for LLM powered applications.

For example, a typical Retrieval-Augmented Generation (RAG) application may have a workflow as given below-

  1. Receive the user’s query.
  2. Reformulate the query by sending it to the LLM which rephrases the user provided query into a concise search query.
  3. Retrieve the data relevant to search query, which could involve connecting to databases, APIs, or other repositories (e.g. Confluence). LangChain provides various document loaders like PyPDFLoader, TextLoader, CSVLoader, ConfluenceLoader for integrating data from numerous sources.
  4. Pass the retrieved documents to LLM to summarize the information
  5. Pass the retrieved information, along with the original query, to an LLM to get the final answer.

That's all for this topic What is LangChain - An Introduction. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Java Program to Check Prime Number
  2. Armstrong Number or Not Java Program
  3. How to Display Pyramid Patterns in Java - Part2
  4. Java Program to Reverse a Number
  5. Swap or Exchange Two Numbers Without Using Any Temporary Variable Java Program

You may also like-

  1. Find Duplicate Elements in an Array Java Program
  2. Count Number of Times Each Character Appears in a String Java Program
  3. Check if Given String or Number is a Palindrome Java Program
  4. Polymorphism in Java
  5. Difference Between Abstract Class And Interface in Java
  6. Java Automatic Numeric Type Promotion
  7. Java Pass by Value or Pass by Reference
  8. finally Block in Java Exception Handling

Merge Sort Program in Java

In this post, we’ll explore how to implement a Merge Sort Program in Java. Merge sort is much more efficient than the simple sort algorithms like bubble sort and insertion sort, especially for large datasets. The only trade-off is that it requires an additional array along with the original array that is sorted.

How merge sort works

Merge sort works on the concept of merging two sorted arrays to create another array which is also sorted.

Now the question is how do you get those sorted arrays which are merged?

Merge Sort follows the Divide and Conquer paradigm. The algorithm repeatedly divides the input array into two halves until you get sub-arrays with a single element which is considered a sorted array.

At that point you start merging these sub-arrays, from two single element sub-arrays you create a sorted merged array of two elements. Then two such sorted sub-arrays of two elements are merged to create a sorted array of four elements and so on until you have a sorted array of all the elements.

Since array is recursively divided into two halves so this division process can be written as a recursive method where base case becomes the point when you have sub-arrays with only one element each.

Let’s try to understand with an example where we have an input array as given below.

int[] intArr = {21, 11, 33, 70, 5, 25, 65, 55};

The process of recursive calls to divide the array into halves can be explained using the following image.

merge sort in java

At this point merge process starts which merges two sorted arrays to create another sorted array, this merging process can be explained using the following image.

merge sort program java

Merge Sort Java program

In the merge sort program there is a method mergeSortRecursive which is called recursively to divide the array.

Merge method merges the two sub-arrays to create a sorted array.

public class MergeSort {
  public static void main(String[] args) {
    int[] intArr = {47, 85, 620, 3456, -7, 10, 4500, 106, -345, 1000, 67, 80, 5500, 34, 78, 782, 4, 0, 99, 190};
    MergeSort ms = new MergeSort();
    ms.mergeSortRecursive(intArr, 0, intArr.length-1);
    System.out.println("Sorted array after merge sort- ");
    for(int num : intArr){
      System.out.print(num + " ");
    }
  }
    
  private void mergeSortRecursive(int[] intArr, int lower, int upper){
    //base case
    if (lower == upper){
      return;
    }else{
      // get mid point for division of array
      int middle = (lower + upper)/2;
      
      mergeSortRecursive(intArr, lower, middle);        
      mergeSortRecursive(intArr, middle+1, upper);
      
      merge(intArr, lower, middle, upper);
    }
  }
    
  private void merge(int[] intArr, int lower, int middle, int upper){
      /** Create two temp arrays pertaining to two halves that 
       are being merged and add elements to them  */
      int subArrayOneLength = middle - lower + 1;
      int subArrayTwoLength = upper - middle;
      int[] temp1 = new int[subArrayOneLength];
      int[] temp2 = new int[subArrayTwoLength];
      for(int i = 0; i < subArrayOneLength; i++){
        temp1[i] = intArr[lower + i];
      }
      for(int j = 0; j < subArrayTwoLength; j++){
        temp2[j] = intArr[middle + 1 + j];
      }           
      int i =0;        
      int j = 0;
      // merging process, merge two temp arrays 
      while((i < subArrayOneLength) && (j < subArrayTwoLength)){
        if(temp1[i] < temp2[j]){
          intArr[lower] = temp1[i++];
        }else{
          intArr[lower] = temp2[j++];
        }
        lower++;
      }
      // If there are more elements
      while(i < subArrayOneLength){
        intArr[lower++] = temp1[i++];
      }
      while(j < subArrayTwoLength){
        intArr[lower++] = temp2[j++];
      }
  }
}

Output

Sorted array after merge sort- 
-345 -7 0 4 10 34 47 67 78 80 85 99 106 190 620 782 1000 3456 4500 5500 

Performance of merge sort

In merge sort there is subdivision of arrays and for each sub-division there is merging. Number of levels (subdivisions of array) can be calculated as– (logN + 1)

For example log of 8 base 2 is 3, so log8 + 1 = 4

Which is same as the number of halves for the array having 8 elements– 8 4 2 1.

At each level N elements are merged which makes the time complexity of merge sort as N*(logN + 1). we can discard the 1 so the time complexity of merge sort is O(N*logN).

Merge sort is not an in place sort algorithm as extra space is required. Auxiliary space required is equal to the number of elements in the original array so the space complexity of merge sort is O(N).

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

>>>Return to Java Programs Page


Related Topics

  1. Shell Sort Program in Java
  2. Radix Sort Program in Java
  3. How to Display Pyramid Patterns in Java - Part1
  4. Arrange Non-Negative Integers to Form Largest Number - Java Program
  5. Find All Permutations of a Given String Java Program

You may also like-

  1. Running Dos/Windows Commands From Java Program
  2. Find Duplicate Elements in an Array Java Program
  3. How to Display Time in AM-PM Format in Java
  4. How to Sort an ArrayList in Descending Order in Java
  5. CopyOnWriteArrayList in Java With Examples
  6. Java Reflection API Tutorial
  7. String in Java Tutorial
  8. NameNode, DataNode And Secondary NameNode in HDFS

Wednesday, March 25, 2026

Java Program to Display Prime Numbers

In this tutorial, we’ll explore a Java Program to Display Prime Numbers up to a given range.

A prime number is a natural number greater than 1 that has no divisors other than 1 and itself. Examples include: 2, 3, 5, 7, 11, 13, 17….

Efficient Prime Check Logic

To check if a number is prime or not you don't need to run a loop starting from 2 till that number to check if number has any divisor. You can use a more efficient approach to loop only up to \( \sqrt{n}\) (square root of the number).If no divisor is found in this range, the number is prime.

Let's try to understand why looping only up to \( \sqrt{n}\) is sufficient.

If a number n is not prime, it can be expressed as a product of two factors-

\( n=a\times b\)

At least one of these factors must be less than or equal to \( \sqrt{n}\).

For example, for n = 36, factors are (6 × 6) or (4 × 9). Notice that one factor (4 or 6) is = \( \sqrt{36}\) = 6. Therefore, if no divisor is found up to \( \sqrt{n}\), there cannot be any divisor beyond \( \sqrt{n}\) either, because the corresponding smaller factor would already have been detected.

Looking for more efficient way to display prime numbers. Refer these sieving algorithms- Java Program - Sieve of Eratosthenes to Find Prime Numbers, Java Program - Sieve of Sundaram to Find Prime Numbers

How LinkedList Class Works Internally in Java

In the Java Collections Framework, two widely used implementations of the List interface are:

The difference lies in their internal data structures. ArrayList uses a dynamically resizable array of Object[], making it efficient for random access but costly for insertions and deletions in the middle.

To read more about how ArrayList works internally in Java refer this post- How ArrayList works internally in Java

In this article, I'll talk about LinkedList internal implementation in Java Collections framework and understand why it is often chosen for scenarios involving frequent insertions and deletions.


Internal implementation of LinkedList class in Java

The LinkedList class in Java implements both the List and Deque interfaces. Internally, it is built using a doubly linked list data structure.

At the core of the implementation of the LinkedList class in Java there is a private static inner class Node<E> which defines the structure of each element in the list. It has item variable for holding the value and two reference to Node class itself for connecting to next and previous nodes.

The Node class from Linked List implementation

private static class Node<E> {
  E item;
  Node<E> next;
  Node<E> prev;
  Node(Node<E> prev, E element, Node<E> next) {
    this.item = element;
    this.next = next;
    this.prev = prev;
  }
}
  • item- Stores the actual data.
  • next- Reference to the next node.
  • prev- Reference to the previous node.

Graphical representation of Java LinkedList with nodes

Here is a graphical representation of a linked list to help you better visualize how actually a node will look like and how it connects with other nodes through next and prev references.
Since reference is stored for both next and previous nodes that is why it is a doubly linked list implementation.

LinkedList internal implementation in Java

This design allows bidirectional traversal and makes insertions/deletions at both ends (head and tail) highly efficient- constant time operations.

For insertions or deletions in the middle of the list, the actual update of node references (prev and next) is still efficient. However, reaching the desired position requires traversal from either end, which makes these operations linear time (O(n)).

Though there are many methods with in the LinkedList class but here I'll try to explain the internal working of the LinkedList, how references are created and shuffled using these 3 methods-

  • private void linkFirst(E e)
  • void linkLast(E e)
  • public void add(int index, E element)

Java LinkedList internal implementation - linkFirst() method

linkFirst() method is used to add an element at the beginning of the list and it is implemented as follows in the LinkedList class

/**
 * Links e as first element.
 */
private void linkFirst(E e) {
  final Node<E> f = first;
  final Node<E> newNode = new Node<>(null, e, f);
  first = newNode;
  if (f == null)
      last = newNode;
  else
      f.prev = newNode;
  size++;
  modCount++;
}

Here one more important thing to mention is first and last Node class references which always refer to the first and last element of the linked list.

/**
 * Pointer to first node.
 * Invariant: (first == null && last == null) ||
 *            (first.prev == null && first.item != null)
 */
transient Node<E> first;
/**
 * Pointer to last node.
 * Invariant: (first == null && last == null) ||
 *            (last.next == null && last.item != null)
 */
transient Node<E> last;

With this info it is easy to see that in the linkFirst method, when the very first element is inserted into the list first and last both refer to this new node.

In case linked list already contains elements and a new element is inserted at the beginning of the list. Then f will hold the reference to the node which was the first element before this insertion. first will be assigned the reference to the newly created node (first = newNode;). The element which was the first element before this insertion is at second position now so its prev element should store reference of the first node, that's what is happening here f.prev = newNode;

And in the call to the constructor of the node class f is sent as a parameter. If you see in the Node class constructor there is a line this.next = next; that's how the newly created node is storing the reference to the second node.

Java LinkedList internal implementation - linkLast() method

linkLast() method is used to insert element as the last element of the list. In that case the node which is currently the last node of the linked list will become the second last node. So the newly created node's prev should store the reference to this second last node and the next of the second last node should store the reference to the node which is the last node now.

/**
 * Links e as last element.
 */
void linkLast(E e) {
  final Node<E> l = last;
  final Node<E> newNode = new Node<>(l, e, null);
  last = newNode;
  if (l == null)
      first = newNode;
  else
      l.next = newNode;
  size++;
  modCount++;
}

Here it is first checking if it is the very first element which is inserted in that case both first and last references point to it. If elements are already there in the linked list then the node which is currently the last node of the linked list will become the second last node now.

See the call to the constructor of the Node class (this.prev = prev;). So the newly created node's prev should store the reference to this second last node and the next of the second last node should store the reference to the node which is the last node now (l.next = newNode;).

Java LinkedList internal implementation - add(int index, E element) method

add(int index, E element) is used to Insert the specified element at the specified position in this list.

public void add(int index, E element) {
  checkPositionIndex(index);

  if (index == size)
    linkLast(element);
  else
    linkBefore(element, node(index));
}

Here it calls linkBefore method

void linkBefore(E e, Node<E> succ) {
  // assert succ != null;
  final Node<E> pred = succ.prev;
  final Node<E> newNode = new Node<>(pred, e, succ);
  succ.prev = newNode;
  if (pred == null)
    first = newNode;
  else
    pred.next = newNode;
  size++;
  modCount++;
}

And node(index) parameter with in the linkBefore() method is call to the following method to get the existing Node at the given index-

/**
* Returns the (non-null) Node at the specified element index.
*/
Node<E> node(int index) {
 // assert isElementIndex(index);

  if (index < (size >> 1)) {
    Node<E> x = first;
    for (int i = 0; i < index; i++)
      x = x.next;
    return x;
  } else {
    Node<E> x = last;
    for (int i = size - 1; i > index; i--)
      x = x.prev;
    return x;
  }
}

I am leaving it to you readers to figure out how linkBefore() method is working. It should be easy based on the explanation already provided for linkFirst() and linkLast() method.

That's all for this topic How LinkedList Class Works Internally 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 HashSet Works Internally in Java
  3. Difference Between ArrayList And LinkedList in Java
  4. ListIterator in Java
  5. Java Collections Interview Questions And Answers

You may also like-

  1. How to Convert Array to ArrayList in Java
  2. Difference between HashMap and ConcurrentHashMap in Java
  3. static import in Java
  4. finally Block in Java Exception Handling
  5. Interface Static Methods in Java
  6. Method reference in Java 8
  7. Java Program to Find First Non-Repeated Character in a Given String
  8. Synchronization in Java - Synchronized Method And Block