强大的Stream API总汇

目录

Stream介绍

流(Stream)到底是什么

 Stream操作的步骤

创建流Stream的四种方式

Stream中间操作

筛选与切片

映射 

 排序

 Stream终止操作

查找与匹配 

 归约

  收集


Stream介绍

Stream是Java8中处理集合的关键抽象概念。

Stream API对集合数据进行操作,类似于使用SQL执行的数据库查询。也可以使用Stream API来并行执行操作。简而言之它提供了一种高效且易于使用处理数据的方式。

流(Stream)到底是什么

是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。

集合讲的是数据,流讲的是计算

注意:

        Stream不会自己存储元素。

        Stream不会改变源对象。相反,他们会返回一个持有结果的新Stream。

        Stream操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。

 Stream操作的步骤

创建Stream:一个数据源,获取一个流。

中间操作:对数据源的数据进行处理。

终止操作:执行中间操作链并产生结果。

创建流Stream的四种方式

方式一: 通过Collection系列集合提供的Stream()或parallelStream()
 List<String > list = new ArrayList<>();
        Stream<String> stream1 = list.stream();
方式二:通过Arrays中的静态方法Stream()获取数组流
Employee[] emps = new Employee[20];
        Stream<Employee> stream2 = Arrays.stream(emps);
方式三:  通过Stream类中的静态方法of()
Stream<String>stream3 = Stream.of("aa","bb");
 方式四:   创建无限流:迭代/生成(迭代:一个数加三,限制数量10个
                                  生成:生成不限量随机数)
   Stream<Integer> stream4 = Stream.iterate(0,(x)->x+3);
        stream4.limit(10).forEach(System.out::println);
//        创建无限流,生成
Stream.generate(()->Math.random())
       .forEach(System.out::println);

Stream中间操作

多个中间操作可以连接起来形成一个流水线,除非流水线触碰终止操作,否则中间操作不会做任何处理,而在终止操作时一次性全部处理,称为“惰性求值”。

中间操作主要涉及方面 

   筛选与切片 、映射、排序。

筛选与切片

主要方法:

filter - 接收lambda,从流中排除某些元素。

limit - 截断流,使其元素不超过给定的数量。

skip(n)- 跳过元素,返回一个扔掉了前n个元素的流,若流中的元素不足n个,则返回一个空流,与limit(n)互补。

distinct - 筛选,通过流所生成的元素hashCode和equals()去除重复元素。

示例1:

创建Employee(属性 name age salary)

public interface ShaiXuanYuQiePian {
    public static void main(String[] args) {
        List<Employee> list = Arrays.asList(
                new Employee("张三",18,9999),
                new Employee("赵四",58,8888),
                new Employee("王五",26,7777),
                new Employee("赵六",36,5555),
                new Employee("田七",17,33333),
        new Employee("田七",17,33333 )

        );
//        内部迭代:迭代器由Stream API完成
//        排除<35岁的
        Stream s = list.stream()
                .filter((e)->e.getAge()>35);
//        终止操作
        s.forEach(System.out::println);
        System.out.println("-------------------------------");
//        外部迭代:按顺序迭代每一个元素
        Iterator<Employee> it = list.iterator();
        while (it.hasNext()){
            System.out.println(it.next());
        }
        System.out.println("------------------------------");
//        排除工资<5000的,并且只显示2个人的信息
        list.stream()
                .filter((e)->e.getSalary()>5000)
                .limit(2)
                .forEach(System.out::println);
        System.out.println("------------------------------");
//        排除工资<5000的并跳过前两个人的信息
        list.stream()
                .filter((e)->e.getSalary()>5000)
                .skip(2)
                .forEach(System.out::println);
        System.out.println("------------------------------");
//           排除工资<5000的并跳过前两个人的信息,并除去重复信息
        list.stream()
                .filter((e)->e.getSalary()>5000)
                .skip(2)
                .distinct()
                .forEach(System.out::println);

    }

}

映射 

主要方法

map - 接收lambda,将元素转换成其他形式或提取信息,接受一个函数作为参数,该函数会被应用到每一个元素上,并将其映射成一个新的元素。

flatMap - 接受一个函数作为参数,将流中的每个值都换成另一个流,然后把所有的流连接成一个流。

示例2:

public class YingShe {
    public static void main(String[] args) {
        List<Employee> list = Arrays.asList(
                new Employee("张三",18,9999),
                new Employee("赵四",58,8888),
                new Employee("王五",26,7777),
                new Employee("赵六",36,5555),
                new Employee("田七",17,33333)
        );
        List<String> list1 = Arrays.asList("aaa","bbb","ccc","ddd","eee");
//       将流中灭个元素的小写都换为大写
        list1.stream()
                .map((str)->str.toUpperCase(Locale.ROOT))
                .forEach(System.out::println);
        System.out.println("--------------------------");
//获取所有姓名
        list.stream()
                .map(Employee::getName)
                .forEach(System.out::println);
        System.out.println("-------------------------");
     
//        获取流中字符串的每一元素
//map返回一个流1Stream,流中保存的事流2Stream<Character>{流1{流2a,a,a},{流2b,b,b}}
        Stream<Stream<Character>> stream =list1.stream()
                .map(YingShe::filterCharacter);
        stream.forEach((sm)->sm.forEach(System.out::print));
        System.out.println("------------------------");
        
//       方法二:代替上述map{a,a,a,b,b,b}
        Stream<Character> sm = list1.stream()
                .flatMap(YingShe::filterCharacter);
        sm.forEach(System.out::print);

    }

//    Character:对单个字符进行操作 Stream<character>将字符串提取出来转换成流
    public static Stream<Character> filterCharacter(String str){
        List<Character>list = new ArrayList<>();
//        toCharArray() 方法将字符串转换为字符数组
        for(Character ch: str.toCharArray()){
            list.add(ch);
        }
        return list.stream();
    }
}

 排序

主要方法

sorted - 自然排序

sorted(Comparator com)-定制排序

示例3:

如果年龄相等就按照姓名排,否则按照年龄排

public class Paixu {
    public static void main(String[] args) {
        List<Employee> list = Arrays.asList(
                new Employee("张三",18,9999),
                new Employee("赵四",58,8888),
                new Employee("王五",26,7777),
                new Employee("赵六",36,5555),
                new Employee("田七",17,33333),
                new Employee("田",17,33333 )

        );
        list.stream()
                .sorted((e1,e2)->{
                    if(e1.getAge()==e2.getAge()){
                        return  e1.getName().compareTo(e2.getName());
                    }else{
                        return new Integer (-e1.getAge()).compareTo(new Integer(e2.getAge())) ;
                    }
                }).forEach(System.out::println);
    }
}

 Stream终止操作

从流的流水线生成结果。其结果可以是任何不是流的值,例如:List、Integer

查找与匹配 

主要方法

* allMatch-检查是否匹配所有元素
* anyMatch-检查是否pip一个元素
* noneMatch-检查是否没有匹配所有元素
* findFirst-返回第一个元素
* findAny-返回当前流中的任意元素
* count-返回流中元素的总个数
* max-返回流中最大值
* min-返回流中最小值

示例四:

 private Employees.Status Status;

    public Employees(String name, int age, int salary, Status Status) {
        this.name = name;
        this.age = age;
        this.salary = salary;
       this.Status  = Status;
    }

    public void setStatus(Employees.Status status) {
        Status = status;
    }

    public Employees.Status getStatus() {
        return Status;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", salary=" + salary +
                ", Status=" + Status +
                '}';
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getSalary() {
        return salary;
    }

    public void setSalary(int salary) {
        this.salary = salary;
    }



    public Employees() {
    }

    public enum  Status{
        FREE,
        BUSY,
        VOCATION;


    }
}

 

public class Test {
    public static void main(String[] args) {
        List<Employees> employee = Arrays.asList(
                new Employees("张三",18,9999, Employees.Status.FREE),
                new Employees("李四",58,8888, Employees.Status.BUSY),
        new Employees("王五",26,5555, Employees.Status.VOCATION),
        new Employees("赵六",36,6666, Employees.Status.FREE),
        new Employees("田七",12,3333, Employees.Status.BUSY)

        );
//        判断Employees.Status.BUSY状态是否所有元素
       boolean b1 = employee.stream()
                .allMatch(e->e.getStatus().equals(Employees.Status.BUSY));
        System.out.println(b1);

//判断Employees.Status.BUSY是否与集合中一个元素匹配
       boolean b2 =  employee.stream()
                .anyMatch(e->e.getStatus().equals(Employees.Status.BUSY));
        System.out.println(b2);

//      判断Employees.Status.BUSY 是否没有匹配集合的所有元素
       boolean b3= employee.stream()
                .noneMatch(e->e.getStatus().equals(Employees.Status.BUSY));
        System.out.println(b3);

//Optional是容器类,将对象封装到这个容器里,避免空指针异常
//        findFirst-返回第一个元素,如果第一个值有可能为空值就将对象封装到Optional
       Optional<Employees> op = employee.stream()
                .sorted((e1,e2)->Double.compare(e1.getSalary(),e2.getSalary()))
                .findFirst();
        System.out.println(op.get());

//        filter 方法用于通过设置的条件过滤出元素
//        返回当前流中的任意元素
        Optional<Employees> op2 =employee.stream()
                .filter((e)->e.getStatus().equals(Employees.Status.FREE))
                .findAny();
        System.out.println(op2.get());

//        返回流中元素的总个数
        Long count = employee.stream()
                 .count();
        System.out.println(count);

//        返回最大/小值
       Optional<Employees> op3 = employee.stream()
                .max((e1,e2)->Double.compare(e1.getSalary(),e2.getSalary()));
        System.out.println(op3);
            Optional<Integer> op4 = employee.stream()
                    .map(Employees::getSalary)
                    .min(Integer::compare);
        System.out.println(op4);

    }

}

 归约

reduce(T identity(起始值),BinayOperator(二元运算))/reduce(BinayOperator)-可以将流中元素反复结合起来

案例5:

public static void main(String[] args) {

    List<Employees1> employee = Arrays.asList(
            new Employees1("张三",18,9999, Employees1.Status.FREE),
            new Employees1("李四",58,8888, Employees1.Status.BUSY),
            new Employees1("王五",26,5555, Employees1.Status.VOCATION),
            new Employees1("赵六",36,6666, Employees1.Status.FREE),
            new Employees1("田七",12,3333, Employees1.Status.BUSY)

    );
            List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
//数组个元素相加
    Integer sum = list.stream()
            .reduce(0,(x,y)->x+y);
    System.out.println(sum);
    System.out.println("------------------------- ");
//    上边函数不可能为空所以用Integer,下边函数可能为空所以返回Optional
//    map和reduce的链接通常称为map-reduce模式,如大数据搜索热词
//薪资相加
   Optional<Integer> op = employee.stream()
            .map(Employees1::getSalary)
            .reduce(Integer::sum);
    System.out.println(op);
    System.out.println("--------------------");
}

 

  收集

收集:collect(Collector); collector叫做收集器是一个接口,作用是你想按照哪一个收集器的方式收集 collector是一个接口,意味着要传他的实例必须传他的对应实现类collectors 

 示例6:收集常用的方法代码中均有标注

public static void main(String[] args){
List<String> list1= employee.stream()
            .map(Employees1::getName)
//            Collectors.toList() 将流中的所有元素收集到 List 中
            .collect(Collectors.toList());
    System.out.println(list1);
    System.out.println("----------------");

//   将流中所有有元素收集到set中
    Set<String> set = employee.stream()
            .map(Employees1::getName)
            .collect(Collectors.toSet());
    System.out.println(set);
    System.out.println("--------------------------");
    /*
    Collectors toCollection(Supplier<C> collectionFactory)
    方法用于使用 Collector 创建一个 Collection。
    它返回一个收集器,它将输入元素按照传递的顺序累积到一个新的集合中。
    比如你需要返回一个特殊集合时,或者逆向返回任何类型集合
     */
    HashSet<String> hs =employee.stream()
            .map(Employees1::getName)
            .collect(Collectors.toCollection(HashSet::new ));
    hs.forEach(System.out::println);

//    人数总数
    Long count = employee.stream()
            .collect(Collectors.counting());
    System.out.println(count);

//    平均值
    Double avg = employee.stream()
            .collect(Collectors.averagingDouble(Employees1::getSalary));
    System.out.println(avg);

//    工资总和
   int sum1 = employee.stream()
            .collect(Collectors.summingInt(Employees1::getSalary));
    System.out.println(sum1);

//    最大值
   Optional<Employees1> op3 = employee.stream()
            .collect(Collectors.maxBy((e1,e2)->Integer.compare(e1.getSalary(), e2.getSalary())));
    System.out.println(op3);

//    最小值
    Optional<Employees1>op4 = employee.stream()
            .collect(Collectors.minBy((e1,e2)->Integer.compare(e1.getSalary(), e2.getSalary())));
    System.out.println(op4);
    System.out.println("-------------------");

    分组
    Map<Employees1.Status,List<Employees1>> map = employee.stream()
            .collect(Collectors.groupingBy(Employees1::getStatus));
    System.out.println(map);
    System.out.println("-------------------");
//多及分组
   Map<Employees1.Status,Map<String,List<Employees1>>> map1 = employee.stream()
            .collect(Collectors.groupingBy(Employees1::getStatus,Collectors.groupingBy((e)->
                    {
                        if(((Employees1)e).getAge()<=35){
                            return "青年";
                        }else{
                            return"老年";
                        }
                    }
                    ))) ;
    System.out.println(map1);
//    分区:分TRUE和FALSE的两个区,满足条件的一个区,不满足条件的一个区、
    Map<Boolean,List<Employees1>> map2 = employee.stream()
            .collect(Collectors.partitioningBy((e)->e.getSalary()>8000));
    System.out.println(map2);
    System.out.println("------------------");
//    收集
    String str = employee.stream()
            .map(Employees1::getName)
            .collect(Collectors.joining(","));
    System.out.println(str);


}
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值