Intro
A sort is called super linearithmic if its running time is \$\omega(N \log N)\$. For example, \$f(N) = \omega(g(N))\$ means that \$f(N)\$ grows "faster" than \$g(N)\$. In this post, I will compare four (4) such algorithms against java.util.Arrays.sort:
Code
io.github.coderodde.util.Arrays.java:
package io.github.coderodde.util;
/**
 * This class contains some comparison sorts.
 * 
 * @author Rodion "rodde" Efremov
 * @version 1.0.0 (Oct 31, 2025)
 * @since 1.0.0 (Oct 31, 2025)
 */
public final class Arrays {
    private static final int[] SHELL_SORT_GAPS =
    { 701, 301, 132, 57, 23, 10, 4, 1 };
    
    private Arrays() {
        
    }
    
    public static <E extends Comparable<? super E>> 
        void insertionSort(E[] array) {
        for (int i = 1; i < array.length; ++i) {
            E x = array[i];
            int j = i;
            
            while (j > 0 && array[j - 1].compareTo(x) > 0) {
                array[j] = array[j - 1];
                --j;
            }
            
            array[j] = x;
        }
    }
        
    public static <E extends Comparable<? super E>> void bubbleSort(E[] array) {
        boolean swapped;
        int n = array.length;
        
        do {
            swapped = false;
            
            for (int i = 1; i < n; ++i) {
                if (array[i - 1].compareTo(array[i]) > 0) {
                    swap(array, i - 1, i);
                    swapped = true;
                }
            }
            
            --n;
        } while (swapped);
    }
    
    public static <E extends Comparable<? super E>> void combSort(E[] array) {
        int gap = array.length;
        float shrinkFactor = 1.3f;
        boolean sorted = false;
        
        while (!sorted) {
            gap = (int)(gap / shrinkFactor);
            
            if (gap <= 1) {
                gap = 1;
                sorted = true;
            } else if (gap == 9 || gap == 10) {
                gap = 11;
            }
            
            for (int i = 0; i + gap < array.length; ++i ){
                if (array[i].compareTo(array[i + gap]) > 0) {
                    swap(array, i, i + gap);
                    sorted = false;
                }
            }
        }
    }
    
    public static <E extends Comparable<? super E>> void shellSort(E[] array) {
        for (int gap : SHELL_SORT_GAPS) {
            for (int i = gap; i < array.length; ++i) {
                E tmp = array[i];
                int j = i;
                
                for (; 
                    (j >= gap) && (array[j - gap].compareTo(tmp) > 0); 
                     j -= gap) {
                 
                    array[j] = array[j - gap];
                }
                
                array[j] = tmp;
            }
        }
    }
    
    private static <E> void swap(E[] array, int i, int j) {
        E tmp = array[i];
        array[i] = array[j];
        array[j] = tmp;
    }
}
io.github.coderodde.util.demo.Demo.java:
package io.github.coderodde.util.demo;
import io.github.coderodde.util.Arrays;
import java.util.Random;
public final class Demo {
    private static final int ARRAY_LENGTH = 50_000;
    
    public static void main(String[] args) {
        Integer[] arr1 = getRandomArray();
        Integer[] arr2 = arr1.clone();
        Integer[] arr3 = arr1.clone();
        Integer[] arr4 = arr1.clone();
        Integer[] arr5 = arr1.clone();
        
        long ta = System.currentTimeMillis();
        Arrays.insertionSort(arr1);
        long tb = System.currentTimeMillis();
        
        System.out.println(
                "Insertion sort in: " + (tb - ta) + " milliseconds.");
        
        ta = System.currentTimeMillis();
        Arrays.bubbleSort(arr2);
        tb = System.currentTimeMillis();
        
        System.out.println(
                "Bubble sort in:    " + (tb - ta) + " milliseconds.");
        
        ta = System.currentTimeMillis();
        Arrays.combSort(arr3);
        tb = System.currentTimeMillis();
        
        System.out.println(
                "Comb sort in:      " + (tb - ta) + " milliseconds.");
        
        ta = System.currentTimeMillis();
        Arrays.combSort(arr4);
        tb = System.currentTimeMillis();
        
        System.out.println(
                "Shell sort in:     " + (tb - ta) + " milliseconds.");
        
        ta = System.currentTimeMillis();
        java.util.Arrays.sort(arr5);
        tb = System.currentTimeMillis();
        
        System.out.println(
                "java.util.Arrays.sort in: " 
                        + (tb - ta)
                        + " milliseconds.");
        
        boolean agree = java.util.Arrays.equals(arr1, arr2) &&
                        java.util.Arrays.equals(arr2, arr3) &&
                        java.util.Arrays.equals(arr3, arr4) &&
                        java.util.Arrays.equals(arr4, arr5);
        
        System.out.println("Sorts agree: " + agree);
    }
    
    private static Integer[] getRandomArray() {
        Random random = new Random(13L);
        Integer[] array = new Integer[ARRAY_LENGTH];
        
        for (int i = 0; i < array.length; ++i) {
            array[i] = random.nextInt();
        }
        
        return array;
    }
}
Typical output
Insertion sort in: 4090 milliseconds.
Bubble sort in:    12530 milliseconds.
Comb sort in:      37 milliseconds.
Shell sort in:     28 milliseconds.
java.util.Arrays.sort in: 45 milliseconds.
Sorts agree: true
Critique request
As always, I am eager to receive any constructive critique on my work.