Java_Stream流

目录
1.什么是Stream
2.API功能举例
-- 2.1 串行流与并行流
-- 2.1.1 串行流与并行流的获取方式
-- 2.1.2 流的操作
--- 1. filter 过滤
--- 2. distinct 去重
--- 3. sorted 排序
--- 4. limit 取前 n 个元素
--- 5. skip 跳过前n个元素
--- 6. map 将一种数据类型流集转为另一种数据类型流集
--- 7. flatMap
--- 8.allMatch(都匹配) - anyMatch(任一匹配) - noneMatch(没有匹配)
--- 9. 分组
--- 10. Stream流 (Collectors中的) 的其他功能
3.Stream的应用场景

1.什么是Stream

Java 中的 Stream 与 Android 中的 RxJava 思想有些相同, 都是基于函数的链式编程; 但是 RxJava 由于Android ui线程等相关机制的原因, 功能更加强大一些, 最大的区别就是 Stream 不能主动切换线程;

在 Java 中称 Stream 为流, 是因为经常会用流去对一些数据集进行一些流水线的操作 ( 如过滤,排序等操作, 用正常的方式代码会比较复杂, 通过Stream流可以减少代码量和提高效率 ), 然后就可以得到想要的结果;

  • RxJava 是基于事件发送接收的, 具有可观测序列的库;
  • Stream 也可以理解为基于事件发送的流, 想到拿到最终的返回结果, 需要有结束流的函数;

2.API功能举例

示例准备代码 (User类):

public class User {
    //姓名
    String name;
    //年龄
    Integer age;
    //性别
    Integer sex;
    //所在省市
    String address;
}

2.1 串行流与并行流

2.1.1 串行流与并行流的获取方式

  • List 获取
    • 串行流获取
      Stream stream = list.stream();
      
    • 并行流获取
      Stream userStream = list.parallelStream();
      
  • Set 获取
    • 串行流获取
       Stream userStream = set.stream();
      
    • 并行流获取
      Stream userStream = set.parallelStream();
      
  • Map 获取

    Map集想要获取Stream流只能通过 key 集 - value 集 - 或者 key-value集来获取;

并行流会开线程进行操作, 虽然互不干扰, 但是难以自行控制线程的切换
示例代码

public class StreamTest {
    public static void main(String[] args) throws IOException {
        List list = Arrays.asList(
                new User("钢铁侠", 30, 0, "华盛顿"),
                new User("蜘蛛侠", 20, 0, "华盛顿"),
                new User("赵丽颖", 30, 1, "湖北武汉市"),
                new User("詹姆斯", 40, 0, "洛杉矶"),
                new User("李世民", 40, 0, "山西省太原市"),
                new User("蔡徐坤", 20, 1, "陕西西安市"),
                new User("葫芦娃的爷爷", 40, 0, "山西省太原市")
        );
        list.parallelStream().map(a -> {
            System.out.println(Thread.currentThread() + "-11111-" + a.name);
            return a.name;
        }).forEach(a -> System.out.println(Thread.currentThread() + "-22222-" + a));
    }
}
打印结果
Thread[ForkJoinPool.commonPool-worker-5,5,main]-11111-葫芦娃的爷爷
Thread[ForkJoinPool.commonPool-worker-3,5,main]-11111-蜘蛛侠
Thread[main,5,main]-11111-李世民
Thread[ForkJoinPool.commonPool-worker-5,5,main]-2222-葫芦娃的爷爷
Thread[ForkJoinPool.commonPool-worker-7,5,main]-11111-钢铁侠
Thread[ForkJoinPool.commonPool-worker-7,5,main]-2222-钢铁侠
Thread[ForkJoinPool.commonPool-worker-5,5,main]-11111-蔡徐坤
Thread[ForkJoinPool.commonPool-worker-5,5,main]-2222-蔡徐坤
Thread[ForkJoinPool.commonPool-worker-5,5,main]-11111-詹姆斯
Thread[ForkJoinPool.commonPool-worker-3,5,main]-2222-蜘蛛侠
Thread[ForkJoinPool.commonPool-worker-5,5,main]-2222-詹姆斯
Thread[main,5,main]-2222-李世民
Thread[ForkJoinPool.commonPool-worker-7,5,main]-11111-赵丽颖
Thread[ForkJoinPool.commonPool-worker-7,5,main]-2222-赵丽颖

并行流相关内容待扩充......

2.1.2 流的操作

1. filter 过滤
public static void main(String[] args) throws IOException {
    List list = Arrays.asList(
        new User("钢铁侠", 40, 0, "华盛顿"),
        new User("蜘蛛侠", 20, 0, "华盛顿"),
        new User("赵丽颖", 30, 1, "湖北武汉市"),
        new User("詹姆斯", 35, 0, "洛杉矶"),
        new User("李世民", 60, 0, "山西省太原市"),
        new User("蔡徐坤", 20, 1, "陕西西安市"),
        new User("葫芦娃的爷爷", 70, 0, "山西省太原市"));
    // 过滤掉年龄大于等于40的对象
    list.stream().filter(a -> a.age >= 40).forEach(b -> System.out.println(b));
}
打印结果
User{name='钢铁侠', age=40, sex=0, address='华盛顿'}
User{name='李世民', age=60, sex=0, address='山西省太原市'}
User{name='葫芦娃的爷爷', age=70, sex=0, address='山西省太原市'}
2. distinct 去重

去重的时候如果数据是引用类型对象, 需要重写其 hashCode() 和 equals() 方法; 唯一性是通过这两个函数去判断的;

public static void main(String[] args) throws IOException {
    List list = Arrays.asList(
        new User("钢铁侠", 40, 0, "华盛顿"),
        new User("蜘蛛侠", 20, 0, "华盛顿"),
        new User("赵丽颖", 30, 1, "湖北武汉市"),
        new User("赵丽颖", 30, 1, "湖北武汉市"),
        new User("詹姆斯", 35, 0, "洛杉矶"),
        new User("詹姆斯", 35, 0, "洛杉矶"),
        new User("李世民", 60, 0, "山西省太原市"),
        new User("蔡徐坤", 20, 1, "陕西西安市"),
        new User("蔡徐坤", 20, 1, "陕西西安市"),
        new User("葫芦娃的爷爷", 70, 0, "山西省太原市"));
    list.stream().distinct().forEach(b -> System.out.println(b));
}
打印结果
User{name='钢铁侠', age=40, sex=0, address='华盛顿'}
User{name='蜘蛛侠', age=20, sex=0, address='华盛顿'}
User{name='赵丽颖', age=30, sex=1, address='湖北武汉市'}
User{name='詹姆斯', age=35, sex=0, address='洛杉矶'}
User{name='李世民', age=60, sex=0, address='山西省太原市'}
User{name='蔡徐坤', age=20, sex=1, address='陕西西安市'}
User{name='葫芦娃的爷爷', age=70, sex=0, address='山西省太原市'}
3. sorted 排序
public static void main(String[] args) throws IOException {
    List list = Arrays.asList(
        new User("钢铁侠", 40, 0, "华盛顿"),
        new User("蜘蛛侠", 20, 0, "华盛顿"),
        new User("赵丽颖", 30, 1, "湖北武汉市"),
        new User("詹姆斯", 35, 0, "洛杉矶"),
        new User("李世民", 60, 0, "山西省太原市"),
        new User("蔡徐坤", 20, 1, "陕西西安市"),
        new User("葫芦娃的爷爷", 70, 0, "山西省太原市"));
    list.stream().sorted((a, b) -> b.age - a.age).forEach(b -> System.out.println(b));
}
打印结果
User{name='葫芦娃的爷爷', age=70, sex=0, address='山西省太原市'}
User{name='李世民', age=60, sex=0, address='山西省太原市'}
User{name='钢铁侠', age=40, sex=0, address='华盛顿'}
User{name='詹姆斯', age=35, sex=0, address='洛杉矶'}
User{name='赵丽颖', age=30, sex=1, address='湖北武汉市'}
User{name='蜘蛛侠', age=20, sex=0, address='华盛顿'}
User{name='蔡徐坤', age=20, sex=1, address='陕西西安市'}
4. limit 取前 n 个元素
List list = Arrays.asList(
    new User("钢铁侠", 40, 0, "华盛顿"),
    new User("蜘蛛侠", 20, 0, "华盛顿"),
    new User("赵丽颖", 30, 1, "湖北武汉市"),
    new User("詹姆斯", 35, 0, "洛杉矶"),
    new User("李世民", 60, 0, "山西省太原市"),
    new User("蔡徐坤", 20, 1, "陕西西安市"),
    new User("葫芦娃的爷爷", 70, 0, "山西省太原市"));
list.stream().limit(3).forEach(b -> System.out.println(b));
打印结果
User{name='钢铁侠', age=40, sex=0, address='华盛顿'}
User{name='蜘蛛侠', age=20, sex=0, address='华盛顿'}
User{name='赵丽颖', age=30, sex=1, address='湖北武汉市'}
5. skip 跳过前n个元素
List list = Arrays.asList(
    new User("钢铁侠", 40, 0, "华盛顿"),
    new User("蜘蛛侠", 20, 0, "华盛顿"),
    new User("赵丽颖", 30, 1, "湖北武汉市"),
    new User("詹姆斯", 35, 0, "洛杉矶"),
    new User("李世民", 60, 0, "山西省太原市"),
    new User("蔡徐坤", 20, 1, "陕西西安市"),
    new User("葫芦娃的爷爷", 70, 0, "山西省太原市"));
list.stream().skip(3).forEach(b -> System.out.println(b));
打印结果
User{name='詹姆斯', age=35, sex=0, address='洛杉矶'}
User{name='李世民', age=60, sex=0, address='山西省太原市'}
User{name='蔡徐坤', age=20, sex=1, address='陕西西安市'}
User{name='葫芦娃的爷爷', age=70, sex=0, address='山西省太原市'}
6. map 将一种数据类型流集转为另一种数据类型流集
public static void main(String[] args) throws IOException {
    List list = Arrays.asList(
        new User("钢铁侠", 40, 0, "华盛顿"),
        new User("蜘蛛侠", 20, 0, "华盛顿"),
        new User("赵丽颖", 30, 1, "湖北武汉市"),
        new User("詹姆斯", 35, 0, "洛杉矶"),
        new User("李世民", 60, 0, "山西省太原市"),
        new User("蔡徐坤", 20, 1, "陕西西安市"),
        new User("葫芦娃的爷爷", 70, 0, "山西省太原市"));
    // 将 user 的 name 取出作为字符串集合
    list.stream().map(a->new String(a.name)).forEach(b-> System.out.println(b));
}
打印结果
钢铁侠
蜘蛛侠
赵丽颖
詹姆斯
李世民
蔡徐坤
葫芦娃的爷爷
7. flatMap

将原有的数据流集中的内容合并为一个新的流集

public static void main(String[] args) throws IOException {
    List list = Arrays.asList(
        new User("钢铁侠", 40, 0, "华 盛 顿"),
        new User("蜘蛛侠", 20, 0, "华盛顿"),
        new User("赵丽颖", 30, 1, "湖北 武汉市"),
        new User("詹姆斯", 35, 0, "洛杉 矶"),
        new User("李世民", 60, 0, "山西省太原市"),
        new User("蔡徐坤", 20, 1, "陕西西 安市"),
        new User("葫芦娃的爷爷", 70, 0, "山西 省 太原市"));
    // 下面示例就是将User类型的流集中的每一个User的address,合并为了一个String类型的新流集然后再遍历
    list.stream().flatMap(a->{
        ArrayList strings = new ArrayList();
        strings.add(a.address);
        return strings.stream();
    }).forEach(a-> System.out.println(a));
    System.out.println("=============================");
    // 下面示例就是将User类型的流集中的每一个User的address,拆成字符串数组流集
    // 然后将字符串数组中的每一个元素合并为一个字符串流集
    // 从打印结果可以看出来其遍历过程
    list.stream().map(a->a.address.split(" "))
        .flatMap(a->Arrays.stream(a))
        .forEach(a-> System.out.println(a));
}
打印结果
华 盛 顿
华盛顿
湖北 武汉市
洛杉 矶
山西省太原市
陕西西 安市
山西 省 太原市
=============================
华
盛
顿
华盛顿
湖北
武汉市
洛杉
矶
山西省太原市
陕西西
安市
山西
省
太原市
8.allMatch(都匹配) - anyMatch(任一匹配) - noneMatch(没有匹配)
public static void main(String[] args) throws IOException {
    List list = Arrays.asList(
        new User("钢铁侠", 40, 0, "华盛顿"),
        new User("蜘蛛侠", 20, 0, "华盛顿"),
        new User("赵丽颖", 30, 1, "湖北武汉市"),
        new User("詹姆斯", 35, 0, "洛杉矶"),
        new User("李世民", 60, 0, "山西省太原市"),
        new User("蔡徐坤", 20, 1, "陕西西安市"),
        new User("葫芦娃的爷爷", 70, 0, "山西省太原市")
    );
    // 所有的User的 age= 20;
    System.out.println(list.stream().allMatch(a -> a.age == 20));// false
}
9. 分组
public static void main(String[] args) throws IOException {
    List list = Arrays.asList(
        new User("钢铁侠", 30, 0, "华盛顿"),
        new User("蜘蛛侠", 20, 0, "华盛顿"),
        new User("赵丽颖", 30, 1, "湖北武汉市"),
        new User("詹姆斯", 40, 0, "洛杉矶"),
        new User("李世民", 40, 0, "山西省太原市"),
        new User("蔡徐坤", 20, 1, "陕西西安市"),
        new User("葫芦娃的爷爷", 40, 0, "山西省太原市")
    );
    // 相同的年龄分到一个组;
    Map> collect = 
        list.stream().collect(Collectors.groupingBy(a -> a.age));
    System.out.println(collect);
}
打印结果
{20=[
User{name='蜘蛛侠', age=20, sex=0, address='华盛顿'}, 
User{name='蔡徐坤', age=20, sex=1, address='陕西西安市'}], 
40=[
User{name='詹姆斯', age=40, sex=0, address='洛杉矶'}, 
User{name='李世民', age=40, sex=0, address='山西省太原市'}, 
User{name='葫芦娃的爷爷', age=40, sex=0, address='山西省太原市'}], 
30=[
User{name='钢铁侠', age=30, sex=0, address='华盛顿'}, 
User{name='赵丽颖', age=30, sex=1, address='湖北武汉市'}
]}

collect 不仅可以分组,将Stream 与 Collector 结合起来(主要是Collectors中所拥有的功能, 不必管它怎么实现, 必竟面向对象编程) 可以做很多其他的操作;

10. Stream流 (Collectors中的) 的其他功能
  • 查找第一个符合条件的元素
  • 查找任意一个符合条件的元素
  • 求和
  • 求最大值
  • 求最小值
  • 平均值
    ......等等

3.Stream的应用场景

例如: 把原来复杂的sql查询或者数据的处理,一遍又一遍地for循环的复杂代码重构,让代码更简洁易懂,可读性强

你可能感兴趣的:(Java_Stream流)