Numbers, pairs, and a difference Problem statement:

Write a function which returns the total number of combinations whose difference is k.
For example, 4 8 15 16 23 42 and the difference 7 has 2 pairs, 8, 15 and 16, 23.


I liked the Finding number of number pairs with given difference question so much (despite its brokenness) that not only did I review it, but I also decided to write up my own implementation of it (following the approach I described in my review). I was intrigued by this comment:

You need the handle the case of elements being equal too, though. That means an array with 2x duplicates such as 4 4 8 8 15 15 16 16 23 23 42 42 should return 4x the number of combinations as without duplicates. - JS1

When a pair is found, I count how many numbers are matching at lowIndex and highIndex respectively, and then calculating how many pairs there are.
NumberPairsDiff.java
public class NumberPairsDiff {

    public static int pairsWithDifference(int[] input, long difference) {
        int[] sorted = Arrays.copyOf(input, input.length);
        Arrays.sort(sorted);

        int pairsFound = 0;

        int lowIndex = 0;
        int highIndex = 0;

        while (lowIndex &lt; sorted.length &amp;&amp; highIndex &lt; sorted.length) {
            long current = (long) sorted[highIndex] - sorted[lowIndex];
            if (current &lt; difference) {
                highIndex++;
            } else if (current &gt; difference) {
                lowIndex++;
            } else {
                // Find out how many values are equal at `highIndex`
                int highMatching = findEqual(sorted, highIndex);
                highIndex += highMatching;

                if (difference == 0) {
                    // 1+2+3+4+5+...+n = 0.5x^2 + 0.5x
                    int add = (int)(0.5f * highMatching * highMatching + 0.5 * highMatching);
                    pairsFound += add;
                    lowIndex += highMatching;
                } else {
                    // Find out how many values are equal at `lowIndex`
                    int lowMatching = findEqual(sorted, lowIndex);
                    lowIndex += lowMatching;
                    pairsFound += lowMatching * highMatching;
                }
            }
        }

        return pairsFound;
    }

    private static int findEqual(int[] sorted, int index) {
        int matching = 1;
        while (index &lt; sorted.length - 1 &amp;&amp; sorted[index] == sorted[index + 1]) {
            index++;
            matching++;
        }
        return matching;
    }

}

Obligatory parametrized unit test, NumberPairsDiffTest.java:
@RunWith(Parameterized.class)
public class NumberPairsDiffTest {

    @Parameterized.Parameters
    public static Collection&lt;Object[]&gt; data() {
        return Arrays.asList(new Object[][]{
                {new int[]{ 4, 4, 8, 8, 15, 15, 16, 16, 23, 23, 42, 42 }, 4, 4},
                {new int[]{ 4, 4, 8, 8, 15, 15, 16, 16, 23, 23, 42, 42 }, 7, 8},
                {new int[]{ 4, 4, 8, 8, 15, 15, 16, 16, 23, 23, 42, 42 }, 0, 18},
                {new int[]{ 1 }, 0, 1},
                {new int[]{ 2, 2 }, 0, 3},
                {new int[]{ 3, 3, 3 }, 0, 6},
                {new int[]{ 4, 4, 4, 4 }, 0, 10},
                {new int[]{ 2, 2, 4 }, 0, 4},
                {new int[]{ 1, 4, 7, 11, 14, 17 }, -3, 4},
                {new int[]{ 1, 4, 7, 11, 14, 17 }, 5, 0},
                {new int[]{ Integer.MIN_VALUE, Integer.MAX_VALUE }, (long)(Integer.MAX_VALUE) * 2L + 1L, 1},
        });
    }

    @Parameterized.Parameter(value = 0)
    public int[] input;

    @Parameterized.Parameter(value = 1)
    public long diff;

    @Parameterized.Parameter(value = 2)
    public int expected;

    @Test
    public void test() {
        String string = String.format(&quot;Array %s with diff %d&quot;, Arrays.toString(input), diff);
        assertEquals(string, expected, NumberPairsDiff.pairsWithDifference(input, diff));
    }

}

Primary concerns

Readable, understandable code?
Missed edge-cases?
Better approaches?
The basic algorithm you use is logical, and well presented. The general style is standard, and I see no issues there. I believe the algorithm can be changed slightly to make the comparison code simpler, but the performance will still be comparable.
I looked for edge cases I would have expected, specifically relating to large differences, but you appear to have covered that well. Unfortunately, your pair-counts for diff == 0 are all off. For example, your third test case:

{new int[]{ 4, 4, 8, 8, 15, 15, 16, 16, 23, 23, 42, 42 }, 0, 18},


should have a count of 6, and not 18. There are only 6 pairs with difference 0. The pair at index 0, and 1, is the same pair as index 1 and 0, so you can't double (or, for some reason triple) count them.
This also applies to cases like: {new int[]{ 1 }, 0, 1},.... you have an input array of just a single element... but you have 1 pair with diff 0? Really???
There is one small performance improvement related to how far you need to iterate in the loop - you have: while (lowIndex &lt; sorted.length &amp;&amp; highIndex &lt; sorted.length) { but that can be just while (highIndex &lt; sorted.length) { since lowIndex is always less than or equal to highIndex. This is particularly confusing if your input difference is negative.
For some reason, and I can't explain it, I prefer left and right for those variable names too... lowIndex seems not-quite-right, but I understand it anyway. Just a niggly thing.
Additionally, there are a few places where I would do things in a more Java-8 way. Let's deal with the smaller items first...
Small things
Consider this code:

int[] sorted = Arrays.copyOf(input, input.length);
Arrays.sort(sorted);


I would (now) use the following:
int[] sorted = IntStream.of(input).sorted().toArray();

As for negative difference input values, I would just handle that as an up-front special condition. The count of pairs with a negative difference will be the same as the count with a positive difference and the same magnitude. Just convert negative difference to positive, and handle the Long.MIN_VALUE special case.
Algorithm
I would alter the algorithm a little. I would have a simple scan of the data to count value duplicates, and store that count in a separate array. With that data structure, the search for duplicates later is much easier. Consider this:
    if (input.length &lt;= 1) {
        return 0;
    }
    
    int[] sorted = IntStream.of(input).sorted().toArray();
    
    // remove and count duplicate values
    int[] counts = new int[sorted.length];
    int size = 0;
    for (int i = 0; i &lt; sorted.length; i++) {
        if (sorted[i] != sorted[size]) {
            sorted[++size] = sorted[i];
        }
        counts[size]++;
    }
    size++;

The above code ends up with a simpler data set to navigate. Unfortunatley, it makes the case where diff==0 a little more complicated... you need to use factorials for that, and not simple products. (Edit, I extracted that logic completely)....
Still, I put the whole method together as:
import java.util.stream.IntStream;

public class NumberPairsDiff {

    public static int pairsWithDifference(int[] input, long difference) {
        
        if (input.length &lt;= 1) {
            return 0;
        }
        
        if (difference == Long.MIN_VALUE) {
            return 0; 
        }
        
        if (difference &lt; 0) {
            difference = -difference;
        }
        
        int[] sorted = IntStream.of(input).sorted().toArray();
        
        // remove and count duplicate values
        int[] counts = new int[sorted.length];
        int size = 0;
        for (int i = 0; i &lt; sorted.length; i++) {
            if (sorted[i] != sorted[size]) {
                sorted[++size] = sorted[i];
            }
            counts[size]++;
        }
        size++;

        if (difference == 0) {
            int pairsFound = 0;
            for (int i = 0; i &lt; size; i++) {
                pairsFound += factorial(counts[i] - 1);
            }
            return pairsFound;
        }

        int left = 0;
        int right = 0;
        int pairsFound = 0;
        
        while (right &lt; size) {
            long diff = (long)sorted[right] - (long)sorted[left];
            if (diff &lt; difference) {
                right++;
            } else if (diff &gt; difference) {
                left++;
            } else {
                pairsFound += counts[left++] * counts[right++];
            }
        }
        return pairsFound;

    }

    private static int factorial(int n) {
        int f = n;
        while (--n &gt; 1) {
            f *= n;
        }
        return f;
    }

}

The above function fails a bunch of your test cases because it produces the correct results ;-)