utils004_Stream简介

本文详细介绍Java Stream API的使用,涵盖并行流、forEach、count、findAny/First、skip/limit、distinct、sorted、filter/map/reduce等核心操作,以及collect和自定义比较器的应用。
package com.jingsong.test;

import lombok.Builder;
import lombok.Data;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author jingsong
 * @date 2022/4/22 23:27
 */
public class StreamTest {
    public static void main(String[] args) {
        List<Student> students = Student.getSomeStudent(9);
        /*
            Student(name=stu1, age=1, man=true),
            Student(name=stu2, age=2, man=false),
            Student(name=stu3, age=3, man=true),
            Student(name=stu4, age=0, man=false),
            Student(name=stu5, age=1, man=true),
            Student(name=stu6, age=2, man=false),
            Student(name=stu7, age=3, man=true),
            Student(name=stu8, age=0, man=false),
            Student(name=stu9, age=1, man=true)
         */


        /*
            1. parallelStream和Stream的区别
                 parallelStream多个线程并行执行元素,相对速度更快;但是每个元素的处理时间过长时,会出现线程阻塞
                 parallelStream适合较多数据且元素处理相对简单的场景。
                参考:
                    a. http://t.csdn.cn/5Bn2a
                    b. http://t.csdn.cn/r4em5
         */
        //students.parallelStream().forEach(s -> System.out.println(s.getName() + "\t" + Thread.currentThread().getName()));
        //students.stream().forEach(s -> System.out.println(s.getName() + "\t" + Thread.currentThread().getName()));


        /*
            2. forEach 遍历
               forEachOrdered 按照元素顺序遍历,针对并行流
         */
        //students.stream().forEach(System.out::println);
        //students.parallelStream().forEachOrdered(System.out::println);

        /*
            3. count 计数
         */
        /*long count = students.stream().count();
        System.out.println("count = " + count);*/

        /*
            4. findAny 一般用于过滤之后findAny.isPresent判断是否存在
              findFirst 获得满足条件的第一个
         */
        /*boolean present = students.stream().filter(s -> s.getName().endsWith("1") || s.getName().endsWith("0")).findAny().isPresent();
        System.out.println("present = " + present);*/
        /*Student student = students.stream().findFirst().get();
        System.out.println("student = " + student);*/

        /*
            5. skip 跳过几个元素
               limit 一共取几个元素
         */
        //students.stream().skip(1).limit(3).forEach(System.out::println);

        /*
            6. distinct() 去重
                根据对象的equals()判断
         */
        //System.out.println(Student.getTwoSameStudent().stream().distinct().count());

        /*
            7. sorted 根据自己定义的规则进行排序
         */
        //students.stream().sorted(Comparator.comparingInt(Student::getAge)).forEach(System.out::println);

        /*
            8. allMatch 元素是否都满足某个条件
               anyMatch 元素们是否有一个满足条件
               noneMach 元素是否都不满足某个条件
         */
        /*boolean stu = students.stream().allMatch(s -> s.getName().startsWith("stu"));
        System.out.println("stu = " + stu);*/
        /*boolean b = students.stream().anyMatch(s -> s.getName().startsWith("stu1"));
        System.out.println("b = " + b);*/
        /*boolean stu1 = students.stream().noneMatch(s -> s.getName().startsWith("stu11"));
        System.out.println("stu1 = " + stu1);*/

        /*
            9. max 根据条件找出最大的元素
               min 根据条件找出最小的元素
         */
        /*Student student = students.stream().max(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return Integer.valueOf(o1.getName().substring(o1.getName().length() - 1)) -
                        Integer.valueOf(o2.getName().substring(o2.getName().length() - 1));
            }
        }).get();
        System.out.println("student = " + student);*/
        /*Student student = students.stream().min(Comparator.comparingInt(o -> Integer.valueOf(o.getName().substring(o.getName().length() - 1)))).get();
        System.out.println("student = " + student);*/


        /*
            10. peek 提供一个可以查看流的中间状态的方法,方便分析流
                    例如forEach会消耗流,仅可查看最终状态。peek的打印则可以查看中间状态
         */
        //students.stream().peek(System.out::println).forEach(System.out::println);


        /*
            11. filter 自定义条件,筛选出你需要的元素
         */
        //students.stream().filter(Student::getMan).forEach(System.out::println);


        /*
            12. map 通过方法搜集元素的某些信息
                写法:  类名::方法名
                获得方法的返回值,组成新的stream流

                mapToInt()     int流
                mapToDouble()  double流
                mapToLong()    long流
         */
        //students.stream().map(Student::getNameAndGender).forEach(System.out::println);
        //students.stream().mapToInt()
        //students.stream().mapToDouble()
        //students.stream().mapToLong()


        /*
            13. 将初始流中的元素细分,再次拆分一个个新的小流,再将所有的小流合并
                int double long同理
         */
        /*students.stream().flatMap(new Function<Student, Stream<?>>() {
            @Override
            public Stream<?> apply(Student student) {
                return Arrays.stream(student.getName().split("tu"));
            }
        }).forEach(System.out::println);*/

        /*
            14. reduce 相当于对流中元素做一个累计操作
                apply方法中
                    public newStu1 apply(stu1,stu2)
                    public newStu2 apply(newStu1,stu3)
                    public newStu3 apply(newStu2,stu4)
                    ......
                    以此类推,也可以指定初始值作为reduce()的第一个参数
         */
        /*Student student = students.stream().reduce(Student.builder().age(-13).build(),new BinaryOperator<Student>() {
            @Override
            public Student apply(Student student, Student student2) {
                student.setAge(student.getAge() + student2.getAge());
                return student;
            }
        });
        System.out.println("student = " + student);*/


        /*
            15. collect
                1. 收集某类元素
                2. 根据某个条件进行分组
                    a. groupingBy 分为多个组
                    b. partitioningBy 分为true or false两个组
                3. 计算平均值,总值等 averagingDouble
         */
        /*List<Integer> collect = students.stream().map(Student::getAge).collect(Collectors.toList());
        System.out.println("collect = " + collect);*/
        /*Map<Boolean, List<Student>> map = students.stream().collect(Collectors.partitioningBy(Student::getMan));
        for (Map.Entry<Boolean, List<Student>> entry : map.entrySet()) {
            System.out.println("entry = " + entry);
        }*/
        /*Double collect = students.stream().collect(Collectors.averagingDouble(Student::getAge));
        System.out.println("collect = " + collect);*/
    }
}


@Data
@Builder
@SuppressWarnings("all")
class Student {
    private String name;
    private Integer age;
    private Boolean man;

    public static List<Student> getSomeStudent(int number) {
        ArrayList<Student> students = new ArrayList<>();
        for (int i = 1; i <= number; i++) {
            students.add(Student.builder().name("stu" + i).age(i & 3).man((i & 1) == 1).build());
        }
        return students;
    }

    public static List<Student> getTwoSameStudent() {
        return Arrays.asList(
                Student.builder().name("hehe").age(11).man(true).build(),
                Student.builder().name("hehe").age(11).man(true).build()
        );
    }

    public String getNameAndGender() {
        return this.name + "::" + this.man;
    }


    @Override
    public boolean equals(Object o) {
        return false;
    }

    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + (age != null ? age.hashCode() : 0);
        result = 31 * result + (man != null ? man.hashCode() : 0);
        return result;
    }
}
### 关于 `pika` 中 `_AsyncBaseTransport._produce` 抛出 `'IndexError: pop from an empty deque'` 当遇到 `pika.adapters.utils.io_services_utils._AsyncBaseTransport.produce failed` 错误并抛出 `'IndexError: pop from an empty deque'` 时,这通常意味着尝试从一个空的双端队列 (deque) 移除元素。此问题可能由多种因素引起。 #### 可能的原因 1. **网络连接不稳定** 如果应用程序与 RabbitMQ 服务器之间的网络连接频繁中断或非常缓慢,则可能导致发送缓冲区中的数据未能及时处理而被清空,进而引发该异常[^2]。 2. **并发访问冲突** 当多个线程试图同时操作同一个 Pika 连接对象及其内部资源(如通道),可能会造成竞争条件,从而破坏了消息队列的状态完整性。为了防止这种情况发生,建议采用线程安全的方式管理这些共享资源,比如通过为每个工作单元分配独立的连接实例来实现线程隔离。 3. **内存不足** 类似的情况也可能发生在 JVM 内存溢出的情况下,如果程序运行环境中可用物理 RAM 不足或者配置不当,就有可能触发类似的错误信息。对于 Spark 应用而言,适当调整缓存大小以及优化任务执行计划有助于缓解此类状况[^3]。 4. **Pika 版本兼容性** 使用较新版本的 Python 或者其他依赖库更新后可能出现不向后的兼容性问题,某些情况下旧版 Pika 的行为模式不再适用于新的环境设置。因此保持软件栈各组件之间良好的匹配度非常重要。 #### 建议采取措施 - 审查现有代码逻辑,确保每次调用 `.basic_publish()` 方法之前已经建立了有效的 AMQP 链路,并且确认目标交换机/队列确实存在。 - 实施健壮的消息重试机制以应对临时性的通信失败;考虑引入指数退避算法等策略提高恢复效率。 - 对于多线程场景下的应用开发,请遵循最佳实践指南构建线程局部存储(TLS),避免跨线程传递未经同步保护的对象引用。 - 监控系统性能指标特别是 CPU 和内存占用情况,必要时升级硬件设施或优化资源配置参数。 - 尝试降级至更稳定的 Pika 发布版本,或是查阅官方文档获取有关最新特性支持状态的信息。 ```python import threading from functools import wraps def thread_safe(fn): """装饰器用于使函数成为线程安全""" lock = threading.Lock() @wraps(fn) def wrapper(*args, **kwargs): with lock: return fn(*args, **kwargs) return wrapper class ThreadSafePublisher(object): @thread_safe def publish_message(self, message_body): try: connection = pika.BlockingConnection(pika.ConnectionParameters('localhost')) channel = connection.channel() channel.exchange_declare(exchange='direct_logs', exchange_type='direct') severity = 'info' channel.basic_publish( exchange='direct_logs', routing_key=severity, body=message_body, properties=pika.BasicProperties(delivery_mode=2)) print(" [x] Sent %r:%r" % (severity, message_body)) connection.close() except Exception as e: logging.error(f"Failed to send message due to {e}") ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值