Repository: TheAlgorithms/Java
File: src/main/java/com/thealgorithms/geometry/GrahamScan.java (Java)

Code before:
package com.thealgorithms.geometry;

import java.util.Arrays;
import java.util.Comparator;
import java.util.Stack;

/**
 * A Java program that computes the convex hull using the Graham Scan algorithm.
 * The time complexity is O(n) in the best case and O(n log(n)) in the worst case.
 * The space complexity is O(n).
 * This algorithm is applicable only to integral coordinates.
 *
 * References:
 * https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/geometry/graham_scan_algorithm.cpp
 * https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/geometry/graham_scan_functions.hpp
 * https://algs4.cs.princeton.edu/99hull/GrahamScan.java.html
 */
public class GrahamScan {
    private final Stack<Point> hull = new Stack<>();

    public GrahamScan(Point[] points) {
        // Pre-process points: sort by y-coordinate, then by polar order with respect to the first point
        Arrays.sort(points);
        Arrays.sort(points, 1, points.length, points[0].polarOrder());
        hull.push(points[0]);

        // Find the first point not equal to points[0] and the first point not collinear with the previous points
        int indexPoint1;
        for (indexPoint1 = 1; indexPoint1 < points.length; indexPoint1++) {
            if (!points[0].equals(points[indexPoint1])) {
                break;
            }
        }
        if (indexPoint1 == points.length) {
            return;
        }

        int indexPoint2;
        for (indexPoint2 = indexPoint1 + 1; indexPoint2 < points.length; indexPoint2++) {
            if (Point.orientation(points[0], points[indexPoint1], points[indexPoint2]) != 0) {
                break;
            }
        }
        hull.push(points[indexPoint2 - 1]);

        // Process the remaining points and update the hull
        for (int i = indexPoint2; i < points.length; i++) {
            Point top = hull.pop();

Review comment (suggestion):
It seems that this implementation does not validate the input data, that the minimum number of points must be 3 to construct a convex hull. And also if all the points are the same, then it also would not be able to process such input. 

Checks can be look something like this:

```
if (points == null || points.length < 3) {
    throw new IllegalArgumentException("At least 3 points are required to compute the convex hull");
}

// Check if all points are the same
boolean allSame = true;
for (int i = 1; i < points.length; i++) {
    if (!points[i].equals(points[0])) {
        allSame = false;
        break;
    }
}

if (allSame) {
    hull.push(points[0]);
    return;
}
```

It is also good to have appropriate tests for such cases.

Code after:
package com.thealgorithms.geometry;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Stack;

/**
 * A Java program that computes the convex hull using the Graham Scan algorithm.
 * The time complexity is O(n) in the best case and O(n log(n)) in the worst case.
 * The space complexity is O(n).
 * This algorithm is applicable only to integral coordinates.
 *
 * References:
 * https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/geometry/graham_scan_algorithm.cpp
 * https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/geometry/graham_scan_functions.hpp
 * https://algs4.cs.princeton.edu/99hull/GrahamScan.java.html
 */
public class GrahamScan {

    private final Stack<Point> hull = new Stack<>();

    public GrahamScan(Point[] points) {
        // Pre-process points: sort by y-coordinate, then by polar order with respect to the first point
        Arrays.sort(points);
        Arrays.sort(points, 1, points.length, points[0].polarOrder());

        hull.push(points[0]);

        // Find the first point not equal to points[0] (firstNonEqualIndex)
        // and the first point not collinear firstNonCollinearIndex with the previous points
        int firstNonEqualIndex;
        for (firstNonEqualIndex = 1; firstNonEqualIndex < points.length; firstNonEqualIndex++) {
            if (!points[0].equals(points[firstNonEqualIndex])) {
                break;
            }
        }

        if (firstNonEqualIndex == points.length) {
            return;
        }

        int firstNonCollinearIndex;
        for (firstNonCollinearIndex = firstNonEqualIndex + 1; firstNonCollinearIndex < points.length; firstNonCollinearIndex++) {
            if (Point.orientation(points[0], points[firstNonEqualIndex], points[firstNonCollinearIndex]) != 0) {
                break;
            }
        }