私は最初の千の素数を合計したいと思います。私はこれを試してみると...get()をオプションの?
IntelliJはisPresent()をチェックするように提案しますが、それも可能ですか?
別のオプションは.orElse(-1)を使用することですが、何も返さないようにします。私は例外を投げるべきですか?
私は最初の千の素数を合計したいと思います。私はこれを試してみると...get()をオプションの?
IntelliJはisPresent()をチェックするように提案しますが、それも可能ですか?
別のオプションは.orElse(-1)を使用することですが、何も返さないようにします。私は例外を投げるべきですか?
空の入力を持つ特定のテストでは、完全に有効です。ゼロの合計はゼロです。したがって、.reduce(Integer::sum).orElse(0)
を使用するか、.reduce(0, Integer::sum)
のようなオプションを完全に取り除くことができます。入力が空の場合は、もちろん0を取得します
getFoos().stream().mapToInt(x -> x).sum();
この方法:
はまた、あなたは原始的なストリームに変換し、直接sum()
方法を使用することができることに注意してください。
ストリームを引数に減らすと、ストリームが空になり、このケースを処理するためにOptional
が導入される可能性があります。アイデンティティ引数を受け入れるもう1つのreduce()メソッドがあり、空のストリームの場合はIDが返されるため、Optional
が返されます。
しかし、私はあなたの仕事に焦点を当てて、プライムと非プライムの数値を分割し、最初のn個の数値を合計するカスタムコレクタを使用することをお勧めします。
いくつかの時間前、私はプライムと非素数のコレクタを実装し、実装には、次のようになります。
public class PrimeNumberCollector implements Collector<Integer,
Map<Boolean, List<Integer>>,
Map<Boolean, List<Integer>>> {
@Override
public Supplier<Map<Boolean, List<Integer>>> supplier() {
return() -> new HashMap<Boolean, List<Integer>>() {{
put(Boolean.TRUE, new ArrayList<>());
put(Boolean.FALSE, new ArrayList<>());
}};
}
@Override
public BiConsumer<Map<Boolean, List<Integer>>, Integer> accumulator() {
return (Map<Boolean, List<Integer>> acc, Integer candidate) -> acc.get(isPrime(candidate))
.add(candidate);
}
@Override
public BinaryOperator<Map<Boolean, List<Integer>>> combiner() {
return (Map<Boolean, List<Integer>> firstMap, Map<Boolean, List<Integer>> secondMap) -> {
firstMap.get(Boolean.TRUE).addAll(secondMap.get(Boolean.TRUE));
firstMap.get(Boolean.FALSE).addAll(secondMap.get(Boolean.FALSE));
return firstMap;
};
}
@Override
public Function<Map<Boolean, List<Integer>>, Map<Boolean, List<Integer>>> finisher() {
return Function.identity();
}
@Override
public Set<Characteristics> characteristics() {
return Collections.unmodifiableSet(EnumSet.of(Characteristics.IDENTITY_FINISH));
}
private static boolean isPrime(final int candidate) {
return IntStream.rangeClosed(2, (int) Math.sqrt(candidate)).noneMatch(i -> candidate % i == 0);
}
}
とその使用方法:その後、
@Test
public void collectingPrimeNumbersWithCustomCollector() {
Map<Boolean, List<Integer>> primesNumbersMap = IntStream.rangeClosed(1, 1_000_000)
.boxed()
.collect(CustomCollectors.primeNumbers()); //or new PrimeNumbersCollector()
Utils.printLine("Prime numbers between 1 - 1_000_000:");
Utils.printLine(primesNumbersMap.get(Boolean.TRUE));
}
あなたは可能性がlimit(1000)
とsum(0, BinaryOperator)
カウントの限界に達するまですべての素数。
代わりに、あなただけの素数を選択し、それらを合計する数字のストリームをフィルタリングするために、次の方法を使用することができます。
private static boolean isPrime(final int candidate) {
return IntStream.rangeClosed(2, (int) Math.sqrt(candidate)).noneMatch(i -> candidate % i == 0);
}
使用量は次のようになります。
Stream.iterate(1L, i -> i + 1) //iterate with sequential numbers
.filter(MyFancyClass::isPrime)
.limit(1000)
.reduce(0L, Long::sum);
秒アプローチは最初のアプローチよりも簡潔で効率的です。
これはあなたの質問にお答えします。
を使用しないで、.get()
を使用することは必ずしも悪い習慣ではありません。それはあなたが実装しているロジックになります。 Optional
が空でない場合は、.get()
に頼ってNoSuchElementException
を投げるのがよいでしょう。
したがって、getFirstThousandPrimes()
が空のリストを返す場合、あなたのコードが正確に行うべきことはあなた自身が尋ねるべき質問です。