2016-09-12 4 views
0

ストリームを手動で短絡する方法はありますか(findFirstなど)?手動でJava 8ストリーム短絡

例:

ワードサイズとアルファベット順の巨大な辞書を想像:

cat 
... (many more) 
lamp 
mountain 
... (many more) 

だけ準備をし、ラインサイズが4を超えた場合すぐに、最初からリターンをファイルを計算:

read cat, compute cat 
... 
read tree, compute lamp 
read mountain, return 

次のコードは非常に簡潔ですが、利点の中に、ストリームの順序を取らない、それは準備ができて、すべての行にあります。述語がfalseを返したとき

try (Stream<String> lines = Files.lines(Paths.get(DICTIONARY_PATH))) { 
     return lines 
       // filter for words with the correct size 
       .filter(line -> line.length() == 4) 
       // do stuff... 
       .collect(Collectors.toList()); 
} 
+3

関連:http://stackoverflow.com/questions/20746429/limit-a-stream-by-a-predicate –

+2

あなたは、一般的に 'takewhile'と呼ばれている欲しいです。 [この質問](http://stackoverflow.com/questions/20746429/limit-a-stream-by-a-predicate)によると、それを行うための組み込みの方法はないようだが、あなたはあなた自身。 – Bakuriu

答えて

0

回答はLimit a stream by a predicateに基づいて、処理が正常に停止します。うまくいけば、この方法はJava 9で利用できる来る:

private static List<String> getPossibleAnswers(int numberOfChars, char[][] possibleChars) throws IOException { 
    try (Stream<String> lines = Files.lines(Paths.get(DICTIONARY_PATH)) { 
     return takeWhile(lines, line -> line.length() <= numberOfChars) 
       // filter length 
       .filter(line -> line.length() == numberOfChars) 
       // do stuff 
       .collect(Collectors.toList()); 
    } 
} 

static <T> Spliterator<T> takeWhile(Spliterator<T> splitr, Predicate<? super T> predicate) { 
    return new Spliterators.AbstractSpliterator<T>(splitr.estimateSize(), 0) {    boolean stillGoing = true; 

     @Override 
     public boolean tryAdvance(Consumer<? super T> consumer) { 
      if (stillGoing) { 
       boolean hadNext = splitr.tryAdvance(elem -> { 
        if (predicate.test(elem)) { 
         consumer.accept(elem); 
        } else { 
         stillGoing = false; 
        } 
       }); 
       return hadNext && stillGoing; 
      } 
      return false; 
     } 
    }; 
} 

static <T> Stream<T> takeWhile(Stream<T> stream, Predicate<? super T> predicate) { 
    return StreamSupport.stream(takeWhile(stream.spliterator(), predicate), false); 
} 
+1

これは古典的なループと比較して非常に非効率的です。 – aventurin

+0

@aventurin java9を使った方が速く実装されるかもしれません。少なくともコードは簡潔で、一時変数は必要ありません。 – Journeycorner

+1

ストリームAPIは、その背後にある肥大化をプログラマから隠すかもしれませんが、CPUサイクル、メモリの再割り当て(ArrayList-collector)、余分なオブジェクトとクラスの作成回数を減らすことはできません。それに加えて、ループを使用する同等のコードは分かりやすく、3行のコードに2つの変数定義を加えただけです。 – aventurin