Stream自己是一個接口,裏面的方法大部分都是高階函數。Stream是一個元素序列,支持一些串行和並行的操做。java
Stream由3部分構成數組
int sum = widgets.stream() .filter(w -> w.getColor() == RED) .mapToInt(w -> w.getWeight()) .sum();
流操做的分類數據結構
// 第一種 Stream stream1 = Stream.of("a", "b", "c"); // 第二種 String[] myArray = new String[]{"a", "b", "c"}; Stream stream2 = Stream.of(myArray); Stream stream3 = Arrays.stream(myArray); // 第三種,經過集合建立Stream對象 List<String> list = Arrays.asList(myArray); Stream stream4 = list.stream();
Stream.of(new int[]{1, 2, 3}).forEach(System.out::println); IntStream.range(3, 8).forEach(System.out::println);
題設條件:有一個List<Integer> list,須要對裏面的元素進行 * 2,並將全部的元素結果相加返回併發
int sum = 0; for(Integer i : list){ sum+= i * 2; } System.out.println(sum);
System.out.println(list.stream().mapToInt(i -> i * 2).sum()); System.out.println(list.stream().map(i -> i * 2).reduce(0, Integer::sum));
Stream<String> stream = Stream.of("a", "b", "c"); // lambda表達式方式 String[] stringArray = stream.toArray(i -> new String[i]); List<String> stringList = stream.collect(Collectors.toList()); // 方法引用方式(構造方法引用) String[] stringArray2 = stream.toArray(String[]::new);
<R> R collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner);
R result = supplier.get(); for (T element : this stream) accumulator.accept(result, element); return result;
不使用Collectors.toList,而使用collect方法來組裝:dom
// lambda寫法 List<String> stringList2 = stream.collect(() -> new ArrayList<>(),(biList, item) -> biList.add(item),(list1, list2) -> list1.addAll(list2)); // 方法引用寫法 List<String> stringList3 = stream.collect(ArrayList::new, ArrayList::add,ArrayList::addAll);
累加器
,每次執行的時候都將建立一個List,將stream中的元素添加到這個集合當中合併器
,語義實際上是將第二步得到的每一個list,添加到最終返回的List當中這裏談談我我的的理解:函數
以上的內容爲我的的猜測。
public static <T, C extends Collection<T>> Collector<T, ?, C> toCollection(Supplier<C> collectionFactory) { return new CollectorImpl<>(collectionFactory, Collection<T>::add, (r1, r2) -> { r1.addAll(r2); return r1; }, CH_ID); }
toCollection接收一個Supplier函數方法,來構造容器性能
實際使用場景:ui
Stream<String> stream = Stream.of("a", "b", "c","c"); List<String> stringList = stream.collect(Collectors.toList()); LinkedList<String> linkedList = stringList.stream() .collect(Collectors.toCollection(LinkedList::new)); Set<String> set = stringList.stream().collect(Collectors.toCollection(HashSet::new));
與Map差異:this
Stream<List<String>> listStream = Stream.of(Arrays.asList("hello1", "world1", "test1") , Arrays.asList("hello2", "world2", "test3") , Arrays.asList("hello3", "world3", "test3")); Stream<String> stringStream = listStream.flatMap(i -> i.stream()); List<String> list = stringStream.collect(Collectors.toList()); list.stream().forEach(System.out::println);
List<String> list = Arrays.asList("hello world","welcome world","hello welcome"); list.stream().map(item -> item.split(" ")).flatMap(i -> Arrays.stream(i)).distinct().collect(Collectors.toList()).forEach(System.out::println);
flapmap將Stream<String[]> 打平爲 Stream<String>指針
findFirst是一箇中斷式的方法,返回Stream的第一個元素,以Optional<T>
的形式返回。
Stream<String> stringStream = Stream.gennerate("abc"::new); Optional<String> optionalS = stringStream.findFirst(); optionalS.ifPresent(System.out::println);
至於爲何findFirst要返回Optional,應該是爲了防止空指針異常,有可能Stream內沒有元素。
Stream.iterate(2,i -> i * 2).limit(10).forEach(System.out::println);
Stream<Integer> stream = Stream.iterate(1, i -> i + 2) .limit(6) .filter(i -> i > 2); System.out.println(stream.skip(3)); System.out.println(stream.count());
這段代碼將會拋出異常:java.lang.IllegalStateException: stream has already been operated upon or closed
緣由是stream每次中間操做,都會返回一個新的stream,而且一個stream只容許被操做一次。
而在執行System.out.println(stream.count());時,stream這個流已經被執行過stream.skip(3)了。
Stream.iterate(1, i -> (i + 1) % 2) .distinct() .limit(6) .forEach(System.out::println); Stream.iterate(1, i -> (i + 1) % 2) .limit(6) .distinct() .forEach(System.out::println);
第一段段代碼將會無限執行下去,而第二段則不會。
緣由是limit(6)和 distinct()的順序不一樣,distinct後,代碼只會返回2個元素,而limit在等待6個元素,因此iterate將無限執行下去,直到能返回6個元素。
List<String> list = new ArrayList<>(5000000); for (int i = 0; i < 5000000; i++) { list.add(UUID.randomUUID().toString()); } System.out.println("開始排序"); long start = System.nanoTime(); list.stream().sorted().count(); long end = System.nanoTime(); long use = TimeUnit.NANOSECONDS.toMillis(end - start); System.out.println("使用時間:" + use);
這裏是經過串行流完成500w個uuid排序,在個人電腦上,串行流使用了4秒,而並行流只須要1秒,提高了將近4倍。
Stream是可短路的,是將全部的配置項,例如distinct,sort,map等中間操做,彙總在一塊兒後才執行,而且只要完成要求,後續的元素遍歷將再也不執行,例如findFirst,得到到符合條件的一個元素後,後續元素將再也不獲得遍歷。
Student student1 = new Student("A",100,15); Student student2 = new Student("B",70,20); Student student3 = new Student("C",80,25); Student student4 = new Student("A",59,30); List<Student> list = Arrays.asList(student1,student2,student3,student4); Map<String, List<Student>> map = list.stream() .collect(Collectors.groupingBy(Student::getName));
經過Collectors.groupingBy()
方法,將Stream<T>的內容經過分組依據 T.xx,返回爲 Map<T.xxx, List<T>>
若是隻須要統計分組後各個依據T.xx的個數,只須要將Collectors.groupingBy(T::xx)
替換爲Collectors.groupingBy(T::xx, Collectors.counting())
便可返回Map<T.xxx, Long>
Map<Boolean, List<Student>> map = list.stream() .collect(Collectors.partitioningBy(i -> i.getScore() >= 60));
操做管道
從source(數據結構,數組,IO等)抓取數據。