java-Stream流常见用法大全-附详细代码

1.Java Streams API 是 Java 8 中引入的一个重要特性。这个特性在 Java 8 的发布中正式出现,发布于 2014 年 3 月 18 日。Streams API 旨在提供一种更简洁和功能强大的方式来处理集合数据的操作,如过滤、映射和归约等。

2.主要设计目标

  • 简洁性:提供一种更简洁、声明性的方式来处理数据集合,避免了传统的迭代代码的复杂性。
  • 并行处理:支持并行流(parallel streams),使得开发者可以更轻松地利用多核处理器来提高性能。
  • 函数式编程:引入了函数式编程的概念,例如 lambda 表达式和方法引用,使得对数据的操作更加直观。

常用用法 :

两个代码,里面常用的方法几乎都有示例,写得不对的地方,欢迎大佬纠正

实体类

package cn.domain;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.*;

import java.math.BigDecimal;

/**
 * @author huang
 */
@Getter
@Setter
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class Product implements Comparable<Product> {
    @TableId(type = IdType.AUTO)
    private Long id;
    private String name;
    private BigDecimal price;

    @Override
    public int compareTo(Product product) {
        return this.price.compareTo( product.price);
    }


    public Product(Long id, BigDecimal price, String name) {
        this.id = id;
        this.price = price;
        this.name = name;
    }
}

测试代码和用法

package cn.xiaoyunyun.test;

import cn.xiaoyunyun.domain.Product;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Lenovo
 */
public class SteamDemo {

    public static void main(String[] args) {

        Product product = new Product();
        product.setId(Long.parseLong("123"));
        product.setPrice(new BigDecimal("1.5"));
        product.setName("冰棒");

        Product coke = new Product();
        coke.setId(Long.parseLong("456"));
        coke.setPrice(new BigDecimal("3.5"));
        coke.setName("可乐");

        Product water = new Product();
        water.setId(Long.parseLong("6789"));
        water.setPrice(new BigDecimal("2.5"));
        water.setName("矿泉水");

        Product masterK = new Product();
        masterK.setId(Long.parseLong("888"));
        masterK.setPrice(new BigDecimal("3"));
        masterK.setName("康师傅");

        Product iceTea = new Product();
        iceTea.setId(Long.parseLong("1122"));
        iceTea.setPrice(new BigDecimal("4.0"));
        iceTea.setName("冰红茶");

        Product redBull = new Product();
        redBull.setId(Long.parseLong("3344"));
        redBull.setPrice(new BigDecimal("5.0"));
        redBull.setName("红牛");

        Product eastPong = new Product();
        eastPong.setId(Long.parseLong("5566"));
        eastPong.setPrice(new BigDecimal("2.8"));
        eastPong.setName("东鹏特饮");

        Product sprite = new Product();
        sprite.setId(Long.parseLong("7788"));
        sprite.setPrice(new BigDecimal("3.2"));
        sprite.setName("雪碧");

        Product fanta = new Product();
        fanta.setId(Long.parseLong("9900"));
        fanta.setPrice(new BigDecimal("3.6"));
        fanta.setName("芬达");


        ArrayList<Product> list = new ArrayList<>();
        ArrayList<Product> listTwo = new ArrayList<>();
        list.add(product);
        list.add(coke);

        list.add(water);
        list.add(masterK);

        list.add(iceTea);
        list.add(redBull);
        list.add(eastPong);
        list.add(sprite);
        list.add(coke);
        list.add(fanta);

        listTwo.add(water);

        //转换成名字list
        List<String> nameList = list.stream().map(Product::getName).collect(Collectors.toList());
        // 过滤出价格大于 1.5 的产品
        List<BigDecimal> priceFilter = list.stream()
                .map(Product::getPrice)
                .filter(price -> price.compareTo(new BigDecimal("1.5")) > 0)
                .collect(Collectors.toList());
        priceFilter.forEach(prices -> System.out.println("product1 = " + prices));
        // 任意一个产品的名字与第一个产品的名字匹配则返回 true
        boolean any = list.stream().anyMatch(x -> x.getName().equals(list.get(0).getName()));
        System.out.println("anyMatch->任意有一个条件匹配则为" + any);
        // 所有产品的名字是否都与 listTwo 中第一个产品的名字相同
        boolean all = list.stream().allMatch(x -> x.getName().equals(listTwo.get(0).getName()));
        System.out.println("allMatch->任意有一个条件匹配则为" + all);
        // 任意一个产品的名字与 listTwo 中第一个产品的名字不匹配则返回 true
        boolean none = list.stream().noneMatch(x -> x.getName().equals(listTwo.get(0).getName()));
        System.out.println("noneMatch->任意有一个不匹配则为" + none);
        //返回集合中的第一个实例
        Optional<Product> first = list.stream().findFirst();
        System.out.println("findFirst返回第一个实例" + first);
        //这些方法在处理可能为空的值时非常有用,可以帮助避免 NullPointerException 并提供清晰的默认值处理机制。
        // 查找价格大于 8 的第一个产品的价格,若没有找到,则使用默认值
        Product deProduct = new Product();
        BigDecimal defaultPrice = new BigDecimal("0.00");
        deProduct.setPrice(defaultPrice);
        Product deProductNew = list.stream().
                filter(price -> price.getPrice().compareTo(new BigDecimal("8")) > 0).
                findFirst().orElse(deProduct);
        System.out.println("deProductNew = " + deProductNew);
        //当 Optional 为空时通过 Supplier 函数生成一个默认值。
        Product orElseGet = list.stream().
                filter(price -> price.getPrice().compareTo(new BigDecimal("8")) > 0).
                findFirst().orElseGet(() -> {
            Product defaultProduct = new Product();
            defaultProduct.setId(Long.parseLong("0"));
            defaultProduct.setName("默认");
            defaultProduct.setPrice(new BigDecimal("0.00"));
            return defaultProduct;
        });
        System.out.println("orElseGet = " + orElseGet);
        //去掉重复的数据
        List<Product> distinct = list.stream().distinct().collect(Collectors.toList());
        System.out.println("distinct = " + distinct);
        //判断数据是否重复
        long count = list.stream().map(Product::getName).distinct().count();
        if (count != list.size()) {
            System.out.println("存在重复数据,请检查数据!");
        }
        //模拟百度网盘操作
        //需要更改的list
        List<Product> updateList = list.stream().filter(x -> x.getId() != null).map(x -> {
            Product po = new Product();
            po.setId(x.getId());
            po.setName(x.getName());
            return po;
        }).collect(Collectors.toList());
        //需要删除的list
        // 假设有一个数据库的数据
        ArrayList<Product> mysqlList = new ArrayList<>();
        List<Long> deleteList = mysqlList.stream().map(Product::getId).filter(x -> updateList.stream().noneMatch(y -> x.equals(y.getId()))).collect(Collectors.toList());
        // 新增的数据
        List<Product> insertList = list.stream().filter(x -> x.getId() == null).map(x -> {
            Product po = new Product();
            po.setId(x.getId());
            po.setName(x.getName());
            return po;
        }).collect(Collectors.toList());
        //先删除 再新增 再修改 baseMapper.deleteByIds(deleteList);
        list.stream().sorted()
                .forEach(System.out::println);
        //如果在类中没实现Comparable     会报Exception in thread "main" java.lang.ClassCastException: product类放在后面了
        //如果按照价格降序的写法
        list.stream().sorted(Comparator.comparing(Product::getPrice).reversed())
                .forEach(System.out::print);
        //返回一个 Optional<Product>,该 Optional 包含流中价格最大的 Product 对象。如果流为空,则返回 Optional.empty()
        Optional<Product> maxProduct = list.stream().max(Comparator.comparing(Product::getPrice));
        System.out.println("用了max会返回该集合中最大的一个价格最大的maxProduct = " + maxProduct);
        //结合 ifPresent一起使用 如果 maxPriceProduct 有值(即流不为空),则打印出价格最高的产品。
        maxProduct.ifPresent(productIP -> System.out.println("不为null的时候返回价格最高的商品" + productIP));

        //返回一个 Optional<Product>,该 Optional 包含流中价格最小的 Product 对象。如果流为空,则返回 Optional.empty()            测试list为null的情况 list.removeAll(list);
        Optional<Product> minProduct = list.stream().min(Comparator.comparing(Product::getPrice));
        System.out.println("用了min会返回该集合中最大的一个价格最小的minProduct = " + minProduct);
        //用于从流中找到任意一个元素。它返回一个 Optional 对象,这个对象可能包含流中的一个元素,也可能为空(如果流为空)。如果是顺序流的的话,会返回第一个,用并行流的话会返回随机一个
        Optional<Product> anyOneProduct = list.stream().findAny();
        System.out.println("用了findAny会返回该集合中任意一个元素 = " + anyOneProduct);
        Optional<Product> anyParallelProduct = list.parallelStream().findAny();
        System.out.println("用了parallelStream 中的findAny会返回该集合中任意一个元素 = " + anyParallelProduct);
        //验证parallelStream
        int j = 100;
        for (int i = 0; i < j; i++) {
            Optional<Product> any1 = list.parallelStream().findAny();
            System.out.println("any1 = " + any1 + i);
        }
        // flatMap 方法接受一个函数,这个函数将流中的每个元素转换成一个新的流(或其他可迭代对象)。然后,flatMap 将这些流合并成一个单一的
        // 示例 1  提取所有产品的价格并合并成一个流
        List<BigDecimal> flatList = list.stream().
                flatMap(productFlat -> Arrays.stream(new BigDecimal[]{productFlat.getPrice()})).
                collect(Collectors.toList());
        System.out.println("flatList = " + flatList);

        // 处理 List<Product> 列表的嵌套列表
        // 假设这些是 Product 类的对象,已经按题目代码创建好
        List<Product> list1 = Arrays.asList(
                new Product(123L, new BigDecimal("1.5"), "冰棒"),
                new Product(456L, new BigDecimal("3.5"), "可乐")
        );

        List<Product> list2 = Arrays.asList(
                new Product(6789L, new BigDecimal("2.5"), "矿泉水"),
                new Product(888L, new BigDecimal("3.0"), "康师傅")
        );

        List<List<Product>> nestedList = Arrays.asList(list1, list2);

        List<Product> allProducts = nestedList.stream()
                .flatMap(List::stream)
                .collect(Collectors.toList());
        //如果直接list1.addAll(list2);    UnsupportedOperationException,因为 Arrays.asList 返回的列表是固定大小的。你不能修改这个列表,比如添加或删除元素。
        //另外一种写法
        ArrayList<Object> list3 = new ArrayList<>();
        list3.addAll(list1);
        list3.addAll(list2);
        System.out.println(allProducts);
        System.out.println(list3);

        // 使用 mapToInt 计算所有产品价格乘以 2 后的总和  乘以 2 并转换为 int
        int total = list.stream()
                .mapToInt(p -> p.getPrice().multiply(BigDecimal.valueOf(2)).intValue())
                .sum();
        // 精度计算不够
        System.out.println("Total price after doubling: " + total);
        // 计算正确 价格x2并累加
        BigDecimal reduce = list.stream().map(Product::getPrice).
                map(n -> n.multiply(BigDecimal.valueOf(2)))
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        System.out.println("过滤出价格并且乘以2,然后一直累加结果 = " + reduce);
        //flatMapToDouble, flatMapToInt, 和 flatMapToLong 是 Java Stream API 中的三个方法,用于将流中的元素映射为原始类型流。这些方法常用于处理原始数据类型,提供高效的操作方式。
        // skip 跳过第几个 limit 限制输出的元素为 2 个
        list.stream().skip(3)
                .limit(2).forEach(System.out::println);
        System.out.println("forEachOrdered >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
        //没有并行流的情况下这两个是等价的
        list.stream().forEachOrdered(System.out::println);
        list.forEach(System.out::println);
        //forEachOrdered 常用于需要保持特定顺序输出的业务场景,特别是在处理并行流时。
        List<Integer> listNumber = Arrays.asList(1, 4, 3, 2, 5);
        listNumber.parallelStream().forEachOrdered(System.out::println);

        //peek() 是 Java Stream API 中的一个中间操作,用于对流中的每个元素进行查看和处理,但不会改变流的元素。它通常用于调试或查看流中的元素。
        List<Product> collect = list.stream().
                peek(peek -> System.out.println("peek = " + peek.getName())).
                collect(Collectors.toList());

        //iterator() 方法用于从流中获取一个迭代器。这个迭代器可以用来遍历流中的元素
        list.stream().iterator();
        // 在 Java 中,迭代器(Iterator)和增强型 for 循环(也称为“for-each”循环)是遍历集合和数组的两种常用方法。它们各有优缺点和适用场景。
        List<Product> removedProducts = new ArrayList<>();
        Iterator<Product> iterator = list.iterator();
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
        while (iterator.hasNext()) {
            Product product3 = iterator.next();
            if (product3.getPrice().compareTo(new BigDecimal("3.5")) == 0) {
                removedProducts.add(product3);
                iterator.remove();
            }
        }
        System.out.println("Removed products: " + removedProducts);
        System.out.println("删除了价格为3.5的产品: " + list);

        //list.stream().dropWhile() 是 Java Stream API 中的方法,用于在流中跳过满足指定条件的元素,直到遇到第一个不满足条件的元素为止。之后,流中的所有剩余元素都会被保留。
        list.stream().dropWhile(product1 -> product1.getName().
                equals("可乐")).
                forEach(System.out::println);

        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 3, 6, 7, 8, 9);

        // 使用 dropWhile 方法  跳过所有小于 5 的元素
        numbers.stream()
                .dropWhile(n -> n < 5)
                .forEach(System.out::println);

        List<String> stringList = list.stream().map(Product::getName).
                dropWhile(product1 -> !product1.equals("可乐")).
                collect(Collectors.toList());

        System.out.println(" = >>>>>>>>>>>>>>>>>>>>>>>>>>>" + stringList);
        // 使用 takeWhile  方法
        List<Integer> takeWhileNumbers = Arrays.asList(1, 2, 3, 4, 5, 7, 8, 9);
        List<Integer> result = takeWhileNumbers.stream()
                .takeWhile(n -> n < 5)
                .collect(Collectors.toList());
        // 输出: [1, 2, 3, 4]
        System.out.println(result);

        // 使用 sequential  方法   是一个用于将流的处理方式从并行模式转换回顺序模式的方法。虽然 sequential() 不是直接链式操作的常见方法,但它的作用是在流链中将流重新设置为顺序流。
        List<Integer> demoNumbers = Arrays.asList(1, 2, 3, 4, 5);
        // 创建并行流  将并行流转换回顺序流 映射操作 收集结果
        List<Integer> sequentialResult = demoNumbers.parallelStream()
                .sequential()
                .map(n -> n * 2)
                .collect(Collectors.toList());
        System.out.println(sequentialResult);
        // spliterator() 是 Stream 接口中的一个方法,用于返回一个 Spliterator 对象。Spliterator 是一个新的接口,提供了一种遍历和分割数据源的方式,支持并行操作。
        list.stream().spliterator();
        // 这两个找了百度说是无效的 看了源码也不是java实现的
        list.stream().notify();
        list.stream().notifyAll();
    }
}

























如果工作中碰到其他的我再补充~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值