2016-04-27 3 views
0

私は最初の千の素数を合計したいと思います。私はこれを試してみると...get()をオプションの?

IntelliJはisPresent()をチェックするように提案しますが、それも可能ですか?

別のオプションは.orElse(-1)を使用することですが、何も返さないようにします。私は例外を投げるべきですか?

答えて

1

空の入力を持つ特定のテストでは、完全に有効です。ゼロの合計はゼロです。したがって、.reduce(Integer::sum).orElse(0)を使用するか、.reduce(0, Integer::sum)のようなオプションを完全に取り除くことができます。入力が空の場合は、もちろん0を取得します

getFoos().stream().mapToInt(x -> x).sum(); 

この方法:

はまた、あなたは原始的なストリームに変換し、直接sum()方法を使用することができることに注意してください。

0

ストリームを引数に減らすと、ストリームが空になり、このケースを処理するために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); 

秒アプローチは最初のアプローチよりも簡潔で効率的です。

これはあなたの質問にお答えします。

1

を使用しないで、.get()を使用することは必ずしも悪い習慣ではありません。それはあなたが実装しているロジックになります。 Optionalが空でない場合は、.get()に頼ってNoSuchElementExceptionを投げるのがよいでしょう。

したがって、getFirstThousandPrimes()が空のリストを返す場合、あなたのコードが正確に行うべきことはあなた自身が尋ねるべき質問です。

関連する問題