diff --git a/DIRECTORY.md b/DIRECTORY.md
index 22453235b..656597c3b 100644
--- a/DIRECTORY.md
+++ b/DIRECTORY.md
@@ -501,6 +501,7 @@
* [DualPivotQuickSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/DualPivotQuickSort.java)
* [DutchNationalFlagSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/DutchNationalFlagSort.java)
* [ExchangeSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/ExchangeSort.java)
+ * [FlashSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/FlashSort.java)
* [GnomeSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/GnomeSort.java)
* [HeapSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/HeapSort.java)
* [InsertionSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/InsertionSort.java)
@@ -874,6 +875,7 @@
* [DualPivotQuickSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/DualPivotQuickSortTest.java)
* [DutchNationalFlagSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/DutchNationalFlagSortTest.java)
* [ExchangeSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/ExchangeSortTest.java)
+ * [FlashSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/FlashSortTest.java)
* [GnomeSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/GnomeSortTest.java)
* [HeapSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/HeapSortTest.java)
* [InsertionSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/InsertionSortTest.java)
diff --git a/src/main/java/com/thealgorithms/sorts/FlashSort.java b/src/main/java/com/thealgorithms/sorts/FlashSort.java
new file mode 100644
index 000000000..e8dbf8c42
--- /dev/null
+++ b/src/main/java/com/thealgorithms/sorts/FlashSort.java
@@ -0,0 +1,206 @@
+package com.thealgorithms.sorts;
+
+/**
+ * Implementation of Flash Sort algorithm that implements the SortAlgorithm interface.
+ *
+ * Sorts an array using the Flash Sort algorithm.
+ *
+ * Flash Sort is a distribution sorting algorithm that partitions the data into
+ * different classes based on a classification array. It performs the sorting by
+ * first distributing the data elements into different buckets (or classes) and
+ * then permuting these buckets into the sorted order.
+ *
+ * The method works as follows:
+ *
+ * - Finds the minimum and maximum values in the array.
+ * - Initializes a classification array `L` to keep track of the number of elements in each class.
+ * - Computes a normalization constant `c1` to map elements into classes.
+ * - Classifies each element of the array into the corresponding bucket in the classification array.
+ * - Transforms the classification array to compute the starting indices of each bucket.
+ * - Permutes the elements of the array into sorted order based on the classification.
+ * - Uses insertion sort for the final arrangement to ensure complete sorting.
+ *
+ */
+public class FlashSort implements SortAlgorithm {
+ private double classificationRatio = 0.45;
+
+ public FlashSort() {
+ }
+
+ public FlashSort(double classificationRatio) {
+ if (classificationRatio <= 0 || classificationRatio >= 1) {
+ throw new IllegalArgumentException("Classification ratio must be between 0 and 1 (exclusive).");
+ }
+ this.classificationRatio = classificationRatio;
+ }
+
+ public double getClassificationRatio() {
+ return classificationRatio;
+ }
+
+ public void setClassificationRatio(double classificationRatio) {
+ if (classificationRatio <= 0 || classificationRatio >= 1) {
+ throw new IllegalArgumentException("Classification ratio must be between 0 and 1 (exclusive).");
+ }
+ this.classificationRatio = classificationRatio;
+ }
+
+ /**
+ * Sorts an array using the Flash Sort algorithm.
+ *
+ * @param array the array to be sorted.
+ * @param the type of elements to be sorted, must be comparable.
+ * @return the sorted array.
+ */
+ @Override
+ public > T[] sort(T[] array) {
+ flashSort(array);
+ return array;
+ }
+
+ /**
+ * Sorts an array using the Flash Sort algorithm.
+ *
+ * @param arr the array to be sorted.
+ * @param the type of elements to be sorted, must be comparable.
+ */
+ private > void flashSort(T[] arr) {
+ if (arr.length == 0) {
+ return;
+ }
+
+ final T min = findMin(arr);
+ final int maxIndex = findMaxIndex(arr);
+
+ if (arr[maxIndex].compareTo(min) == 0) {
+ return; // All elements are the same
+ }
+
+ final int m = (int) (classificationRatio * arr.length);
+
+ final int[] classificationArray = new int[m];
+
+ final double c1 = (double) (m - 1) / arr[maxIndex].compareTo(min);
+
+ classify(arr, classificationArray, c1, min);
+
+ transform(classificationArray);
+
+ permute(arr, classificationArray, c1, min, arr.length, m);
+
+ insertionSort(arr);
+ }
+
+ /**
+ * Finds the minimum value in the array.
+ *
+ * @param arr the array to find the minimum value in.
+ * @param the type of elements in the array, must be comparable.
+ * @return the minimum value in the array.
+ */
+ private > T findMin(final T[] arr) {
+ T min = arr[0];
+ for (int i = 1; i < arr.length; i++) {
+ if (arr[i].compareTo(min) < 0) {
+ min = arr[i];
+ }
+ }
+ return min;
+ }
+
+ /**
+ * Finds the index of the maximum value in the array.
+ *
+ * @param arr the array to find the maximum value index in.
+ * @param the type of elements in the array, must be comparable.
+ * @return the index of the maximum value in the array.
+ */
+ private > int findMaxIndex(final T[] arr) {
+ int maxIndex = 0;
+ for (int i = 1; i < arr.length; i++) {
+ if (arr[i].compareTo(arr[maxIndex]) > 0) {
+ maxIndex = i;
+ }
+ }
+ return maxIndex;
+ }
+
+ /**
+ * Classifies elements of the array into the classification array classificationArray.
+ *
+ * @param arr the array to be classified.
+ * @param classificationArray the classification array holding the count of elements in each class.
+ * @param c1 the normalization constant used to map the elements to the classification array.
+ * @param min the minimum value in the array.
+ * @param the type of elements in the array, must be comparable.
+ */
+ private > void classify(final T[] arr, final int[] classificationArray, final double c1, final T min) {
+ for (int i = 0; i < arr.length; i++) {
+ int k = (int) (c1 * arr[i].compareTo(min));
+ classificationArray[k]++;
+ }
+ }
+
+ /**
+ * Transforms the classification array classificationArray into the starting index array.
+ *
+ * @param classificationArray the classification array holding the count of elements in each class.
+ */
+ private void transform(final int[] classificationArray) {
+ for (int i = 1; i < classificationArray.length; i++) {
+ classificationArray[i] += classificationArray[i - 1];
+ }
+ }
+
+ /**
+ * Permutes the array into sorted order based on the classification array classificationArray.
+ *
+ * @param arr the array to be permuted.
+ * @param classificationArray the classification array holding the count of elements in each class.
+ * @param c1 the normalization constant used to map the elements to the classification array.
+ * @param min the minimum value in the array.
+ * @param n the length of the array.
+ * @param m the number of classes in the classification array.
+ * @param the type of elements in the array, must be comparable.
+ */
+ private > void permute(final T[] arr, final int[] classificationArray, final double c1, T min, int n, int m) {
+ int move = 0;
+ int j = 0;
+ int k = m - 1;
+ T flash;
+ while (move < n - 1) {
+ while (j > classificationArray[k] - 1) {
+ j++;
+ k = (int) (c1 * arr[j].compareTo(min));
+ }
+ flash = arr[j];
+ while (j != classificationArray[k]) {
+ k = (int) (c1 * flash.compareTo(min));
+ T temp = arr[classificationArray[k] - 1];
+ arr[classificationArray[k] - 1] = flash;
+ flash = temp;
+ classificationArray[k]--;
+ move++;
+ }
+ }
+ }
+
+ /**
+ * Sorts an array using the insertion sort algorithm.
+ *
+ * @param arr the array to be sorted.
+ * @param the type of elements to be sorted, must be comparable.
+ */
+ private > void insertionSort(final T[] arr) {
+ int n = arr.length;
+ for (int i = 1; i < n; i++) {
+ T key = arr[i];
+ int j = i - 1;
+ while (j >= 0 && arr[j].compareTo(key) > 0) {
+ arr[j + 1] = arr[j];
+ j--;
+ }
+ arr[j + 1] = key;
+ }
+ }
+}
diff --git a/src/test/java/com/thealgorithms/sorts/FlashSortTest.java b/src/test/java/com/thealgorithms/sorts/FlashSortTest.java
new file mode 100644
index 000000000..6b1a74403
--- /dev/null
+++ b/src/test/java/com/thealgorithms/sorts/FlashSortTest.java
@@ -0,0 +1,90 @@
+package com.thealgorithms.sorts;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import org.junit.jupiter.api.DynamicTest;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestFactory;
+import org.junit.jupiter.api.function.Executable;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+public class FlashSortTest extends SortingAlgorithmTest {
+ private final FlashSort flashSort = new FlashSort();
+
+ public FlashSort getFlashSort() {
+ return flashSort;
+ }
+
+ @Override
+ SortAlgorithm getSortAlgorithm() {
+ return getFlashSort();
+ }
+
+ @Test
+ public void testDefaultConstructor() {
+ double defaultRation = 0.45;
+ FlashSort sorter = new FlashSort();
+ assertEquals(defaultRation, sorter.getClassificationRatio());
+ }
+
+ @ParameterizedTest
+ @ValueSource(doubles = {0.1, 0.2, 0.5, 0.9})
+ public void testCustomConstructorValidRatio(double ratio) {
+ FlashSort sorter = new FlashSort(ratio);
+ assertEquals(ratio, sorter.getClassificationRatio());
+ }
+
+ @ParameterizedTest
+ @ValueSource(doubles = {0, 1, -0.1, 1.1})
+ public void testCustomConstructorInvalidRatio(double ratio) {
+ assertThrows(IllegalArgumentException.class, () -> new FlashSort(ratio));
+ }
+
+ @TestFactory
+ public Collection dynamicTestsForSorting() {
+ List dynamicTests = new ArrayList<>();
+ double[] ratios = {0.1, 0.2, 0.5, 0.9};
+
+ for (double ratio : ratios) {
+ FlashSort sorter = (FlashSort) getSortAlgorithm();
+ sorter.setClassificationRatio(ratio);
+ dynamicTests.addAll(createDynamicTestsForRatio(ratio));
+ }
+
+ return dynamicTests;
+ }
+
+ private Collection createDynamicTestsForRatio(double ratio) {
+ List dynamicTests = new ArrayList<>();
+ for (TestMethod testMethod : getTestMethodsFromSuperClass()) {
+ dynamicTests.add(DynamicTest.dynamicTest("Ratio: " + ratio + " - Test: " + testMethod.name(), testMethod.executable()));
+ }
+ return dynamicTests;
+ }
+
+ private List getTestMethodsFromSuperClass() {
+ List testMethods = new ArrayList<>();
+ Method[] methods = SortingAlgorithmTest.class.getDeclaredMethods();
+ for (Method method : methods) {
+ if (method.isAnnotationPresent(Test.class)) {
+ testMethods.add(new TestMethod(() -> {
+ try {
+ method.invoke(this);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }, method.getName()));
+ }
+ }
+ return testMethods;
+ }
+
+ record TestMethod(Executable executable, String name) {
+ }
+}