java Stream操作

news/2024/12/22 23:42:13/

java stream操作

Stream是什么

Stream又称为流,可以将集合转换为一种流,对集合中的每个元素进行一系列的流式操作,流并不存储元素,对流的操作也不会修改数据源

数据源 ------转换为--》流----》进行中间操作----》终止操作

多个中间操作可以连接起来形成一个流水线,除非流水线触发终止操作,否则中间操作不会执行任何处理,在终止操作时一次性全部处理

转化为流

使用stream()或者parallelStream()方法将集合转为流

生成流

可以使用Stream.generate来生成流,产生一个无限流,通过反复调用函数来生成流

Stream<String> stream = Stream.generate(()->"Echo");

也可以使用Stream.of来生成Stream,产生一个给定值的流

Stream<String> stream1 = Stream.of("hello""java8");

可以用Stream.empty生成一个不包含任何元素的流

Stream<Object> empty = Stream.empty();

可以使用Arrays.stream根据数据来生成流

Stream<String> stream2 = Arrays.stream(new String[]{"hello""java8"});

中间操作

中间操作是惰性求值的,只进行描述Stream,而不产生新的集合

筛选
filter

过滤操作,只返回为true(满足Predicate断言条件)的数据

// filter方法接收的是Predicate
Stream<T> filter(Predicate<? super T> predicate);
/**
* filter  接收lambda,从流中排除某些元素
*/

public static void testFilter(){
  // 中间操作
  // 使用的Predicate   boolean test(T t);
  Stream<String> stream = list.stream()
    .filter(e ->
            {
              System.out.println("filter中间操作");
              return e.equals("张三");
            }
           );
  // 这时中间操作还没有执行执行
  System.out.println("----中间操作结束----");
  //终止操作:一次执行全部操作
  stream.forEach(
    System.out::println
  );
}
distinct

去重

/**
* distinct 筛选,通过流所生成元素的hashCode()和equals()方法去重
*/

public static void testDistinct(){
  list.stream().distinct().forEach(System.out::println);
}
切片
limit

返回前n个元素

/**
* limit 截断流,使其元素不超过给定数量
*/

public static void testLimit(){
  list.stream().limit(2).forEach(System.out::println);
}
skip

去除(跳过)前n个元素

/**
* skip 跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回空流
*/

public static void testSkip(){
  list.stream().skip(2).forEach(System.out::println);
}
public static void testLimitAndSkip(){
  System.out.println("--------先limit再skip---------");
  list.stream().limit(2).skip(1).forEach(System.out::println);
  System.out.println("--------先skip再limit---------");
  list.stream().skip(1).limit(2).forEach(System.out::println);
}

注意:在limit和skip搭配使用的时候,两个的顺序不同会导致结果不同

  • 先进行limit,再进行skip时,会选择前两个数据,然后再跳过第一个数据,只会筛选出一条数据
  • 先进行skip,再进行limit时,会先跳过一条数据,在选择剩下数据的前两条,最终会筛选出两条数据
排序
sorted

排序可以有两种排序方式,第一种是进行排序的类要实现Comparable接口,第二种是在自己实现一个Comparator接口

 /**
 * sorted()自然排序  Comparable 所要排序的类必须实现Comparable接口
 */

public static void test(){
  list.stream().map(User::getAge).sorted().forEach(System.out::println);
}

/**
* sorted(Comparator com) 定制排序(Comparator)
*/

public static void test1(){
  list.stream().sorted(
    (o1, o2) -> {
      if(o1.getAge() > o2.getAge()){
        return -1;
      }
      return 0;
    }
  ).forEach(System.out::println);
}
映射
map

转换功能,将mapper应用于当前流中的所有元素所产生的结果,其将一种类型的值转换成了另一种类型

// map方法接收的参数为Function接口
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
/**
* map 接收lambda,将元素转换为其他形式或提取信息。接收一个函数作为函数,
* 该函数会被应用到每个元素上,并将其映射成一个新的元素
*
* 如果函数返回的是一个流的话,使用map会使得流里存储着多个流
*/

public static void testMap(){
  // 使用Function  R apply(T t);
  list.stream().map(User::getAge).forEach(System.out::println);
}
flatmap

将多个Stream合并成一个Stream,将mapper应用于当前流中所有元素所产生的结果连接到一起(每一个结果都是一个流)

// flatMap方法接收的参数为Function接口
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);
/**
* flatMap  接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
*
* 如果函数返回的是一个流,使用flatMap会使得函数返回的流中的元素放到一个流中
*/

public static void testFlatMap(){
  // 要求Function  R apply(T t);中返回值是一个Stream流
  List<String> add = new ArrayList<>();
  add.add("添加元素");
  List<String> strings = list.stream().map(User::getName).collect(Collectors.toList());
  strings.stream().flatMap(
    TestStreamApi1::joinStream
  ).forEach(System.out::println);
}

终止操作

allMatch

流中所有元素都要匹配给定的条件为true,否则为false 相当于且

/**
* allMatch测试
*/

public static void testAllMatch(){
  boolean isSex = list.stream().allMatch(
    l -> l.getSex() == 0
  );
  System.out.println(isSex);
}
anyMatch

流中有任意一条数据匹配给定的条件为true,否则为false 相当于并

/**
* anyMatch测试
*/

public static void testAnyMatch(){
  boolean isSex = list.stream().anyMatch(
    l -> l.getSex() == 0
  );
  System.out.println(isSex);
}
noneMatch

流中所有的数据都不匹配给定条件时为true,否则为false 相当于非

/**
* noneMatch测试
*/

public static void testNoneMatch(){
  boolean isSex = list.stream().noneMatch(
    l -> l.getSex() == 0
  );
  System.out.println(isSex);
}
findFirst

找到第一个元素

/**
* findFirst测试
*/

public static void testFindFirst(){
  User user = list.stream().sorted(
    ((o1, o2) -> {
      if(o1.getAge() > o2.getAge()){
        return -1;
      } else if(o1.getAge() < o2.getAge()){
        return 1;
      }
      return 0;
    })
  ).findFirst().get();
  System.out.println(user);
}
findAny

找到其中任意一个元素

/**
* findAny测试
*/

public static void testFindAny(){
  User user = list.stream().filter(
    l -> l.getSex() == 0
  ).findAny().get();
  System.out.println(user);
}
count

返回流中元素的数量

/**
* count测试
*/

public static void testCount(){
  long count = list.stream().count();
  System.out.println(count);
}
max

返回流中根据比较之后的最大值元素

// max方法接收的是Comparator接口
Optional<T> max(Comparator<? super T> comparator);
/**
* max测试
*/

public static void testMax(){
  User user = list.stream().max(
    ((o1, o2) -> {
      if(o1.getAge() > o2.getAge()){
        return 1;
      } else if(o1.getAge() < o2.getAge()){
        return -1;
      }
      return 0;
    })
  ).get();
  System.out.println(user);
}
min

返回流中根据比较之后的最小值元素

// min方法接收的是Comparator接口
Optional<T> min(Comparator<? super T> comparator);
/**
* min测试
*/

public static void testMin(){
  User user = list.stream().min(
    ((o1, o2) -> {
      if(o1.getAge() > o2.getAge()){
        return 1;
      } else if(o1.getAge() < o2.getAge()){
        return -1;
      }
      return 0;
    })
  ).get();
  System.out.println(user);
}

归约和收集

归约reduce

使用reduce来进行运算,从一组值中生成一个值

像count()、max()、min()、sum()这些内部其实也是使用的reduce

// reduce方法接收的是BinaryOperator接口(二元运算操作)  
Optional<T> reduce(BinaryOperator<T> accumulator);
/**
* 归约  将流中元素反复结合起来,得到一个值
* reduce(T identity, BinaryOperator<T> accumulator) /BinaryOperator<T> accumulator/U identity,
*                  BiFunction<U, ? super T, U> accumulator,
*                  BinaryOperator<U> combiner
*/

public static void testReduce(){
  List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9);
  // BinaryOperator  二元运算   R apply(T t, U u);
  int sum = list.stream().reduce((x, y) -> x+y).get();
  System.out.println(sum);
}
收集collect

根据不同的收集器collect(Collectors.toList())、collect(Collectors.toSet())来返回不同的集合

/**
* 收集 collect -- 将流转换为其他形式 接收一个Collector接口的实现,用于给Stream中元素做汇总的方法
*/

public static void testCollect(){
  // Collector是一个接口  有一个Collectors提供了各种转换方式
  List<String> strings = list.stream().map(User::getName).collect(Collectors.toList());
  System.out.println(strings);
}
数据汇总

使用summingInt可以获取总和

Integer sum = list.stream().collect(Collectors.summingInt(User::getAge));
System.out.println(sum);

使用averagingInt可以计算平均值

Double average = list.stream().collect(Collectors.averagingInt(User::getAge));
System.out.println(average);

使用summarizingInt可以获取个数、总和、平均值、最大值和最小值

IntSummaryStatistics summaryStatistics = list.stream().collect(Collectors.summarizingInt(User::getAge));
// IntSummaryStatistics{count=6, sum=117, min=8, average=19.500000, max=30}
System.out.println(summaryStatistics);
连接字符串

joining用于连接字符串

String join = list.stream().map(User::getName).collect(Collectors.joining(","));
System.out.println(join);
数据分组

collect还可以对数据进行分组

Map<Long, List<Long>> collect = adUnits.stream().collect(Collectors.groupingBy(AdUnit::getAd_campaign_id,
        Collectors.mapping(AdUnit::getId, Collectors.toList())));

groupingBy收集器接受一个分类函数,用来对数据分组

数据分区

partitioningBy用于数据分区

Map<Boolean,List<User>> join = list.stream().collect(Collectors.partitioningBy(user -> user.getSex() == 0));
// {false=[User{id=2, name='李四', age=20, sex=1}, User{id=4, name='赵六', age=25, sex=1}], true=[User{id=1, name='张三', age=18, sex=0}, User{id=3, name='王五', age=16, sex=0}, User{id=5, name='张三', age=30, sex=0}, User{id=6, name='张三', age=8, sex=0}]}

System.out.println(join);

分区就是分组的一个特殊情况

Optional的使用

当初java8打着去除空指针的旗号推出了Optional,但是很多人用起来发现其实和判断是否为null没什么区别

其实有效地使用Optional的关键是要使用这样的方法:它的值不存在的情况下产生一个可替代物,而只有在值存在的情况下才会使用这个值

// 提供一个默认值,在Optional为空的时候使用默认值
public T orElse(T other)
// 提供一个默认值,在Optional为空的时候使用默认值(调用other来产生默认值)
public T orElseGet(Supplier<? extends T> other)
// 提供一个默认值,在Optional为空的时候抛出异常(调用exceptionSupplier来产生异常)
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X
// 如果Optional不为空,将值传给consumer
public void ifPresent(Consumer<? super T> consumer)
// 产生该Optional的值传递给mapper后的结果,只要这个Optional不为空且结果不为null,否则产生一个空Optional
public<U> Optional<U> map(Function<? super T, ? extends U> mapper)

而对于有些人总是使用optional.isPresent()来判断是不是空,其实和之前判断value != null没什么区别,这种情况使用Optional没有任何好处

[https://zhhll.icu/2020/java基础/java8/1.java Stream操作/](https://zhhll.icu/2020/java基础/java8/1.java Stream操作/)

本文由 mdnice 多平台发布


http://www.ppmy.cn/news/1222657.html

相关文章

2311rust到31版本更新

1.27.1稳定版 在此修补程序前,下例在编译器内部恐慌. fn main() {let a vec!["".to_string()];a.iter().enumerate().take_while(|(_, &t)| false).collect::<Vec<_>>(); }1.27.1拒绝上述代码,并显示以下错误消息: error[E0507]: cannot move ou…

【Gateway】基于ruoyi-cloud-plus项目,gateway局部过滤器和过滤返回以及集成nacos

1.使用Gateway路由转发 1.1标题引入依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency>1.2添加YML配置 spring:cloud:gateway:# 打印请求日志(自定义)…

使用requests库设置no_proxy选项的方法

问题背景 在使用requests库进行HTTP请求时&#xff0c;如果需要使用爬虫IP服务器&#xff0c;可以通过设置proxies参数来实现。proxies参数是一个字典&#xff0c;其中包含了爬虫IP服务器的地址和端口号。然而&#xff0c;当前的requests库并不支持通过proxies参数来设置no_pr…

系列三、GC垃圾回收【总体概览】

一、GC垃圾回收【总体概览】 JVM进行GC时&#xff0c;并非每次都对上面的三个内存区域&#xff08;新生区、养老区、元空间/永久代&#xff09;一起回收&#xff0c;大部分回收的是新生区里边的垃圾&#xff0c;因此GC按照回收的区域又分为了两种类型&#xff0c;一种是发生在新…

U盘不能访问不一定是坏了,可能还有其他原因!U盘无法访问修复详解

当你将USB驱动器连接到计算机时,系统会将其识别为可移动驱动器,并启动其文件管理过程。 然而,用户现在注意到,即使可以检测到他们的USB驱动器,也无法访问它们。 如果幸运的话,拔下插头就能解决问题,但如果不是,请继续阅读以了解更多故障排除选项。 USB闪存驱动器是便…

Android开发:(AndroidStudio模拟器)如何将模拟器语言设置为中文 模拟器输入法更改为中文输入 键盘输入中文

文章目录 Android开发模拟器设置将模拟器语言设置为中文输入法中文的设置 Android开发模拟器设置 将模拟器语言设置为中文 第一步&#xff1a;打开模拟器后&#xff0c;上滑打开下面的设置图标。 第二步&#xff1a;找到 System (系统) &#xff0c;点击进入。 第三步&am…

idea一键打包docker镜像并推送远程harbor仓库的方法(包含spotify和fabric8两种方法)--全网唯一正确,秒杀99%水文

我看了很多关于idea一键打包docker镜像并推送harbor仓库的文章&#xff0c;不论国内国外的&#xff0c;基本上99%都是瞎写的&#xff0c; 这些人不清楚打包插件原理&#xff0c;然后就是复制粘贴一大篇&#xff0c;写了一堆垃圾&#xff0c;然后别人拿来也不能用。 然后这篇文…

python爬虫概述及简单实践:获取豆瓣电影排行榜

目录 前言 Python爬虫概述 简单实践 - 获取豆瓣电影排行榜 1. 分析目标网页 2. 获取页面内容 3. 解析页面 4. 数据存储 5. 使用代理IP 总结 前言 Python爬虫是指通过程序自动化地对互联网上的信息进行抓取和分析的一种技术。Python作为一门易于学习且强大的编程语言&…