java-8java-streamstreams-api

Java 8 : Count the occurrence of digit 4 in the given int array


I am new to Java 8. I tried several ways to use the Streams API to solve the problem where we have been given an array of int = {48, 44, 4, 88, 84, 16, 12, 13 }. All I am trying to do is to find the occurrence of digit 4 in the whole array. I tried the following code -

int[] array = new int[] {48,44,4,88,84,16,12,13};

        List<Integer> list = new ArrayList<Integer>();
        
        for(int i:array) {
            list.add(i);
        }
        
        List<Integer> l = list.stream().filter(n->n%10)
                .map(n->n%10)
                        .collect(Collectors.toList());
        System.out.println(l);

Please advice the Streams API way to solve this.


Solution

  • First, you need to obtain a stream from the given array of int[]. You can do it either by using the static method IntStream.of, or with Arrays utility class and it's method stream().

    Both will give you an IntStream - a stream of int primitives. In order to collect stream elements into a list you need to convert it to a stream of objects. For that you can apply method boxed() on the stream pipeline and each int element will get wrapped with Integer object.

    In order to find all elements in the given list that contain a target digit (4), you can turn the target digit into a string and then apply a filter based on it.

    public static List<Integer> findOccurrencesOfDigit(List<Integer> source, 
                                                       int digit) {
        String target = String.valueOf(digit);
    
        return source.stream()
                        .filter(n -> String.valueOf(n).contains(target))
                        .collect(Collectors.toList());
    }
    

    main()

    public static void main(String[] args) {
        int[] nums = {48,44,4,88,84,16,12,13};
    
        System.out.println(findOccurrencesOfDigit(nums, 4));
    }
    

    Output

    [48, 44, 4, 84]
    

    Note: method filter() expects a Predicate (a function represented by a boolean condition, that takes an element and return true of false)

    Your attempt to create a predicate filter(n -> n % 10) is incorrect syntactically and logically. n % 10 doesn't produce a boolean value, it'll give the right most digit of n.

    If you want to use modulus (%) operator to create a predicate, you have to divide the element by 10 in a loop until it'll not become equal to 0. And check before every division weather remainder is equal to the target digit. It could be done like that:

    public static boolean containsDigit(int candidate, int digit) {
        boolean flag = false;
        while (candidate != 0) {
            if (candidate % 10 == digit) {
                flag = true;
                break;
            }
            candidate /= 10; // same as candidate = candidate / 10;
        }
        return flag;
    }
    

    You can utilize this method inside a lambda expression like that (note: it's a preferred way to avoid multiline lambda expressions by extracting them into separate methods)

    filter(n -> containsDigit(n, digit))