FizzBu​​zz使用JDK8 Lambda

时间:2016-06-14 14:18:21

标签: lambda java-8 fizzbuzz

只想通过JDK8看看lambda程序有多小,我的方法是使用结果构建器:

IntStream.rangeClosed(0 , 100).forEach(i ->{
        StringBuffer bfr= new StringBuffer();
        if(i % 3 == 0 )
            bfr.append("Fizz");
        if(i % 5 == 0 )
            bfr.append("Buzz");
        if(i % 3 != 0 && i % 5 != 0 )
            bfr.append(i);

        System.out.println(bfr.toString());
});

任何人都可以尝试使用谓词吗?我想不出办法做到这一点。

10 个答案:

答案 0 :(得分:9)

以下是三种解决方案。

Java 8 with Streams:

IntStream.rangeClosed(0, 100).mapToObj(
        i -> i % 3 == 0 ?
                (i % 5 == 0 ? "FizzBuzz" : "Fizz") :
                (i % 5 == 0 ? "Buzz" : i))
        .forEach(System.out::println);

带有Eclipse Collections的Java 8:

IntInterval.zeroTo(100).collect(
        i -> i % 3 == 0 ?
                (i % 5 == 0 ? "FizzBuzz" : "Fizz") :
                (i % 5 == 0 ? "Buzz" : i))
        .each(System.out::println);

Java 8 with Eclipse Collections using Predicates:

Interval.zeroTo(100).collect(
        new CaseFunction<Integer, String>(Object::toString)
            .addCase(i -> i % 15 == 0, e -> "FizzBuzz")
            .addCase(i -> i % 3 == 0, e -> "Fizz")
            .addCase(i -> i % 5 == 0, e -> "Buzz"))
        .each(System.out::println);

<强>更新

从Eclipse Collections 8.0 release开始,Eclipse Collections中的功能接口现在扩展了Java 8中的等效功能接口。这意味着CaseFunction现在可以用作java.util.function.Function,这意味着它将与Stream.map(Function)一起使用。以下示例使用CaseFunctionStream<Integer>

IntStream.rangeClosed(0, 100).boxed().map(
        new CaseFunction<Integer, String>(Object::toString)
                .addCase(i -> i % 15 == 0, e -> "FizzBuzz")
                .addCase(i -> i % 3 == 0, e -> "Fizz")
                .addCase(i -> i % 5 == 0, e -> "Buzz"))
        .forEach(System.out::println);

<强>更新

从Eclipse集合8.1 release开始,现在支持原始案例函数。现在可以按如下方式编写上面的代码,删除对boxed的调用。 IntCaseFunction实现了扩展IntToObjectFunction的{​​{1}}。

java.util.function.IntFunction

IntStream.rangeClosed(0, 100).mapToObj( new IntCaseFunction<>(Integer::toString) .addCase(i -> i % 15 == 0, e -> "FizzBuzz") .addCase(i -> i % 3 == 0, e -> "Fizz") .addCase(i -> i % 5 == 0, e -> "Buzz")) .forEach(System.out::println); 也适用于IntCaseFunction示例,作为参数传递给IntInterval方法。

注意:我是Eclipse Collections的提交者。

答案 1 :(得分:2)

我的版本使用格式。

IntStream.rangeClosed(1, 100).forEach(
    i -> System.out.format("%s%s%n",
                           (i % 3 == 0 ? "Fizz": ""),
                           (i % 5 == 0 ? "Buzz": (i % 3 == 0 ? "" : i))
         )
);

答案 2 :(得分:1)

包含无限流的版本。起源于Haskell。常见于Kevlin Henney演讲

public static void main(String[] args) {

    // creates an infinite stream with "Fizz" on every 3rd position
    Stream<String> fizzes = Stream.generate(() -> new String[] {"","","Fizz"}).flatMap(arr -> Arrays.stream(arr));
    // creates an infinite stream with "Buzz" on every 5th position 
    Iterator<String> buzzes = Stream.generate(() -> new String[] {"","","","","Buzz"}).flatMap(arr -> Arrays.stream(arr)).iterator();
    // Infinite number stream as String
    Iterator<String> integers = IntStream.iterate(1, x -> x + 1).mapToObj(value -> Integer.valueOf(value).toString()).iterator();

    // concatenates fizzes with buzzes and return the max string from number or the concatenation
    // FizzBuzz > Fizz > Buzz > 'any number as string' > ""
    String[] array = fizzes.limit(100).map(fizz -> max(integers.next(), fizz+buzzes.next())).toArray(value -> new String[value]);

    System.out.println(Arrays.toString(array));
}

public static String max(String val1, String val2) {
    return val1.compareTo(val2) >= 0 ? val1 : val2;
}

更准确一点:

public class FizzBuzz {

    public static void main(String[] args) {
        // creates an infinite stream with "Fizz" on every 3rd position
        Stream<String> fizzes = Stream.generate(() -> new String[] {"","","Fizz"}).flatMap(arr -> Arrays.stream(arr));
        // creates an infinite stream with "Buzz" on every 5th position
        Iterator<String> buzzes = Stream.generate(() -> new String[] {"","","","","Buzz"}).flatMap(arr -> Arrays.stream(arr)).iterator();
        // Concatenates fizzes with buzzes
        Iterator<String> words = fizzes.map(fizz -> fizz+buzzes.next()).iterator();
        // Infinite number stream as String
        Stream<String> numbers = IntStream.iterate(1, x -> x + 1).mapToObj(Integer::toString);
        // Choice operation word or number
        BinaryOperator<String> choice1 = FizzBuzz::max;
        BinaryOperator<String> choice2 = FizzBuzz::emptyAsNumberOrWord;

        numbers.limit(100).map(number -> choice1.apply(number, words.next())).forEach(System.out::println);
    }

    public static String max(String number, String word) {
        return number.compareTo(word) >= 0 ? number : word;
    }

    public static String emptyAsNumberOrWord(String number, String word) {
        return word.isEmpty() ? number : word;
    }
}

答案 3 :(得分:0)

您的代码可以用谓词重写:

        IntPredicate dividesBy3 = i -> i % 3 == 0;
        IntPredicate dividesBy5 = i -> i % 5 == 0;
        IntPredicate doesntDivide = dividesBy3.negate().and(dividesBy5.negate());

        IntStream.rangeClosed(0, 100).forEach(i -> {
            StringBuffer bfr = new StringBuffer();

            if (dividesBy3.test(i)) bfr.append("Fizz");
            if (dividesBy5.test(i)) bfr.append("Buzz");
            if (doesntDivide.test(i)) bfr.append(i);

            System.out.println(bfr);
    });

但实际上并不会变小:)

答案 4 :(得分:0)

最近,我正在观看Kevlin Henney,他在其中一个演讲中惊慌失措。它让我想到了Java 8,并没有提供的解决方案对我来说很优雅。读取链式三元运算符非常困难。这就是我想出的:

public class MyApproach {
    private java.util.function.IntPredicate divBy(int number) {
        return i -> i % number == 0;
    }

    public String fizzBuzz(int number) {
        String result = "";
        result += divBy(3).test(number) ? "Fizz" : "";
        result += divBy(5).test(number) ? "Buzz" : "";
        return (result).isEmpty() ? String.valueOf(number) : result;
    }

    public static void main(String[] args) {
        MyApproach myApproach = new MyApproach();
        int startInclusive = Integer.parseInt(args[0]);
        int endInclusive = Integer.parseInt(args[1]);

        IntStream.rangeClosed(startInclusive, endInclusive)
            .mapToObj(myApproach::fizzBuzz)
            .forEach(System.out::println);
    }
}

这样我们可以投入一些测试:

class FizzBuzzTest extends Specification {
    def "parametrized test for fizzBuzz method" () {
        given:
        def myApproach = new MyApproach()

        expect:
        result == myApproach.fizzBuzz(num)

        where:
        result     | num
        "Fizz"     | 21
        "Fizz"     | 123
        "Buzz"     | 50
        "Buzz"     | 250
        "FizzBuzz" | 150
        "13"       | 13
    }
}

答案 5 :(得分:0)

  

Stream API实现:

import java.util.stream.Stream;

public class FizzBuzz {
    public static void main(String[] args) {

        final String FIZZ = "Fizz";
        final String BUZZ = "Buzz";
        Stream.iterate(1, n -> n + 1)
                .limit(100)
                .forEachOrdered(item -> {
                    if (item % 3 == 0 && item % 5 == 0) {
                        System.out.println(FIZZ + " " + BUZZ);
                        return;
                    } else if (item % 3 == 0) {
                        System.out.println(FIZZ);
                        return;
                    } else if (item % 5 == 0) {
                        System.out.println(BUZZ);
                        return;
                    }

                    System.out.println(item);
                });
    }
}

答案 6 :(得分:0)

             IntStream.rangeClosed(1, 100)
                      .mapToObj(x -> x % 15 == 0 ? "FizzBuzz" : x % 5 == 0 ? "Buzz" : x % 3 == 0 ? "Fizz" : x)
                      .forEach(System.out::println);`

答案 7 :(得分:0)

public class FizzBuzz {

    private static final int RANGE_START = 1;
    private static final int RANGE_END = 100;

    public static void main(String[] args) {
        IntStream.rangeClosed(RANGE_START, RANGE_END)
                .mapToObj(FizzBuzz::FizzBuzzMapper)
                .forEach(System.out::println);
    }

    private static String FizzBuzzMapper(final int number) {
        return PAIR_LIST.stream()
                .filter(p -> p.getKey().test(number))
                .map(Pair::getValue)
                .findFirst()
                .orElse(String.valueOf(number));
    }

    private static final List<Pair<Predicate<Integer>, String>> PAIR_LIST = List.of(
            Pair.of(i -> integerPredicate(15).test(i), "FizzBuzz"),
            Pair.of(i -> integerPredicate(5).test(i), "Buzz"),
            Pair.of(i -> integerPredicate(3).test(i), "Fizz")
    );

    private static Predicate<Integer> integerPredicate(final int divisor) {
        return i -> i % divisor == 0;
    }
}

答案 8 :(得分:0)

public class FizzBuzz {

    public static void main(String[] args) {
        IntStream.rangeClosed(1, 100).forEach(FizzBuzz::check);
    }

    public static void check(int n) {
        System.out.println((n % 3 == 0 ? "Fizz" : "") + (n % 5 == 0 ? "Buzz" : ""));
    }

}

答案 9 :(得分:0)

我的函数式方法版本,当然不是很短。

它既不使用else,也不使用三元运算符。但是它可以通过向 fizzBu​​zzers 地图添加新条件来扩展。

public class FizzBuzz {

    public static void main(String[] args) {
        final Map<Integer, String> fizzBuzzers = new HashMap<>();
        fizzBuzzers.put(3,  "Fizz");
        fizzBuzzers.put(5,  "Buzz");
        fizzBuzzers.put(8,  "Bingo");
        fizzBuzzers.put(17, "Dingo");
        
        IntStream.rangeClosed(1, 100)
            .forEach(i -> System.out.println(fizzBuzz(i, fizzBuzzers)));

    }

    private static String fizzBuzz(int i, Map<Integer, String> fizzBuzzers) {
        final List<Map.Entry<Integer, String>> multiBuzz = fizzBuzzers.entrySet().stream()
                .filter(entry -> i % entry.getKey() == 0)
                .collect(Collectors.toList());
        
        if (!multiBuzz.isEmpty()) {
            return multiBuzz.stream()
                    .map(Map.Entry::getValue)
                    .collect(Collectors.joining());
        }
        return String.valueOf(i);
    }