* Статични методи на клас 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 + " ")); } }
Добави коментар