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等)抓取数据。