Counting combinations of consecutive symbols in Java Let's assume we have an array that contains the following elements:

-1, 0, 0, 1, 0, -1, 0, -1, 1


I would like to count the combinations of consecutive elements such that

-1,0 &amp; 0,0 &amp; 0,1 &amp; 1,0 &amp; 0,-1 &amp; -1,0 &amp; 0,-1 &amp; -1&amp;1


In this case: 

The count of -1,0 = 2
The count of 0,1 = 1
The count of 1,0 = 1
and so on


I implemented the following:

List&lt;Double&gt; sixProbabilites = new ArrayList&lt;Double&gt;();

        int count_neg10 = 0, count_neg11 = 0, count_10 = 0, count_1neg1 = 0, count_0neg1 = 0, count_01 = 0;

        for(int i=0; i&lt;slopeChanges.size(); i++) {
            if(i+1 != slopeChanges.size()) {
                if((slopeChanges.get(i) == -1) &amp;&amp; (slopeChanges.get(i) == 0)) {count_neg10++;}
                else if((slopeChanges.get(i) == -1) &amp;&amp; (slopeChanges.get(i+1) == 1)) {count_neg11++;}
                else if((slopeChanges.get(i) == 1) &amp;&amp; (slopeChanges.get(i+1) == 0)) {count_10++;}
                else if((slopeChanges.get(i) == 1) &amp;&amp; (slopeChanges.get(i+1) == -1)) {count_1neg1++;}
                else if((slopeChanges.get(i) == 0) &amp;&amp; (slopeChanges.get(i+1) == -1)) {count_0neg1++;}
                else if((slopeChanges.get(i) == 0) &amp;&amp; (slopeChanges.get(i+1) == 1)) {count_01++;}
            }
        }


There is no problem with the code but I am just wondering if there is a way to enhance the code especially the if statement. Is there any way to reduce the code size to few lines?
I would build a Map with a custom keying function and just iterate over the length (minus one) of the array of values.

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

public class GroupFrenquency {
    public static &lt;T&gt; Map&lt;String, Integer&gt; groupFrenquencies(T[] arr, Function&lt;List&lt;T&gt;, String&gt; keyFn) {
        Map&lt;String, Integer&gt; frequency = new HashMap&lt;&gt;();
        for (int i = 0; i &lt; arr.length - 1; i++) {
            String key = keyFn.apply(Arrays.asList(arr[i], arr[i + 1]));
            frequency.put(key, frequency.containsKey(key) ? frequency.get(key) + 1 : 1);
        }
        return frequency;
    }

    public static void main(String[] args) {
        Integer[] sequence = { -1, 0, 0, 1, 0, -1, 0, -1, 1 };
        Function&lt;List&lt;Integer&gt;, String&gt; keyFn = (items) -&gt; String.format("%s,%s", items.get(0), items.get(1));

        System.out.println(groupFrenquencies(sequence, keyFn).entrySet().stream()
                .map(e -&gt; String.format("The count of %-4s = %d", e.getKey(), e.getValue()))
                .collect(Collectors.joining(System.lineSeparator())));
    }
}


Output

The count of 0,0  = 1
The count of 0,1  = 1
The count of 1,0  = 1
The count of 0,-1 = 2
The count of -1,1 = 1
The count of -1,0 = 2




Using reflection, you can create a copy of the array instead of creating an entire list object, when creating the key. The only downside is that you need to pass in the class type of the array, because you cannot initialize a generic array without knowing the type.

import java.lang.reflect.Array;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

public class GroupFrenquency {
    public static &lt;T&gt; Map&lt;String, Integer&gt; groupFrenquencies(Class&lt;T&gt; type, T[] arr, Function&lt;T[], String&gt; keyFn) {
        Map&lt;String, Integer&gt; frequency = new HashMap&lt;&gt;();
        for (int i = 0; i &lt; arr.length - 1; i++) {
            String key = keyFn.apply(copyArray(type, arr, i, 2));
            frequency.put(key, frequency.containsKey(key) ? frequency.get(key) + 1 : 1);
        }
        return frequency;
    }

    @SuppressWarnings("unchecked")
    private static &lt;T&gt; T[] copyArray(Class&lt;T&gt; type, T[] source, int startPos, int length) {
        T[] copy = (T[]) Array.newInstance(type, length);
        System.arraycopy(source, startPos, copy, 0, length);
        return copy;
    }

    public static void main(String[] args) {
        Class&lt;Integer&gt; type = Integer.class;
        Integer[] sequence = { -1, 0, 0, 1, 0, -1, 0, -1, 1 };
        Function&lt;Integer[], String&gt; keyFn = (items) -&gt; String.format("%s,%s", items[0], items[1]);

        System.out.println(groupFrenquencies(type, sequence, keyFn).entrySet().stream()
                .map(e -&gt; String.format("The count of %-4s = %d", e.getKey(), e.getValue()))
                .collect(Collectors.joining(System.lineSeparator())));
    }
}