2014-01-19 8 views
18

Я читаю из java 8 API на поток абстракции, но я не понимаю, это предложение очень хорошо:поток и ленивые вычисления

Промежуточные операции возвращают новый поток. Они всегда ленивы; Выполнение промежуточной операции, такой как filter(), фактически не выполняет , а создает новый поток, который при обходе содержит элементы исходного потока, которые соответствуют предикату . Обход источника конвейера не начинается до выполняется операция терминала по конвейеру.

Когда операция фильтра создает новый поток, этот поток содержит фильтрованный элемент? Похоже, что поток содержит элементы только тогда, когда они пройдены с помощью операции с терминалом. Но, чем, что содержит отфильтрованный поток? Я смущен!!!

+0

@Lukas, у нас уже есть [tag: java-stream] для Java 8 Stream API. Тег, который вы создали, очень ... общий. – Charles

+9

Но его официальное название - «Streams API», а не «Java-Stream». Java Stream может означать что угодно. В том числе InputStream/OutputStream и т.п. Во всяком случае, я думаю, это должно быть принято в мета ... –

ответ

27

Это означает, что фильтр применяется только во время работы терминала. Подумайте о чем-то вроде этого:

public Stream filter(Predicate p) { 
    this.filter = p; // just store it, don't apply it yet 
    return this; // in reality: return a new stream 
} 
public List collect() { 
    for (Object o : stream) { 
     if (filter.test(o)) list.add(o); 
    } 
    return list; 
} 

(Это не компилируется и является упрощением реальности, но принцип есть)

3

Streams ленив, поскольку промежуточные операции не оценивается, если терминал операция не вызываются.

Каждая промежуточная операция создает новый поток, сохраняет предоставленную операцию/функцию и возвращает новый поток.

Конвейер накапливает эти вновь созданные потоки.

Время, когда вызывается операция терминала, начинается обход потоков, и соответствующая функция выполняется один за другим.

Параллельные потоки не оценивают потоки «один за другим» (в терминальной точке). Операции выполняются одновременно, в зависимости от доступных ядер.

1

Мне кажется, что промежуточная операция не совсем ленивые:

List<String> l3 = new ArrayList<String>(); 
     l3.add("first"); 
     l3.add("second"); 
     l3.add("third"); 
     l3.add("fouth"); 
     l3.add("fith"); 
     l3.add("sixth"); 

     List<String> test3 = new ArrayList<String>(); 
     try { 
      l3.stream().filter(s -> { l3.clear(); test3.add(s); return true;}).forEach(System.out::println); 
     } catch (Exception ex) { 
      ex.printStackTrace(); 
      System.out.println("!!! "); 
      System.out.println(test3.stream().reduce((s1, s2) -> s1 += " ;" + s2).get()); 
     } 

Задачи и результаты:

first 
    null 
    null 
    null 
    null 
    null 
    java.util.ConcurrentModificationException 
     at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1380) 
     at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481) 
     at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) 
     at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151) 
     at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174) 
     at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) 
     at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418) 
     at test.TestParallel.main(TestParallel.java:69) 
    !!! 

    first ;null ;null ;null ;null ;null 

Похож числом итераций наборов по созданию потока, но адресность нового потокового элемента ленивой.

+0

Не могли бы вы отформатировать свой код, выделив его и нажав Ctrl + K – WhatsThePoint

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