首页 > 其他分享 >stream流

stream流

时间:2024-02-05 16:56:56浏览次数:18  
标签:stream Optional 接口 result 方法 public

目录

一、流程

1.创建流

单列集合: List.stream()

数组: Arrays.stream(数组) \ Stream.of(数组)

双列集合: Map.entrySet().stream()

2.中间操作

对流进行处理

3.终结操作

对处理过的流进行最后的输出 如果没有终结操作的话,中间操作就不会被施行


二、中间操作

1.过滤filter

可以对流中的元素进行条件过滤,符合过滤条件的才能继续留在流中

filter(Predicate<? super T> predicate) 参数为函数式接口可以使用lambda

如果过滤 == true则保留,false则过滤掉

2.map()

类型转换:对集合中的对象进行运算或者转化类型,比如可以将集合中的POJO转换成其一个属性的集合,然后输出这个POJO集合会发现输出的都是这个属性的信息

计算: 对一个对象集合,map可以对每一个对象的每个属性进行赋值计算等操作

顺序性: 可以再次对流进行map操作,意义就是如果这个流现在里面全都是某一属性的集合,这个map就可以再次对此进行类型转换或者计算,有点像SQL的语句嵌套的感觉

3.sorted()

对list集合进行排序

//示例1:对id进行升序排序
private static void printSortList(List<User> list) {
List<User> userList=list.stream().sorted(Comparator.comparing(User::getId)).collect(Collectors.toList());
userList.forEach(u->System.out.println(u));
}
//示例2:对id进行降序排序
private static void printSortList(List<User> list) {
List<User> userList=list.stream().sorted(Comparator.comparing(User::getId).reversed()).collect(Collectors.toList());
userList.forEach(u->System.out.println(u));
}
//示例3:age升序 id=降序=thenComparing
private static void printSortList(List<User> list) {
List<User> userList=list.stream()
.sorted(Comparator.comparing(User::getAge).thenComparing(User::getId).reversed())
.collect(Collectors.toList());
userList.forEach(u->System.out.println(u));
}
4.flatMap

map只能把一个对象转换成另一个对象来作为流中的元素。而flatMap可以把一个对象转换成多个对象作为流中的元素。

//如果一个元素的一个属性为List类型的话
authors.stream()
  .flatMap(new Function<Author, Stream<Book>>(){
    @Override
    public Stream<Book> apply(Author author){
      return author.getBooks().stream();
    }
  })

flatMap另一种方式 = 对流进行操作并返回流

image-20230827213550941
5.limit()

对流中的前几个元素进行操作,如果设置参数超过集合的长度对返回的长度没有影响

6.skip(int a)

跳过前a个元素开始操作
skip索引起始于1,如果传入负值会抛出异常。

7.去重

distinct()

注意: distinct方法是依赖Obiet的equals方法来判断是否是相同对象的。所以需要注意重新equals方法。

Object的equals是 == 比较的是地址,所以要注意equals的重写

list.stream().distinct().forEach(employee -> System.out.println(employee.getName()));

8.排序

sorted()

空参: 实现排序的POJO类中要实现Comparable接口,定义抽象方法compareTo 返回正整数为升序,负整数为降序

this.xxx - 参数.xxx = ? this在左,参数在右

public class Cat implements Comparable<T>{
  //实现方法
  public int compareTo(Cat cat){
    return this.age - cat.age;
  }
}

实参: 不必纠结前后顺序,如果不对更换一下顺序即可

authors.stream()
  .disitinct()
  .sorted(new Comparator<Author>(){
  	@Override
  	public int compare(Author o1,Author o2){
      return o1.getAge() - o2.getAge();
    }
	})
  .forEach()

三、终结操作

终结操作之后这个流就报废了,如果再使用的话就会报错

1.forEach

对流中的元素进行遍历操作,我们通过传入的参数去指定对遍历到的元素进行什么具体操作

2.count

可以用来获取当前流中的元素个数 返回值为long

3.max&min

求流中的最大值或者最小值,也许是比较int型或者String所以要重写匿名方法来设置比较规则,正数为大,负数为小

返回值为Optional

4.collect

将流中的元素转换成一个集合

转换为

List:

collect(Collectors.toList())

Set

collect(Collectors.toSet())

Map

image-20230827220648546

key也可能重复,所以先将流中的元素去重也可以

5.anyMatch(重写判断条件)

判断是否有任意符合匹配条件的元素,结果为Boolean类型

6.allMatch(重写判断条件)

判断是否都符合匹配条件,return Boolean类型

7.noneMatch(重写判断条件)

判断是否都不符合匹配条件,return Boolean类型

8.findAny 随机性

获取流中的任意一个元素.该方法没有办法保证获取的一定是流中的第一个元素

返回值 Optional

image-20230827222301089

ifPresent()判断这个Optional对象中是否有值,有则执行

9.findFirst

获取流中的第一个元素

和上面的返回值及操作相似

10.reduce归并

对流中的数据按照你指定的计算方式计算出一个结果。 (缩减操作)
reduce的作用是把stream中的元素给组合起来,我们可以传入一个初始值,它会按照我们的计算方式依次拿流中的元素和在初始化值的基础上进行计算,计算结果再和后面的元素计算。

T result = identity; // 初始累加值
forI(T element : this stream)
	result = accumulator .apply(result, element)
return result;

其中identitv就是我们可以通过方法参数传入的初始值,accumulator的apply具体进行什么计算也是我们通过方法参数来确定的。

//类似于
int[] arr = {};
int result = 1;
for(int i : arr){
	result = result * 1;
}
return result;

reduce传入两个参数

第一种

//求所有年龄的和
authors.stream().
map(author -> author.getAge()).
reduce(0,new BinaryQperator<Integer>(){
@Override
public Integer apply(Integer result,Integer element){
//计算过程
  return result + element;
}
})
//其中,第一个参数是我们设置的默认初始值 0 ,第二个参数是流中的每一个元素

第二种

//求最大值
//求最小值就可以将Integer.MIN改为 MAX这样计算
Integer reduce = list.stream().
             reduce(Integer.MIN_VALUE, new BinaryOperator<Integer>() {
                 @Override
                 public Integer apply(Integer result, Integer element) {
                     return result < element ? element : result;
                 }
             });

reduce一个参数重载形式

将流中的第一个元素作为初始化值

boolean foundAny = false ;T result = nu11;
for (T element : this stream) {
  if (!foundAny) {
    foundAny = true;
    result = element;
  }e1se
		result = accumulator .apply(result, element);
}
return foundAny ? optional .of(result) : optional.empty() ;
11.Optional

Optional就好像是包装类,可以把我们的具体数据封装在Optional对象内部。然后我们去使用Optional中封装好的方法操作封装进去的数据就可以非常优雅的避免空指针异常。

12.创建Optional

使用静态方法Optional.ofNullable(POJO)

public static void main(String[] args) {
        Optional<Person> personOptional = getPersonOptional();
        personOptional.ifPresent(person2 -> System.out.println(person2.getName()));

    }
    public static Optional<Person> getPersonOptional() {
        Person person = new Person("朱大夫", 34, "一个伟大的人");
        return Optional.ofNullable(person);
    }

Optional.of() 确定对象不为空使用

Optional.empty() 返回null值的Optional对象

13.安全消费值

Optional.ifPresent()

14.获取值.

get方法,不推荐,如果包装的是一个null值会抛出异常

orElseGet
获取数据并且设置数据为空时的默认值。如果数据不为空就能获取到该数据。如果为空则根据你传入的参数来创建对象作为默认值返回。

optional<Author> authoroptional = optional.ofNu1able(getAuthor ());Author authorl = authoroptional.orE1seGet(() -> new Author());

orElseThrow
获取数据,如果数据不为空就能获取到该数据。如果为空则根据你传入的参数来创建异常抛出。

public static void main(String[] args) {
        try {
            Optional<Person> personOptional = getPersonOptional();
            Person person = personOptional.orElseThrow(() -> new RuntimeException("没有值会抛出这个异常"));
            System.out.println(person);
        } catch (RuntimeException e) {
            throw new RuntimeException(e);
        }

    }
    public static Optional<Person> getPersonOptional() {
        Person person = new Person("朱大夫", 34, "一个伟大的人");
        return Optional.ofNullable(person);
    }
15.过滤

filter() 和stream.map类似

如果此Optional本来是有数据的,但是经过filter过滤之后,没有符合条件的数据,此Optional也会变成一个无数据的Optional对象

personOptional.filter(person1 -> person1.getAge() > 34).ifPresent(person1 -> System.out.println(person1.getName()));
16.判断

isPresent()判断是否存在

17.数据转换

和stream中的map方法一样,返回的也还是一个Optional对象

四、函数式接口

1.只有一个抽象方法的接口我们称之为函数接口

JDK的函数式接口都加上了@FunctionalInterface注解进行标识.但是无论是否加上该注解只要接口重质油一个抽象方法,都是函数式接口

consumer消费接口 void accept(T t)

function计算转换接口 R apply(T t)

predicate判断接口 boolean test(T t)

Supplier 生产型接口 T get()

spanjava11自带的函数式接口可以传入多个参数 : package java.util.function; BiFunction\BiConsumer等////

2.函数式接口常用默认方法

意义在于定义方法的时候: 当我们将多个函数式接口 a b 当做一个方法的参数时,可以在方法内使用这个函数式接口的默认方法,比如a.and(b).

and拼接条件

or或者条件

negate取反的操作 !


3.方法引用

重点是,参数顺序->知道参数是什么,参数准确传入->简化代码 == 方法引用

我们在使用lambda时不需要考虑什么时候用方法引用,用哪种方法引用,方法引用的格式是什么。我们只需要在写完lambda方法发现方法体只有一行代码,并且是方法的调用时使用快捷键尝试是否能够转换成方法引用即可。当我们方法引用使用的多了慢慢的也可以直接写出方法引用。

4.基本格式

类名或者对象名::方法名

5.引用类的静态方法

使用前提
如果我们在重写方法的时候,方法体中只有一行代码,并且这行代码是调用了某个类的静态方法,并且我们把要重写的抽象方法中所有的参数都按照顺序传入了这个静态方法中,这个时候我们就可以引用类的静态方法。

6.引用类的实例方法

使用前提
如果我们在重写方法的时候,方法体中只有一行代码,并且这行代码是调用了第一个参数的成员方法,并且我们把要重写的抽象方法中剩余的所有的参数都按照顺序传入了这个成员方法中,这个时候我们就可以引用类的实例方法。

image-20230903170426963
public class OptionalTest {
    interface UseString {
        String use(String str, int start, int length);
    }
    public static String subAuthorName(String str, UseString useString) {
        int start = 0;
        int length = 1;
        return useString.use(str, start, length);
    }

    public static void main(String[] args) {
        subAuthorName("小牧", String::substring);
    }
}
7.构造器引用

类名::new

五、高级用法

1.基本数据类型优化

我们之前用到的很多Stream方法由于都使用了泛型,所以涉及到的参数和返回值都是引用数据类型即使我们操作的都是整数小数,但是实际用的都是他们的包装类.JDK提供的自动装箱和自动拆箱可以让我们在使用对应的包装类时就好像使用基本数据类型一样.但是这样在大数据量下是会消耗时间的.

Stream还提供了很多专门针对基本数据类型的方法
mapToInt,mapToLong,mapToDouble,flatMapToInt,flatMapToLong,等

2.并行流

Stream.parallel()将串行流转换成并行流

或者一个集合直接list.parallelStream()

image-20230903175102432

标签:stream,Optional,接口,result,方法,public
From: https://www.cnblogs.com/axuuww/p/18008422

相关文章

  • Nginx--upstream健康检查
    nginx判断节点失效状态:Nginx默认判断失败节点状态以connectrefuse和timeout状态为准,不以HTTP错误状态进行判断失败,因为HTTP只要能返回状态说明该节点还可以正常连接,所以nginx判断其还是存活状态;除非添加了proxy_next_upstream指令设置对404、502、503、504、500和timeout......
  • 文件上传错误:Processing of multipart/form-data request failed. Stream ended unexp
    问题描述Processingofmultipart/form-datarequestfailed.Streamendedunexpectedly不通过网关,直接在本地debug是可以上传成功的,线上环境通过网关上传则会导致此错误,可能是网关修改了请求内容。解决方式前端将文件转换为base64字符串,服务端接收到再转换为字节数组......
  • 文件流(File Stream)是NTFS文件系统中的一个特性,它允许在一个文件中存储多个数据流。每
    文件流(FileStream)是NTFS文件系统中的一个特性,它允许在一个文件中存储多个数据流。每个数据流都可以独立地读取和写入数据,并与主数据流关联。文件流在文件系统中起到存储和管理附加属性、元数据等信息的作用。技术原理:NTFS文件系统使用文件标识符(FileID)来唯一标识每个文件。对......
  • stream流的常用操作
    Stream流的一些操作这段时间在项目开发中使用到Java8的Stream流操作发现真的特别方便,这里总结了一些常用的stream流操作.1简介在使用Stream流之前先来简单介绍一下:1Stream事java8才提供的一种以流的方式来处理数据集的一种手段,凡是属于Collection接口之下的所有字......
  • java中如何获取Stream流
    在Java中获取Stream流主要有以下几种方式:通过集合类(Collection)获取:所有的java.util.Collection接口的实现类,包括List,Set,和Queue等,都可以使用.stream()方法来获取一个Stream。例如:List<String>list=Arrays.asList("a","b","c");Stream<String>streamOfList=......
  • Stream流的中间方法和终结方法有哪些
    在Java8及更高版本的StreamAPI中,Stream操作可以分为中间操作(IntermediateOperations)和终结操作(TerminalOperations)。下面是两类方法的一些常见示例:中间操作(IntermediateOperations):中间操作不会立即执行任何处理,而是返回一个新的Stream。这些操作可以链接起来形成一个流水线......
  • Databend Stream 的设计与实现 | Data Infra 第 18 期
    年前最后一场DataInfra直播活动将于本周六(02月03日)与大家见面。本次活动我们邀请到了 Databend 研发工程师-张祖前,与大家分享主题为《DatabendStream的设计与实现》的相关知识。Databend Stream是用于获取Databend中表增量的一个特性。Stream可以捕获到Databend......
  • stream里面filter foreach 还能再fileter吗
    是的,在 Java 的 Stream API 中,你可以在 filter 和 forEach 操作之间再次使用 filter。实际上,你可以根据需要链式调用多个中间操作(如 filter、map 等),但请注意,forEach 是一个终端操作,它会消费流并产生一个非流的结果。一旦调用了 forEach 或其他任何终端操作,流就被消......
  • [cpp]: thread -- with header <syncstream>
    [cpp]: thread--withheader<syncstream>    一、说明: 1、【并发编程】thread编程中的同步输出:std::osyncstream// Definedinheader <syncstream>   二、程序代码1#include<iostream>2#include<string>3#include<......
  • Stream
    Arrayint[]anArray=newint[10];String[]stringArray=newString[]{"a","b","c"};ListList<String>stringList=java.util.Arrays.asList("a","b","c");List<String>strin......