* Статични методи на клас Stream
Публикувано на 16 март 2015 в раздел ПИК3 Java.
В тази статия ще разгледаме статичните методи на клас Stream. Ще покажем и два начина за генериране на безкраен поток - чрез Supplier и чрез метод iterate.
Примерите с код, които ще опишем по-долу се надграждат един-друг. В началото трябва да добавите java.util.function.*, java.util.*, java.text.* и java.util.stream.*.
Stream.builder() създава обект от клас Stream.Builder. Този обект може да акумулира обекти от даден тип и по този начин в последствие да изгражда поток. Методите add и accept добавят елементи (те са напълно еквивалентни), а метод build връща обект от тип Stream.
Stream.Builder<String> strb = Stream.builder();
strb.add("Ivan");
strb.accept("Petar");
strb.add("Maria");
Stream<String> stream1 = strb.build();
Stream.generate(Supplier<T>) - генерира поток на базата на Supplier. Това е безкраен поток, защото Supplier ще връща безкраен брой елементи! Когато работите с такъв поток, трябва в даден момент задължително да използвате short-circuit метод, в противен случай ще се получи безкраен цикъл. В следващият пример генерираме безкраен поток от текущи дата и час, конвертирани в String, след което показваме как може да се чете пореден елемент от този поток:
// Генерираме дата и час във формат MM/dd/yyyy hh:mm:ss
// и го предаваме на обект от интерфейс Supplier
Format formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Supplier<String> stringDateSupplier = () -> formatter.format(new Date());
// Пример, че работи
System.out.println(stringDateSupplier.get());
// Генерираме безкраен поток
Stream<String> stream2 = Stream.generate(stringDateSupplier);
Безкрайният поток от дати естествено въобще не е практичен пример. Работата с подобен поток може да генерира много елементи с една и съща дата в рамките на една секунда. Затова го даваме само за демонстрация - не го използвайте никога в практиката.
Stream.concat(Stream<T>, Stream<T>) - обединява два потока от един и същи по тип елементи в общ поток.
// Обединяваме двата вече създадени потока в един общ Stream<String> stream3 = Stream.concat(stream1, stream2); // Употребяваме short-circuit операция Optional<String> getElement = stream3.filter(e -> e.length()>=5).findAny(); getElement.ifPresent(System.out::println);
Имайте предвид, че в този момент (след употребата на крайната операция върху stream3) вече не можем да използваме не само stream3, но не можем да използваме също stream1 и stream2 - те са вече затворени
Stream.of(T... values) и Stream.of(T t) - генерира поток по подадените параметри.
// Създаваме два потока от низове с имена на хора
Stream<String> stream4 = Stream.of("Ivan");
Stream<String> stream5 = Stream.of("Petar", "Maria");
Stream.empty() - създава нов празен поток (не много смислена операция, но все пак възможна)
Stream<String> stream6 = Stream.empty(); Stream.concat(stream6, Stream.concat(stream4, stream5));
Stream.iterate(T, UnaryOperator<T>) - по подаден seed (първоначална стойност) генерира безкроен поток от елементи по правилото, дефинирано от UnaryOperator-а. В следващият пример създаваме поток от естествени числа и после намираме първите 10 прости.
// Използваме "boxing" - примитивите се конвертират автоматично до Long
Stream<Long> naturalNumbers = Stream.iterate(1L, n -> n + 1);
// Намираме и отпечатваме първите 10 прости числа
naturalNumbers
.filter(n -> {
if (n%2==0 || n==1) return false;
for(int i=3;i*i<=n;i+=2) {
if(n%i==0) return false;
}
return true;
})
.limit(10)
.forEach(n -> System.out.print(n + " "));
Ето и целият код с всички примери накуп:
import java.util.stream.*;
import java.util.*;
import java.util.function.*;
import java.text.*;
public class StreamExample{
public static void main(String[] args){
Stream.Builder<String> strb = Stream.builder();
strb.add("Ivan");
strb.accept("Petar");
strb.add("Maria");
Stream<String> stream1 = strb.build();
// Генерираме дата и час във формат MM/dd/yyyy hh:mm:ss
// и го предаваме на обект от интерфейс Supplier
Format formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Supplier<String> stringDateSupplier = () -> formatter.format(new Date());
// Пример, че работи
System.out.println(stringDateSupplier.get());
// Генерираме безкраен поток
Stream<String> stream2 = Stream.generate(stringDateSupplier);
// Обединяваме двата вече създадени потока в един общ
Stream<String> stream3 = Stream.concat(stream1, stream2);
// Употребяваме short-circuit операция
Optional<String> getElement = stream3.filter(e -> e.length()>=5).findAny();
getElement.ifPresent(System.out::println);
// Създаваме два потока от низове с имена и факултетни номера на студенти
Stream<String> stream4 = Stream.of("Ivan");
Stream<String> stream5 = Stream.of("Petar", "Maria");
Stream<String> stream6 = Stream.empty();
Stream.concat(stream6, Stream.concat(stream4, stream5));
// Използваме "boxing" - примитивите се конвертират автоматично до Long
Stream<Long> naturalNumbers = Stream.iterate(1L, n -> n + 1);
// Намираме и отпечатваме първите 10 прости числа
naturalNumbers
.filter(n -> {
if (n%2==0 || n==1) return false;
for(int i=3;i*i<=n;i+=2) {
if(n%i==0) return false;
}
return true;
})
.limit(10)
.forEach(n -> System.out.print(n + " "));
}
}
Добави коментар