-1

How can I call a function to print a value while iterating over a range using an IntStream?

public static void fizzBuzz(int n) {

    // The below does not work as it expects a return value.
    // Is there a different method that I could use to perform this?
    IntStream.range(1, n).map(n -> print(n));
}

private static void print(int n){
    boolean isDivisibleBy3 = n % 3 == 0;
    boolean isDivisibleBy5 = n % 5 == 0;
    
    if(isDivisibleBy3 && isDivisibleBy5){
        System.out.println("FizzBuzz");
    } else if (isDivisibleBy3){
        System.out.println("Fizz");
    } else if (isDivisibleBy5){
        System.out.println("Buzz");
    } else {
        System.out.println(n);
    }
}
Mureinik
  • 297,002
  • 52
  • 306
  • 350
Punter Vicky
  • 15,954
  • 56
  • 188
  • 315
  • 3
    Why you are using map here? Use forEach – Lemmy Dec 20 '20 at 22:35
  • 3
    You can use `peek()` _to support debugging, where you want to see the elements as they flow past a certain point in a pipeline_ or use the `forEach()` operator to consume an each element from the stream (not return value compared to `map()`). – Glains Dec 20 '20 at 22:40
  • Sorry , map was just intended to show as an example - just wanted to understand if there is a functional interface that accepts a value could be used as part of foreach. – Punter Vicky Dec 21 '20 at 04:40

4 Answers4

1

The map() operation needs a non-void function as its input so this function can be applied to every element in your stream and replace them. Use forEach() instead. It can apply a void function on your elements.

Also do not use n within your lambda expression. It is already declared and cannot be overwritten.

public static void fizzBuzz(int n) {
    IntStream.range(1, n).forEach(x -> print(x));
}
1

map is used when you want to convert one value to another. Since print doesn't return anything (its return type is void), you can't use map. You could use forEach instead though:

IntStream.range(1, n).forEach(n -> print(n));
Mureinik
  • 297,002
  • 52
  • 306
  • 350
1

As others have noted, your current approach does not lend itself to map because your function is void. You could map int to String though. That method might look like,

private static String mapFizzBuzz(int n) {
    boolean isDivisibleBy3 = n % 3 == 0;
    boolean isDivisibleBy5 = n % 5 == 0;

    if (isDivisibleBy3 && isDivisibleBy5) {
        return "FizzBuzz";
    } else if (isDivisibleBy3) {
        return "Fizz";
    } else if (isDivisibleBy5) {
        return "Buzz";
    }
    return Integer.toString(n);
}

And then your current approach would work, if you further printed with a forEach. Like,

IntStream.range(1, n).mapToObj(x -> mapFizzBuzz(x)).forEach(System.out::println);
Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
1

Perhaps this is what you wanted. Have the method return the string. Then use IntStream to iterate thru the numbers. These are then passed on to the method which maps an int to the returned value which is a String. Then you simply print that value.

public class FizzBuzzStream {
    
    public static void main(String[] args) {
        
        int n = 20;
        
        IntStream.range(1, n).mapToObj(FizzBuzzStream::eval)
                .forEach(System.out::println); 
        
    }
    
    private static String eval(int n) {
        boolean isDivisibleBy3 = n % 3 == 0;
        boolean isDivisibleBy5 = n % 5 == 0;
        
        if (isDivisibleBy3 && isDivisibleBy5) {
            return "FizzBuzz";
        }
        if (isDivisibleBy3) {
            return "Fizz";
        }
        if (isDivisibleBy5) {
            return "Buzz";
        }
        return Integer.toString(n);
    }
    
}

Prints

1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
16
17
Fizz
19
WJS
  • 36,363
  • 4
  • 24
  • 39