只想通过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());
});
任何人都可以尝试使用谓词吗?我想不出办法做到这一点。
答案 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)
一起使用。以下示例使用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);
<强>更新强>
从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,也不使用三元运算符。但是它可以通过向 fizzBuzzers 地图添加新条件来扩展。
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);
}