DSA

A* Search Algorithm in Java: Heuristic Pathfinding

Master the A* search algorithm in Java. Learn how it combines Dijkstra's logic with heuristics to find the shortest path significantly faster in maps and grids.

Sachin Sarawgi·April 19, 2026·3 min read
#dsa#java#graph#shortest path#a-star#heuristic#interview preparation#algorithms

The A (A-Star) search algorithm* is one of the most successful pathfinding algorithms in computer science. It is widely used in video games and robotics because it is both efficient and guaranteed to find the shortest path (given a proper heuristic).

It is essentially Dijkstra's algorithm with a brain.

The Core Concept: $f(n) = g(n) + h(n)$

Instead of just looking at the distance from the start (like Dijkstra), A* uses a "heuristic" to estimate the distance to the goal.

  • $g(n)$: The actual cost from the start node to the current node $n$.
  • $h(n)$: The estimated (heuristic) cost from node $n$ to the goal.
  • $f(n)$: The total estimated cost of the path through node $n$.

A* always expands the node with the lowest $f(n)$.


A* Implementation in Java (on a Grid)

import java.util.*;

public class AStarSearch {
    static class Node implements Comparable<Node> {
        int x, y, g, h, f;
        Node parent;

        Node(int x, int y) {
            this.x = x;
            this.y = y;
        }

        @Override
        public int compareTo(Node other) {
            return Integer.compare(this.f, other.f);
        }
    }

    public List<Node> findPath(int[][] grid, int[] start, int[] end) {
        PriorityQueue<Node> openList = new PriorityQueue<>();
        boolean[][] closedList = new boolean[grid.length][grid[0].length];

        Node startNode = new Node(start[0], start[1]);
        Node endNode = new Node(end[0], end[1]);

        openList.add(startNode);

        while (!openList.isEmpty()) {
            Node current = openList.poll();
            closedList[current.x][current.y] = true;

            if (current.x == endNode.x && current.y == endNode.y) {
                return reconstructPath(current);
            }

            for (Node neighbor : getNeighbors(current, grid)) {
                if (closedList[neighbor.x][neighbor.y]) continue;

                int tentativeG = current.g + 1; // Assuming cost between adjacent cells is 1

                if (tentativeG < neighbor.g || !contains(openList, neighbor)) {
                    neighbor.parent = current;
                    neighbor.g = tentativeG;
                    neighbor.h = calculateHeuristic(neighbor, endNode);
                    neighbor.f = neighbor.g + neighbor.h;

                    if (!contains(openList, neighbor)) {
                        openList.add(neighbor);
                    }
                }
            }
        }
        return null; // No path found
    }

    private int calculateHeuristic(Node a, Node b) {
        // Manhattan distance for grid-based movement
        return Math.abs(a.x - b.x) + Math.abs(a.y - b.y);
    }
}

Dijkstra vs. A*

Feature Dijkstra A*
Heuristic None (or $h(n) = 0$) Uses $h(n)$ to guide search
Expansion Expands in all directions equally Focuses towards the goal
Performance Slower Much faster (with a good heuristic)
Optimality Guaranteed shortest path Guaranteed (if $h(n)$ is admissible)

What is an "Admissible" Heuristic?

A heuristic is admissible if it never overestimates the actual cost to reach the goal. If your heuristic is too "optimistic," A* might pick a sub-optimal path. Manhattan distance (for 4-direction movement) and Euclidean distance (for any-angle movement) are classic admissible heuristics.

Summary

A* is the gold standard for pathfinding in constrained spaces. By combining the rigorous distance tracking of Dijkstra with a smart "guess" about the remaining distance, it avoids exploring unnecessary areas of the graph. Understanding A* is a great way to show that you can apply mathematical intuition to solve practical engineering problems.

📚

Recommended Resources

Java Masterclass — UdemyBest Seller

Comprehensive Java course covering Java 17+, OOP, concurrency, and modern APIs.

View Course
Effective Java, 3rd EditionMust Read

Joshua Bloch's classic guide to writing clear, correct, and efficient Java code.

View on Amazon
Java Concurrency in Practice

The authoritative book on writing thread-safe, concurrent Java programs.

View on Amazon

Practical engineering notes

Get the next backend guide in your inbox

One useful note when a new deep dive is published: system design tradeoffs, Java production lessons, Kafka debugging, database patterns, and AI infrastructure.

No spam. Just practical notes you can use at work.

Sachin Sarawgi

Written by

Sachin Sarawgi

Engineering Manager and backend engineer with 10+ years building distributed systems across fintech, enterprise SaaS, and startups. CodeSprintPro is where I write practical guides on system design, Java, Kafka, databases, AI infrastructure, and production reliability.

Found this useful? Share it: