2016-06-14 3 views
3

Просто хочу, чтобы увидеть, JDK8 лямбда, как маленькая программа может быть, мой подход использует результат строитель: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()); 
}); 

Можно ли попытаться использовать предикат вместо этого? Я не мог придумать, как это сделать.

+2

https://gist.github.com/stuart-marks/9657079 –

+2

@StuartMarks шляпы от вас! –

ответ

7

Здесь находятся три решения.

Java 8 с Streams:

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

Java 8 с Eclipse Collections:

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

Java 8 с коллекциями Eclipse, используя Предикаты:

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); 

Update:

Как Затмения Коллекции 8.0 release, функциональные интерфейсы в Eclipse, Collections в настоящее время расширяют эквивалентные функциональные интерфейсы в Java 8. Это означает, что CaseFunction теперь может быть использован в качестве java.util.function.Function, что означает, что он будет работать с Stream.map(Function). В следующем примере используется CaseFunction с Stream<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); 

Update:

Как Затмения Коллекции 8.1 release, есть теперь поддержка примитивных функций дела. Теперь приведенный выше код можно записать следующим образом, удалив вызов boxed. IntCaseFunction реализует IntToObjectFunction, который распространяется на 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 например, передается в качестве параметра методу collect.

Примечание: Я коммиттер для Eclipse Collections.

+0

Ницца, спасибо! Вам нужно больше освежить поток Stream –

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); 
    }); 

Но на самом деле не становится меньше, :)

+0

делитBy3.negate(). И (делитBy5.negate()); Вы можете переписать это как; делитBy3.or (делитBy5) .negate(); – stelar7

0

Недавно я наблюдал за Кевлином Хенни, который говорил на разных языках по одному из своих разговоров. Это заставило меня задуматься о 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 
    } 
} 
0

Моя версия, используя формат.

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

Смежные вопросы