Stream流在实际项目中的相关应用

stream流实战应用

基础应用看 stream流基础应用

1.stream流把数组列表转为实体类列表

通过map方法去每一次循环做操作

(map:接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。)

List<Object[]> students = studentService.findByAgeList(ageList);
List<Student> student = students.stream()
        .map(item -> {
            Student student= new Student();
            student.setName((String) item[0]);
            student.setId((String) item[1]);
            student.setAge((String) item[2]);
            return student;
        })
        .collect(Collectors.toList()); 

2.stream流按照属性进行分组/排序

Collectors.groupingBy()方法进行分组,Comparator.comparing()方法是对分组结果进行排序,也就是age属性

Map<Object, List<Student>> tempMap = new LinkedHashMap<>();
tempMap = student.parallelStream()
    .sorted(Comparator.comparing(Student::getAge))
    .collect(Collectors.groupingBy(Student-> Student.getAge()));

另一种

List<Map<String,Object>> authorList = new ArrayList<>();
authorList .sort(Comparator.comparing(map -> {
    String age = map.get("age").toString();
    return Integer.parseInt(age);
}));

3.filter()筛选

String s = authorList.stream().filter(item -> item.getName().equals(authorName))
.findFirst().map(StudentEntity::getId).orElse("null");

筛选出相等的元素,findFirst()取第一个元素,orElse()是如果取不到数据就给它赋默认你填写的值

*这个里可能会出现一个问题,我之前是把findFirst()放到了map的后边,但是因为getId可能是空,取不到值就会报空指针,所以移到了前面,根据具体情况去看你需要什么样的一个stream流

stuList.stream()
    .filter(item -> item.getName().equals(authorName))
    .forEach(studentEntity-> studentEntity.setSid("accountSid"));

 还可以给筛选出的指定数据进行循环赋值

4.isPresent()方法 判空

用于判空,返回Optional的情况下使用 true为存在

如果确定有数据的话可以直接在括号里写

first.ifPresent(content-> dataList.add(content.getName()));

5.count()方法 记录总数

记录总数

dataList.stream().filter(item -> item.getState() == 2).count()

6.sorted()方法 排序 和Comparator.comparingInt()

sorted()用于排序        Comparator.comparingInt()返回结果转为int

List<Student> sortedStudentList = StudentInfoItemList() .stream()
.sorted(Comparator.comparingInt(studentInfoItem -> 
educService.findById(studentInfoItem.getEducId()).getLevel()))
.toList();

7. anyMatch()方法 存在筛选的数据

是否存在筛选后的数据

boolean exist = sortedEducList.stream()
.anyMatch(item -> educService.findBySid(item.getEducId())
.getLevel() >= stuLevel);

注:一个stream流只能使用一次,也就是返回的Stream流只能在被操作一次,用过之后流就不存在了

8.sum()方法求和

int sum = dataMap.stream()
           .mapToInt(item -> Integer.parseInt(item.get("count"))).sum();

8.优化stream流的运行速度

将普通的steam流变成并行流(parallelStream)对于可以并行处理的部分

List<Object[]> students = studentService.findByAgeList(ageList);
List<Student> student = students.parallelStream()
        .map(item -> {
            Student student= new Student();
            student.setName((String) item[0]);
            student.setId((String) item[1]);
            student.setAge((String) item[2]);
            return student;
        })
        .collect(Collectors.toList()); 

并行流使用的相关

1.概念

并行流是Java 8引入的一种流处理方式,可以在多个线程上同时执行操作,以提高处理速度。它适用于那些可以独立处理的操作,每个操作之间没有依赖关系。

然而,并行流在处理数据时会使用多个线程并发执行操作,因此可能存在并发问题。当多个线程同时修改共享的数据时,可能会导致数据不一致或产生其他问题。

为了避免并发问题,在使用并行流时需要确保对共享数据的访问是线程安全的,或者通过使用线程安全的集合类来避免共享数据的修改。例如,可以使用Collectors.groupingByConcurrent()方法来创建一个线程安全的Map,或者使用并发集合类如ConcurrentHashMap

此外,还需要注意在使用并行流时,一些操作可能会失去顺序性。并行流会对数据进行分区处理,并且每个分区都可能在不同的线程上执行操作,所以最终的处理结果可能会失去原有的顺序。如果需要保持顺序,可以使用forEachOrdered()方法来替代forEach()方法。

总之,在使用并行流时需要确保数据访问的线程安全性,并且考虑到并发问题和顺序性的影响。

2.操作主要是查询和数据转换

如果代码中的操作主要是查询和数据转换,并且没有直接修改共享数据的部分,那么这个代码片段可能没有并发问题。

在这种情况下,使用并行流可以提高代码的执行效率,因为查询和转换操作是独立的,并且没有共享数据的修改。并行流可以将这些操作并行地分配给多个线程,以加快处理速度。

然而,仍然建议在使用并行流时谨慎考虑以下几点:

  1. 查询操作是否与外部资源(如数据库)有关。如果查询操作涉及到对共享资源的读取或写入,需要确保对共享资源的访问是线程安全的。
  2. 数据转换操作是否引入了状态变化。如果数据转换操作依赖于其他操作的结果或状态,可能会导致并发问题。确保操作之间的依赖关系被正确处理。
  3. 并行流在某些情况下可能导致额外的开销。在数据量较小或处理逻辑简单的情况下,并行流可能不一定比顺序流更快。在实际使用中,可以尝试使用不同的流类型进行比较和性能测试,找到最合适的方式。

总之,如果你的代码只涉及查询和数据转换,并且没有直接修改共享数据,那么在大多数情况下,使用并行流是安全且高效的。但仍建议对代码进行充分测试和验证,以确保并行流的正确性和性能提升。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
DL是一个高性能的日志复制服务,提供了持久化、复制以及强一致性的功能,这对于构建可靠的分布式系统都是至关重要的,如复制状态机(replicated-state-machines)、通用的发布/订阅系统、分布式数据库以及分布式队列。DistributedLog会分类维护记录的序列(sequences of records),并将其称为Log(又叫做Log Stream),将记录写入到DL Log的进程称之为Writer,从Log读取并处理记录的进程称之为Reader。因此,它整体的软件栈如下所示:具体来讲,它包含如下几个组成部分:LogLog是有序的、不可变的日志记录(log record),它的数据结构如下所示:日志记录每条日志记录都是一个字节序列。日志记录会按照序列写入到日志,并且会分配一个名为DLSN(分布式序列号,DistributedLog Sequence Number)的唯一序列号。除了DLSN以外,应用程序还可以在构建日志记录的时候设置自己的序列号,应用程序所定义的序列号称为TransactionID(txid)。不管是DLSN还是TransactionID都能用来定位Reader,使其从特定的日志记录开始读取。Log分段(Log Segments)Log会被分解为Log分段,每个分段包含了其记录的子集。Log分段是分布式的,应该放到Log分段存储(如BookKeeper)。DistributedLog会基于配置好的策略来轮询每个Log分段,要么是可配置的时间段(如每两个小时),要么是可配置的最大规模(如每128MB)。所以Log的数据将会分为同等大小的Log分段,并且均匀分布到Log分段存储节点上。这样,Log的存储就不会局限于单台服务器的限制,同时,能够在集群分散读取的量。Log的数据可以永远保存,直到应用程序显式地将其截断,也可以在一个可配置的时间段内保存。对于构建复制状态机来说,显式截断会非常有用,如分布式数据库。在数据何时能够截断这一点上,它们往往有着严格的控制。基于时间保留Log对于实时分析的场景更为有用,它们只关心一定时间内的数据。命名空间属于同一组织的Log通常会归类在同一个命名空间(namespace)下,并据此进行管理。DL的命名空间基本上就是用来定位Log流在何处的。应用程序可以在某个命名空间下创建和删除,也能将某个截断到给定的序列号上(DLSN或TransactionID均可以)。WriterWriter会将数据写入到它们所选择的Log。所有的记录都会按照顺序添加到Log之。序列号是由Writer所负责的,这就意味着对于某个Log,在给定的时间点上,只能有一个激活的Writer。当出现网络分区(network partition),导致两个Writer试图往同一个Log进行写入的时候,DL会保证其正确性,这是通过Log分段存储的屏障(fencing)来实现的。Writer由名为Write Proxy的服务层来提供和管理,Write Proxy用来接受大量客户端的fan-in写入。ReaderReader会从它们所选择的Log读取记录,这会在一个给定的位置开始。这个给定的位置可以是DLSN,也可以是TransactionID。Reader将会严格按照Log的顺序读取记录。在同一个Log,不同的Reader可以在不同的起始位置读取记录。与其他的订阅/发布系统不同,DistributedLog并不会记录/管理Reader的位置,它将跟踪的任务留给了应用程序本身,因为不同的应用在跟踪和协调位置上可能会有不同的需求,很难用一种方式就将这些需求全部解决。在应用程序层面,借助各种存储(如ZooKeeper、FileSystem或Key/Value存储)能够很容易地跟踪Reader的位置。Log记录可以缓存在名为Read Proxy的服务层,从而应对大量Reader的读取。Fan-in与Fan-outDistributedLog的核心支持单Writer、多Reader的语义。服务层构建在DistributedLog Core之上,支持大量的Writer和Reader。服务层包含Write Proxy和Read Proxy,Write Proxy管理Log的Writer,并且在机器宕机时,能够对它们进行故障恢复。它能够从众多来源聚集Writer,允许不必关心Log的所有权(又称为Fan-in)。Read Proxy通过将记录放到缓存,优化了Reader的读取路径,以应对成百上千的Reader读取同一个Log的状况。作为一个日志服务,DistributedLog的优势可以总结为:高性能:面对大量的并发日志时,在可持久化的Writer上DL能够提供毫秒级的延迟,同时还能应对上千客户端每秒大量的读取和写入操作。持久化和一致性:消息会持久化到磁盘上,并且以副本的形式存储多份,从而避免丢失。通过严格的顺序,保证Writer和Reader之间的一致性。各种工作负载:DL支持各种负载,包括延迟敏感的在线事务处理(OLTP)应用(如分布式数据库的WAL和基于内存的复制状态机)、实时的提取和计算以及分析处理。多租户:针对实际的工作负载,DL的设计是I/O隔离的,从而支持多租户的大规模日志。分层架构:DL有一个现代化的分层设计,它将有状态的存储层与无状态的服务提供层进行了分离,能够使存储的扩展独立于CPU和内存,因此支持大规模的写入fan-in和读取fan-out。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值