栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

5.Stream API (核心)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

5.Stream API (核心)

5.1 创建stream     1.什么是 Stream?

   2. Stream的操作三个步骤:

    3. 创建流的实现方式:(几种方法如下)

流的中间操作

   

5.2 筛选 / 切片

    filter:接收 Lambda ,从流中排除某些元素
    limit:截断流,使其元素不超过给定数量
    skip(n):跳过元素,返回一个舍弃了前n个元素的流;若流中元素不足n个

               ,则返回一个空 流;与 limit(n) 互补
    distinct:筛选,通过流所生成的 hashCode() 与 equals() 取除重复元

中间 操作     //没有终止操作,就不会有输出

  • 内部迭代:迭代操作由 Stream API 完成
  • 外部迭代:我们通过迭代器完成 
List emps = Arrays.asList(
    new Employee(101, "Z3", 19, 9999.99),
    new Employee(102, "L4", 20, 7777.77),
    new Employee(103, "W5", 35, 6666.66),
    new Employee(104, "Tom", 44, 1111.11),
    new Employee(105, "Jerry", 60, 4444.44)
);

@Test
public void test01(){
    emps.stream()
        .filter((x) -> x.getAge() > 35)
        .limit(3) //短路?达到满足不再内部迭代
        .distinct()  //他是通过 HashCode 和equals实现 实体类中 要重写这个方法
        .skip(1)
        .forEach(System.out::println);

}
5.3 映射 (常用)
  • map:接收 Lambda ,将元素转换为其他形式或提取信息;接受一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素
  • flatMap:接收一个函数作为参数,将流中每一个值都换成另一个流,然后把所有流重新连接成一个流
@Test
public void test02(){
    List list = Arrays.asList("aaa", "bbb", "ccc","eee",);
    list.stream()
        .map((str) -> str.toUpperCase())
               //里面是一个映射函数
        .forEach(System.out::println);
}

             FlatMap 的结果

public Stream filterCharacter(String str){
    List list = new ArrayList<>();
    for (char c : str.toCharArray()) {
        list.add(c);
    }
    return list.stream();
}

@Test
public void test03(){
    List list = Arrays.asList("aaa", "bbb", "ccc","ddd","eee");
    Test02 test02 = new Test02();
    list.stream()  // 把这个数组里数 分别转换为流,再连接为一个流
        .flatMap( 类名::filterCharacter) //静态的引用
        .forEach(System.out::println);
}
5.4 排序
  • sorted():自然排序
  • sorted(Comparator c):定制排序
     Comparable:自然排序
@Test
public void test04(){
    List list = Arrays.asList("aaa","bbb","ccc","ddd","eee");
    list.stream()
        .sorted() //默认的系统排序comparaTo()
        .forEach(System.out::println);
}
   Comparator:定制排序
@Test
public void test05(){
    emps.stream()
        .sorted((e1, e2) -> { //compara()
            if (e1.getAge().equals(e2.getAge())){
                    //先判断年龄是否一样 ,再按照姓名排序
                return e1.getName().compareTo(e2.getName());
            } else {
               //年龄优先排序
                return e1.getAge().compareTo(e2.getAge());
            }
        })
        .forEach(System.out::println);
}
 终止操作

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

  5.5 查找 / 匹配
public enum Status {
    FREE, BUSY, VOCATION;
}

@Test
public void test01(){
    List list = Arrays.asList(Status.FREE, Status.BUSY, Status.VOCATION);

    boolean flag1 = list.stream()  //获得流
        .allMatch((s) -> s.equals(Status.BUSY));
         //检查 所有的是否是全符合 忙碌状态
    System.out.println(flag1);

    boolean flag2 = list.stream()
        .anyMatch((s) -> s.equals(Status.BUSY));
         //是否能找到一个 符合里面的条件
    System.out.println(flag2);

    boolean flag3 = list.stream()
        .noneMatch((s) -> s.equals(Status.BUSY));
         //检查是否 没有这个条件的 元素
    System.out.println(flag3);

    // 避免空指针异常
    Optional op1 = list.stream()
        .findFirst();
    // 如果Optional为空 找一个替代的对象
    Status s1 = op1.orElse(Status.BUSY);
    System.out.println(s1);

    Optional op2 = list.stream()
        .findAny();
    System.out.println(op2);

    long count = list.stream()
        .count();
    System.out.println(count);
}
5.6 归约 / 收集
  • 归约:reduce(T identity, BinaryOperator) / reduce(BinaryOperator) 可以将流中的数据反复结合起来,得到一个值
  • 收集:collect 将流转换成其他形式;接收一个 Collector 接口的实现,用于给流中元素做汇总的方法
   reduce:
@Test
public void test01(){
    List list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
    Integer integer = list.stream()
        .reduce(0, (x, y) -> x + y);  //相当于与不断地递归相加 
    System.out.println(integer);
}
    collect:

List emps = Arrays.asList(
    new Employee(101, "Z3", 19, 9999.99),
    new Employee(102, "L4", 20, 7777.77),
    new Employee(103, "W5", 35, 6666.66),
    new Employee(104, "Tom", 44, 1111.11),
    new Employee(105, "Jerry", 60, 4444.44)
);

@Test
public void test02(){
    //放入List
    List list = emps.stream()
        .map(Employee::getName)
        .collect(Collectors.toList()); 
    list.forEach(System.out::println);
    
	//放入Set
    Set set = emps.stream()
        .map(Employee::getName)
        .collect(Collectors.toSet());
    set.forEach(System.out::println);

    //放入linkedHashSet
    linkedHashSet linkedHashSet = emps.stream()
        .map(Employee::getName)
        .collect(Collectors.toCollection(linkedHashSet::new));
    linkedHashSet.forEach(System.out::println);
}

@Test
public void test03(){
    //总数
    Long count = emps.stream()
        .collect(Collectors.counting());
    System.out.println(count);

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

    //总和
    Double sum = emps.stream()
        .collect(Collectors.summingDouble(Employee::getSalary));
    System.out.println(sum);

    //最大值
    Optional max = emps.stream()
        .collect(Collectors.maxBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
    System.out.println(max.get());

    //最小值
    Optional min = emps.stream()
        .map(Employee::getSalary)
        .collect(Collectors.minBy(Double::compare));
    System.out.println(min.get());
}

@Test
public void test04(){
    //分组
    Map> map = emps.stream()
        .collect(Collectors.groupingBy(Employee::getId));
    System.out.println(map);

    //多级分组
    Map>> mapMap = emps.stream()
        .collect(Collectors.groupingBy(Employee::getId, Collectors.groupingBy((e) -> {
            if (e.getAge() > 35) {
                return "开除";
            } else {
                return "继续加班";
            }
        })));
    System.out.println(mapMap);
    
    //分区
    Map> listMap = emps.stream()
        .collect(Collectors.partitioningBy((e) -> e.getSalary() > 4321));
    System.out.println(listMap);
}

@Test
public void test05(){
    //总结
    DoubleSummaryStatistics dss = emps.stream()
        .collect(Collectors.summarizingDouble(Employee::getSalary));
    System.out.println(dss.getMax());
    System.out.println(dss.getMin());
    System.out.println(dss.getSum());
    System.out.println(dss.getCount());
    System.out.println(dss.getAverage());
    
    //连接
    String str = emps.stream()
        .map(Employee::getName)
        .collect(Collectors.joining("-")); //可传入分隔符
    System.out.println(str);
}
5.7 需求解决

怎样使用 map 和 reduce 数一数流中有多少个 Employee 呢?

List emps = Arrays.asList(
    new Employee(101, "Z3", 19, 9999.99),
    new Employee(102, "L4", 20, 7777.77),
    new Employee(103, "W5", 35, 6666.66),
    new Employee(104, "Tom", 44, 1111.11),
    new Employee(105, "Jerry", 60, 4444.44)
);

@Test
public void test02(){
    Optional result = emps.stream()
        .map((e) -> 1)
        .reduce(Integer::sum);
    System.out.println(result.get());

给定一个数字列表,如何返回一个由每个数的平方构成的列表呢?(如:给定【1,2,3,4,5】,返回【1,4,9,16,25】)

@Test
public void test01(){
    List list = Arrays.asList(1, 2, 3, 4, 5);
    list.stream()
        .map((x) -> x * x)
        .forEach(System.out::println);
}
5.8 并行流
  • 并行流:就是把一个内容分成几个数据块,并用不同的线程分别处理每个数据块的流
  • Java 8 中将并行进行了优化,我们可以很容易的对数据进行操作;Stream API 可以声明性地通过 parallel() 与 sequential() 在并行流与串行流之间切换
    Fork / Join 框架:

     Fork / Join 框架与传统线程池的区别:

 Fork / Join 实现:
public class ForkJoinCalculate extends RecursiveTask {

    private static final long serialVersionUID = 1234567890L;

    private long start;
    private long end;

    private static final long THRESHPLD = 10000;

    public ForkJoinCalculate(long start, long end) {
        this.start = start;
        this.end = end;
    }

    @Override
    protected Long compute() {
        long length = end - start;

        if (length <= THRESHPLD) {
            long sum = 0;
            for (long i = start; i <= end; i++) {
                sum += i;
            }
        } else {
            long middle = (start + end) / 2;

            ForkJoinCalculate left = new ForkJoinCalculate(start, end);
            left.fork(); //拆分子任务 压入线程队列

            ForkJoinCalculate right = new ForkJoinCalculate(middle + 1, end);
            right.fork();

            return left.join() + right.join();
        }

        return null;
    }
}

public class TestForkJoin {

    
    @Test
    public void test01(){
        Instant start = Instant.now();

        ForkJoinPool pool = new ForkJoinPool();
        ForkJoinCalculate task = new ForkJoinCalculate(0, 100000000L);

        Long sum = pool.invoke(task);
        System.out.println(sum);

        Instant end = Instant.now();
        System.out.println(Duration.between(start, end).getNano());
    }

    
    @Test
    public void test02(){
        Instant start = Instant.now();

        Long sum = 0L;
        for (long i = 0; i < 100000000L; i++) {
            sum += i;
        }

        Instant end = Instant.now();
        System.out.println(Duration.between(start, end).getNano());
    }
}
   Java 8 并行流 / 串行流:
@Test
public void test03(){
    //串行流(单线程):切换为并行流 parallel()
    //并行流:切换为串行流 sequential()
    LongStream.rangeClosed(0, 100000000L)
        .parallel() //底层:ForkJoin
        .reduce(0, Long::sum);

}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/657263.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号