user10320581
user10320581

Reputation:

Number of occurrence IntStream Java

I want to define a method named countRepeats that takes in a List of digits 0 to 9 and returns the number of occurrences of adjacent repeated letters.

For example,

Test case 1: the array {0, 1, 2, 2, 1, 2, 2, 1, 3, 3, 1} has three occurrences of repeated digits

Test case 2: the array {0, 1, 1, 1, 1, 2} has one occurrence

Below are my codes:

List<Integer> intlist = new ArrayList<Integer>();
        int [] array = new int[]{};
        while(sc.hasNext()){
          intlist.add(sc.nextInt());
          array = intlist.stream().mapToInt(i->i).toArray();  
        }
        System.out.println("Number of occurrences: " + countRepeats(array));

public static long countRepeats(int [] array){
      return IntStream.range(0, array.length-1)
                    .filter(n -> array[n] > 0)
                    .filter(i -> (array[i] == array[i+1]))
                    .peek(System.out::println)
                    .count();
}

However, I failed to get the desired outcome for my test case 2. Anyone can enlighten me ?

Upvotes: 7

Views: 2971

Answers (2)

Tom Hawtin - tackline
Tom Hawtin - tackline

Reputation: 147154

Building on the original poster's solution, if we check whether a repeated pair is part of a larger sequence (and check end of array) then we can avoid boxing.

import java.util.*;
import java.util.stream.*;

interface CountRepeats {
    static void main(String[] args) {
        test(0, 1, 2, 2, 1, 2, 2, 1, 3, 3, 1);
        test(0, 1, 1, 1, 1, 2);
    }
    static void test(int... digits) {
        System.err.println(
            countRepeats(digits)+": "+Arrays.toString(digits)
        );
    }
    static long countRepeats(int[] array) { 
        return IntStream.range(0, array.length-1)
            .filter(i ->
                array[i] == array[i+1] && (
                   i+2 >= array.length ||
                   array[i] != array[i+2]
                )
             )
             .count();
    }
}

This isn't really streams' strong point.

(The line

                   i+2 >= array.length ||

really should be

                   i >= array.length-2 ||

to avoid an integer overflow causing an ArrayOutOfBoundsException. Old languages and their broken integers...)

Upvotes: 3

ernest_k
ernest_k

Reputation: 45309

This uses predicates that compare consecutive elements:

public static long countRepeats(int [] array){

      return IntStream.range(1, array.length)
            .filter(i -> i - 2 < 0 || array[i - 2] != array[i])
            .filter(i -> array[i] == array[i - 1])
            .count();
}

The first filter operation is intended to eliminate duplicates to force a count of 1 where an element is repeated more than 2 times in a row. The second one simply removes elements that aren't repeated consecutively.

Upvotes: 1

Related Questions