jdk 1.8 新特性之——stream流的学习

1、流的特点

     流只能遍历一次,流中的元素向流水线一样经过一个或多个中间操作,最后执行终端操作,完成流的遍历。

     流采用内部迭代。

2.流的操作 类型

   中间操作—— 返回一个stream,同一个stream可以进行多个中间操作。

                filter:过滤操作,filter函数接收一个Lambda表达式作为参数,该表达式返回boolean;

                map:转换操作,map函数将stream的元素转换成另一种类型输出;

                distinct:去重操作,去除stream中的重复元素;

                limit:截取操作,截取流的前N个元素;

                skip:跳过操作,跳过流的前n个元素;

                flatMap:合并操作,将小流合并成一个大流;

                sorted:排序操作,根据传入的排序规则排序;

                peek:观察,返回一个新stream,新stream类型不变,即peek不改变流的元素,接受一个实现了 consumer 接口的类,新Stream每个元素被消费的时候都会执行给定的消费函数,若新stream没有被消费, 则peek中的消费函数不会执行;

                 parallel:生成一个并行流。

                

   终端操作——返回处理结果,一个stream只能进行一次终端操作。

                foreach:遍历操作,遍历stream;

                collect:汇聚操作,可变汇聚,把Stream中的元素收集到一个结果容器中(比如Collection);

                reduce:汇聚操作,返回一个汇聚结果;

                allMatch:搜索操作,是不是Stream中的所有元素都满足给定的匹配条件;

                anyMatch:搜索操作,Stream中是否存在任何一个元素满足匹配条件;

                noneMatch:搜索操作,是不是Stream中的所有元素都不满足给定的匹配条件;

                findFirst:搜索操作,返回Stream中的第一个元素,如果Stream为空,返回空Optional;

                findAny:搜索操作,获取任一元素,Optional容器只存1个或0个元素,遍历集合,获取到一个元素就结束遍历;

                max:计算操作,取最大值,计算数值流的最大值,返回一个Optional的子类。

person类

 

class Person {

  private String name;

  private int type;

  public Person() {}

  public Person(String name, int type) {
    this.name = name;
    this.type = type;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public int getType() {
    return type;
  }

  public void setType(int type) {
    this.type = type;
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (o == null || getClass() != o.getClass()) {
      return false;
    }
    Person person = (Person) o;
    return name != null ? name.equals(person.name) : person.name == null;
  }

  @Override
  public int hashCode() {
    return name != null ? name.hashCode() : 0;
  }

  @Override
  public String toString() {
    return "Person{" + "name='" + name + '\'' + ", type=" + type + '}';
  }

  public boolean isStudent() {
    return this.type == 1;
  }

  public Person compareTo(Person person) {
    return person.getType() > this.type ? person : this;
  }
}

 

 

 

 

 

3、获取流

      原始流(数值流)的获取

    // 原始流的初始化
    IntStream intStream = IntStream.of(1, 2, 3, 4, 5, 0, 8, 6, 8, 9, 7);
    // 初始化0-10的整数流,包括10
    IntStream intStream1 = IntStream.rangeClosed(0, 10);
    intStream1.forEach(System.out::print);
    IntStream intStream2 = IntStream.range(0, 10);
    System.out.println();
    intStream2.forEach(System.out::print);
    // 原始类型流封装为流对象,数据量比较大的情况下,将基本数据类型(int,double...)包装成相应对象流的做法是低效的,因此可以初始化为原始流
    Stream<Integer> stream = intStream.boxed();
    DoubleStream doubleStream = DoubleStream.of(1.1, 2.2, 3.3);
    LongStream longStream = LongStream.of(1, 2, 3, 4);
    Stream.iterate(0, x -> x + 1).limit(10).parallel();

    //对象流转数值流
   Stream<Integer> stream1 = Arrays.asList(1,2,3).stream();
   IntStream iStreaam = stream1.mapToInt(i -> i);
    // 数组转流
   Integer[] arr = {1, 2, 3};
   Stream<Integer> stream3 = Arrays.stream(arr);

   //迭代器转化成stream
   Iterator<Integer> values = Arrays.asList(1, 2, 3).iterator();
   Stream<Interger> iterStream = StreamSupport.stream(Spliterators.spliteratorUnknownSize(values, Spliterator.SORTED), true);
   Iterable<Integer> iterable = () -> values;
   iterStream = StreamSupport.stream(iterable.spliterator(), false);

    从流中获得集合,

 

 

    Person[] ps = list.stream().toArray(Person[]::new);
    String[] names = list.stream().map(Person::getName).toArray(String[]::new);
    List<Person> personList = list.stream().collect(toList());
    List<String> stringList = list.stream().map(Person::getName).collect(toList());
    Set<Person> personSet = list.stream().collect(toSet());
    Set<Integer> integerSet = list.stream().collect(mapping(Person::getType, toSet()));
    HashSet<Person> personHashSet = list.stream().collect(toCollection(HashSet::new));
    // list转map,如果有key相同,需要加第三个参数,设置重复key对应的value的处理,这里后面的覆盖前面的
    Map<Integer, String> hashMap =
        list.stream().collect(toMap(Person::getType, Person::getName, (x, y) -> y));
    hashMap.forEach((k, v) -> System.out.println(k + "-" + v));
    // groupingBy根据指定属性分组
    Map<String, List<Person>> map = list.stream().collect(groupingBy(Person::getName));
    map.forEach((k, v) -> System.out.println(k + "-" + v));

   这里toList()使用了静态引用,可以直接使用Collectors下的静态方法。

import static java.util.stream.Collectors.*;

   统计,combine 操作将一个IntSummaryStatistics和另一个IntSummaryStatistics组合起来

    // 统计
    IntSummaryStatistics intSummaryStatistics =
        list.stream().collect(summarizingInt(Person::getType));
    System.out.println("平均:" + intSummaryStatistics.getAverage());
    System.out.println("记录数:" + intSummaryStatistics.getCount());
    System.out.println("最大:" + intSummaryStatistics.getMax());
    System.out.println("最小:" + intSummaryStatistics.getMin());
    System.out.println("和:" + intSummaryStatistics.getSum());

    IntSummaryStatistics intSummaryStatistics1 =
        Stream.of(1, 2, 3, 3, 4, 5, 6).collect(summarizingInt(Integer::intValue));
    // combine 操作将一个IntSummaryStatistics和另一个IntSummaryStatistics组合起来
    intSummaryStatistics.combine(intSummaryStatistics1);
    System.out.println(intSummaryStatistics.getSum());

 filter操作,filter函数接收一个Lambda表达式作为参数,该表达式返回boolean。

    // filter函数接收一个Lambda表达式作为参数,该表达式返回boolean。过滤流
    List<Person> l = list.stream().filter(Person::isStudent).collect(toList());
    List<Person> ll = list.stream().filter(p -> p.isStudent()).collect(toList());

map转换,将一个流转换成另一种类型的流,

    // map映射对流中的每个元素执行一个函数,使得元素转换成另一种类型输出.转换流
    List<String> ps = list.stream().map(Person::getName).collect(toList());
    list.stream().map(p -> p.getType()).sorted();

distinct、limit、ship 去重、截取和跳过

    Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3);
    // distinct去重
    Object[] os = stream.distinct().collect(toList()).toArray();
    Stream.of(os).forEach(s -> System.out.print(s));
    System.out.println();
    // collect为终端操作,stream只能执行一个终端操作,执行完后关闭
    // List<Integer> list = stream.limit(5).collect(toList());
    // limit截取流的前N个元素
    Stream.of(os).limit(5).forEach(s -> System.out.print(s));
    System.out.println();
    // skip跳过流的前n个元素
    Stream.of(os).skip(5).forEach(s -> System.out.print(s));
    System.out.println();

   // 创建无限流,通过limit提取指定大小
   Stream.generate(() -> new Random().nextInt()).limit(10).forEach(System.out::println);
   // 产生规律的数据,0为初始值
   Stream.iterate(0, x -> x + 1).limit(10).forEach(System.out::println);
   Stream.iterate(0, UnaryOperator.identity()).limit(10).forEach(System.out::println);

flatMap合并操作,将小流合并成一个大流,string.split(" ")将list分成三个stream,flatMap再将其合并成一个stream

    List<String> list = new ArrayList();
    list.add("I am a boy");
    list.add("I love the girl");
    list.add("But the girl loves another girl");
    // 大流里面包含了一个个小流,将这些小流合并成一个流。split ""和" "不一样。flatMap拆解流
    List<String> ll =
        list.stream().map(string -> string.split(" ")).flatMap(Arrays::stream).collect(toList());
    System.out.println(ll.size());
    ll.stream().forEach(str -> System.out.print(str));

peek,观察strean中元素的状态,不改变元素

    //返回一个新stream,新stream没有被消费,不执行打印语句
    Stream<Person> s = list.stream().peek(System.out::println);
    list.stream().peek(System.out::println).count();
    // stream的转换操作都是lazy的,只在终端操作时循环stream,对每个元素执行中间操作和终端操作,这里包括peek,foreach
    list.stream().peek(person -> System.out.println(person.getName())).forEach(System.out::println);

     查看stream中元素的操作过程

public class PeekStream {

  public static void main(String[] args) {
    Stream<Integer> stream = Stream.iterate(0, x -> x + 1).limit(10);
    //new PeekStream().testPeek(stream);
    new PeekStream().testPeek(stream.parallel());
  }

  public void testPeek(Stream<Integer> stream) {
    //peek
    stream.peek(this::peek1).filter(x -> x > 5).peek(this::peek2).filter(x -> x < 8)
        .peek(this::peek3).forEach(System.out::println);
  }

  public void peek1(int x) {
    System.out.println(Thread.currentThread().getName() + ":->peek1->" + x);
  }

  public void peek2(int x) {
    System.out.println(Thread.currentThread().getName() + ":->peek2->" + x);
  }

  public void peek3(int x) {
    System.out.println(Thread.currentThread().getName() + ":->peek3->" + x);
  }
}

sorted排序操作

    // 按type从小到大排序
    list.stream().sorted((p1, p2) -> {
      if (p1.getType() < p2.getType()) {
        return -1;
      } else if (p1.getType() > p2.getType()) {
        return 1;
      } else {
        return 0;
      }
    }).forEach(System.out::println);
    // 按type的自然顺序排序
    list.stream().sorted(Comparator.comparing(Person::getType)).forEach(System.out::println);
    // 按type的自然顺序倒序排序
    list.stream().sorted(Comparator.comparing(Person::getType).reversed())
        .forEach(System.out::println);
    String[] ss = {"sad", "aer", "fdsd", "her"};
    // 自然排序比较器
    Stream.of(ss).sorted(Comparator.naturalOrder()).forEach(System.out::println);
    // 逆自然排序比较器
    Stream.of(ss).sorted(Comparator.reverseOrder()).forEach(System.out::println);

 

 

 

 

 

搜索操作

    // anyMatch是否匹配任一元素
    boolean result = list.stream().anyMatch(Person::isStudent);
    System.out.println("是否包含学生:" + result);
    // allMatch是否匹配所有元素
    boolean result1 = list.stream().allMatch(Person::isStudent);
    System.out.println("是否全部是学生:" + result1);
    // noneMatch是否没有一个匹配
    boolean result2 = list.stream().noneMatch(Person::isStudent);
    System.out.println("是否全部不是学生:" + result2);

    

    String str = "";
    // findAny获取任一元素,Optional容器只存1个或0个元素
    Optional<Person> person3 = list.stream().findAny();
    // parallel并行流
    Optional<Person> person4 = list.stream().parallel().findAny();
    // findFirst获取流的第一个元素
    Optional<Person> person5 = list.stream().findFirst();
    System.out.println("有序流抽取一个人:" + person3.get());
    System.out.println("随机抽取一个人:" + person4.get());
    System.out.println("抽取第一个人:" + person5.get());
    Optional<Person> optional = list.stream().parallel().filter(Person::isStudent).findAny();
    optional.ifPresent(System.out::println);
    // System.out.println("max:" + list.stream().max((p1, p2) -> p1.compareTo(p2)));

reduce聚合操作

    // reduce聚合操作,求和,最后返回sum,最开始,sum是流第一个元素的值,num是流第二个元素的值,返回Optional对象,因为stream可能为空
    System.out.println(list.stream().map(Person::getType).reduce((sum, num) -> sum + num));
    // 第一个参数设置初始值,返回String
    System.out.println(list.stream().map(Person::getName).reduce("", (str, s) -> str + s));

 

         

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值