Java的Stream流

1. Stream

Java8的两个重大改变,一个是Lambda表达式,另一个就是本节要讲的Stream API表达式。==Stream 是Java8中处理集合的关键抽象概念==,它可以对==集合进行非常复杂的查找、过滤、筛选等操作.==

1.1 为什么使用stream流

当我们需要对集合中的元素进行操作的时候,除了必需的添加、删除、获取外,最典型的就是集合遍历。我们来体验 集合操作数据的弊端,需求如下:

一个ArrayList集合中存储有以下数据:张无忌,周芷若,赵敏,成俊杰,张三丰
需求:1.拿到所有姓张的 2.拿到名字长度为3个字的 3.打印这些数据
package demo10;
​
import java.util.ArrayList;
import java.util.List;
​

public class Test {
    public static void main(String[] args) {
//        一个ArrayList集合中存储有以下数据:张无忌,周芷若,赵敏,成俊杰,张三丰
​
//        需求:1.拿到所有姓张的 2.拿到名字长度为3个字的 3.打印这些数据
        List<String> list=new ArrayList<>();
        list.add("张无忌");
        list.add("周芷若");
        list.add("赵敏");
        list.add("程俊杰");
        list.add("张三丰");
​
        //1.拿到所有姓张的
        List<String> newList01=new ArrayList<>();
        for(String n:list){
            if(n.startsWith("张")){
                 newList01.add(n);
            }
        }
​
        //2.拿到名字长度为3个字的
        List<String> newList02=new ArrayList<>();
        for(String n:newList01){
             if(n.length()==3){
                 newList02.add(n);
             }
        }
​
        //3.打印这些数据
        for(String s:newList02){
            System.out.println(s);
        }
​
​
    }
}
​

分析:

循环遍历的弊端

这段代码中含有三个循环,每一个作用不同:

  1. 首先筛选所有姓张的人;

  2. 然后筛选名字有三个字的人;

  3. 最后进行对结果进行打印输出。

每当我们需要对集合中的元素进行操作的时候,总是需要进行循环、循环、再循环。这是理所当然的么?不是。循环 是做事情的方式,而不是目的。每个需求都要循环一次,还要搞一个新集合来装数据,如果希望再次遍历,只能再使 用另一个循环从头开始。

那Stream能给我们带来怎样更加优雅的写法呢?

Stream初体验

List<String> list=new ArrayList<>();
        list.add("张无忌");
        list.add("周芷若");
        list.add("赵敏");
        list.add("张三");
        list.add("程俊杰");
        list.add("张三丰");
​
        //
list.stream().filter(t->t.startsWith("张")).filter(t->t.length()==3).forEach(item-> System.out.println(item));

1.2 Stream流的原理

Stream流式思想类似于工厂车间的“生产流水线”,Stream流不是一种数据结构,不保存数据,而是对数据进行加工 处理。Stream可以看作是流水线上的一个工序。在流水线上,通过多个工序让一个原材料加工成一个商品。

1.3 步骤

(1)获取Stream流对象

(2) 中间操作---返回类型还是Stream流对象。

(3)终止操作---不在是Stream流对象

1.4 获取Stream流对象的方式

(1) 通过集合对象调用stream()

(2)通过Arrays获取stream流对象

(3)通过Stream流里面of方法

package demo11;
​
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
​

public class Test11 {
    public static void main(String[] args) {
        List<String> list=new ArrayList<>();
        list.add("张无忌");
        list.add("周芷若");
        list.add("赵敏");
//        Stream<String> stream = list.stream();
//        stream.forEach(System.out::println);
//        //第二种使用Arrays工具类
//        String[] arr={};
//        Stream<String> stream1 = Arrays.stream(arr);
//
//        //第三种:Stream类
//        Stream<Integer> stream2 = Stream.of(1, 2, 4, 7, 8);
        //上面的流都是串行流。并行流
        Stream<String> stringStream = list.parallelStream();
        stringStream.forEach(System.out::println);
    }
}
​

 1.5 Stream流的api方法

举个简单的例子:

假设有一个Person类和一个Person列表,现在有两个需求:1)找到年龄大于18岁的人并输出;2)找出所有中国人的数量。

@Data
class Person {
    private String name;
    private Integer age;
    private String country;
    private char sex;
​
    public Person(String name, Integer age, String country, char sex) {
        this.name = name;
        this.age = age;
        this.country = country;
        this.sex = sex;
    }
}
public class Test {
    public static void main(String[] args) {
        List<Person> personList = new ArrayList<>();
        personList.add(new Person("欧阳雪",18,"中国",'F'));
        personList.add(new Person("Tom",24,"美国",'M'));
        personList.add(new Person("Harley",22,"英国",'F'));
        personList.add(new Person("向天笑",20,"中国",'M'));
        personList.add(new Person("李康",22,"中国",'M'));
        personList.add(new Person("小梅",20,"中国",'F'));
        personList.add(new Person("何雪",21,"中国",'F'));
        personList.add(new Person("李康",22,"中国",'M'));
//1. 年龄大于18 filter:过滤掉不满足条件的元素. forEach:输出元素. ---如果没有终止函数,那么中间函数的代码不会被执行。
       personList.stream(). filter(item->{
            System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~");
            return item.getAge()>18;
        }).forEach(System.out::println);
​
        //2. 找出中国人  并统计个数: count()
        long count = personList.stream().filter(item
          -> item.getCountry().equals("中国")).count();
        System.out.println("中国人:"+count);
    }
}

(2)找出年龄最大和最小

   
 Person person = personList.stream().max(((o1, o2)
         -> o1.getAge() - o2.getAge())).get();
        Person person2 = personList.stream().min(((o1, o2) 
        -> o1.getAge() - o2.getAge())).get();
        System.out.println(person);
        System.out.println(person2);

(3)map-->

会把集合中的元素转化成另一种类型

    personList.stream().filter(item->item.getCountry().equals("中国"))
    .map(item->new P(item.getName(),item.getAge()))
    .forEach(System.out::println);

    public class Test03 {
    public static void main(String[] args) {
//        整数数组每个元素+3
        List<Integer> list = Arrays.asList(1, 17, 27, 7);
        list.stream().map(item->item+3).forEach(System.out::println);
​
        List<String> list2=Arrays.asList
                     ("hello","world","java","spring","springmvc");
        //字符串大写
        list2.stream().map(String::toUpperCase).forEach(System.out::println);
    }
}

(4)收集 collect

把处理过的集合搜集成新的集合。

  
 List<Person> personList = new ArrayList<>();
        personList.add(new Person("小梅",24,"中国",'F'));
        personList.add(new Person("欧阳雪",18,"中国",'F'));
        personList.add(new Person("Tom",24,"美国",'M'));
        personList.add(new Person("Harley",22,"英国",'F'));
        personList.add(new Person("向天笑",20,"中国",'M'));
        personList.add(new Person("李康",22,"中国",'M'));
        personList.add(new Person("Tom",21,"中国",'F'));
        personList.add(new Person("李康",22,"中国",'M'));
​
        //把Person-年龄大于20人--里面名称----新的集合。
        List<String> collect = personList.stream()
        .filter(item -> item.getAge() > 20)
        .map(item -> item.getName())
        .collect(Collectors.toList());
        System.out.println(collect);

(5)sorted排序

   List<Person> collect = personList.stream()
   .sorted((o1, o2) -> o1.getAge() - o2.getAge())
   .collect(Collectors.toList());

        System.out.println(collect);

(6) reduce规约

归约,也称缩减,顾名思义,是把一个流缩减成一个值,能实现对集合求和、求乘积和求最值操作。

  

整型集合: -----请求。[1,2,3,4]=

List<Integer> list= Arrays.asList(1,2,3,5);Optional<Integer> reduce = list.stream().reduce((t1, t2) -> t1 * t2);//t1=1, t2=2 ===>2//t1=2  t2=3===>6//t1=6  t2=5====>30System.out.println(reduce.get());

(7)查询第一个findFirst

  
      Optional<Person> first = personList.stream()
      .filter(item->item.getAge()>=18&&item.getAge()<=20).findFirst();
        System.out.println(first.get());

  1. 中间的操作: filter map sorted distinct() skip limit()

  2. 终止操作: forEach count() reduce() collect(Collectors.toList()) findFirst

​ max min

一个小例子
交易员类
public class Trader {
    private  String name;
    private  String city;
​
    public Trader(String name, String city) {
        this.name = name;
        this.city = city;
    }
​
    public String getName() {
        return name;
    }
​
    public String getCity() {
        return city;
    }
​
    @Override
    public String toString() {
        return "Trader{" +
                "name='" + name + '\'' +
                ", city='" + city + '\'' +
                '}';
    }
}
​
Transaction(交易记录)
​
public class Transaction {
    private  Trader trader; //交易员
    private  int year;
    private  int value;
    public Transaction(Trader trader, int year, int value){
        this.trader = trader;
        this.year = year;
        this.value = value;
    }
    public Trader getTrader(){
        return this.trader;
    }
    public int getYear(){
        return this.year;
    }
    public int getValue(){
        return this.value;
    }
    public String toString(){
        return "{" + this.trader + ", " +
                "year: "+this.year+", " +
                "value:" + this.value +"}";
    }
}
Trader raoul = new  Trader("Raoul", "Cambridge");
        Trader mario = new Trader("Mario", "Milan");
        Trader alan = new Trader("Alan", "Cambridge");
        Trader brian = new Trader("Brian", "Cambridge");
​
        List<Transaction> transactions = Arrays.asList(
                new Transaction(brian, 2011, 300),
                new Transaction(raoul, 2012, 1000),
                new Transaction(raoul, 2011, 400),
                new Transaction(mario, 2012, 710),
                new Transaction(mario, 2012, 700),
                new Transaction(alan, 2012, 950)
        );
​
(1) 找出2011年发生的所有交易,并按交易额排序(从低到高)。输出结果
(2) 交易员都在哪些不同的城市工作过? 
(3) 查找所有来自于剑桥的交易员,并按姓名排序。
(4) 返回所有交易员的姓名字符串,按字母顺序排序。
(5) 有没有交易员是在米兰工作的?
(6) 打印生活在剑桥的交易员的所有交易额。
(7) 所有交易中,最高的交易额是多少?
(8) 找到交易额最小的交易。
能使用方法引用的尽量用方法引用。
//(1) 找出2011年发生的所有交易,并按交易额排序(从低到高)。输出结果
        List<Transaction> collect = transactions.stream().filter(item -> item.getYear() == 2011).sorted(Comparator.comparingInt(Transaction::getValue)).collect(Collectors.toList());
        System.out.println("1、"+collect);
//        (2) 交易员都在哪些不同的城市工作过?
        List<String> collect1 = transactions.stream().map(item -> item.getTrader().getCity()).distinct().collect(Collectors.toList());
        System.out.println("2、"+collect1);
//        (3) 查找所有来自于剑桥的交易员,并按姓名排序。
        List<String> cambridge1 = transactions.stream().filter(item -> item.getTrader().getCity().equals("Cambridge")).map(item -> item.getTrader().getName()).sorted(String::compareTo).distinct().collect(Collectors.toList());
        System.out.println("3、"+cambridge1);
//        (4) 返回所有交易员的姓名字符串,按字母顺序排序。
        List<String> collect2 = transactions.stream().map(item -> item.getTrader().getName()).distinct().sorted(Collator.getInstance(Locale.CHINA)).collect(Collectors.toList());
        System.out.println("4、"+collect2);
//        (5) 有没有交易员是在米兰工作的?
        boolean milan = transactions.stream().map(item -> item.getTrader().getCity()).anyMatch(("Milan"::equals));
        System.out.println("5、"+milan);
//        (6) 打印生活在剑桥的交易员的所有交易额。
        List<Integer> cambridge = transactions.stream().filter(item -> item.getTrader().getCity().equals("Cambridge")).map(item -> item.getValue()).collect(Collectors.toList());
        System.out.println("6、"+cambridge);
        //        (7) 所有交易中,最高的交易额是多少?
        Integer integer1 = transactions.stream().map(item -> item.getValue()).max(Comparator.comparingInt(o -> o)).get();
        System.out.println("7、"+integer1);
//        (8) 找到交易额最小的交易。
        Integer integer = transactions.stream().map(item -> item.getValue()).min(Comparator.comparingInt(o -> o)).get();
        System.out.println("8、"+integer);
//        能使用方法引用的尽量用方法引用。
    }
}

输出结果为:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值