探索JDK24新特性!Stream Gatherers:一次革命性的流处理升级,代码量减半

AirSim安装和地图加载 详细教程如何安装AirSim并加载地图 阅读详情

在这里插入图片描述

还在为复杂数据流处理写一堆繁琐代码而头疼吗?还在为实现滑动窗口、状态管理等功能而绞尽脑汁吗? JDK 24带来了一项革命性特性——Stream Gatherers,它将彻底改变你处理数据流的方式。

想象一下,如果传统的Stream API是工厂生产线上的基础工序,那么Gatherers就是那个能记忆、能思考、还能一变多的"超级工序"。

本文将带你深入了解这个强大特性,让你的代码不仅更简洁,更具表达力,还能解决以前需要绕很大弯子才能实现的复杂场景。 无论你是处理金融数据、日志分析还是复杂业务逻辑,Stream Gatherers都能让你事半功倍!

一、Stream Gatherers是什么

Stream Gatherers是JDK 24中引入的一个强大新特性,它扩展了Java Stream API的能力,让我们能够更灵活地处理数据流。想象一下,如果传统的Stream API是一条生产线上的基础工序(如筛选、映射),那么Gatherers就像是更复杂的工序,可以记住之前处理过的元素,还能根据一个输入元素产生多个或零个输出元素。

传统Stream API(如map、filter、reduce)在处理某些复杂场景时有局限性,而Gatherers正是为解决这些限制而生的。

在这里插入图片描述

二、Stream Gatherers的核心特性

1、有状态操作

传统Stream操作如map是无状态的,每个元素处理都独立进行。而Gatherers可以在处理过程中维护状态,让前面元素的处理结果影响后续元素的处理方式。

2、输入输出数量不对等

在传统map操作中,一个输入元素只能产生一个输出元素。而使用Gatherers,一个输入元素可以产生零个、一个或多个输出元素。

3、与现有API无缝集成

Gatherers可以与原有Stream API一起使用,形成更强大的数据处理流水线。

三、通过代码示例详解Stream Gatherers

1、滑动窗口平均值计算

一个常见需求是计算数据的滑动窗口平均值,传统方式比较复杂,而使用Gatherers可以简洁实现。

这里的windowSliding(3)创建了一个滑动窗口,每次包含3个连续元素。当我们遍历[1,2,3,4,5,6,7,8,9]这个序列时,会生成窗口[1,2,3]、[2,3,4]、[3,4,5]等,然后对每个窗口计算平均值。

import java.util.List;
import java.util.stream.Gatherers;

public class SlidingWindowExample {
    public static void main(String[] args) {
        // 原始数据
        List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9);
        
        // 计算大小为3的滑动窗口的平均值
        List<Double> averages = numbers.stream()
            .gather(Gatherers.windowSliding(3)  // 创建大小为3的滑动窗口
                .map(window -> window.stream()  // 对每个窗口计算平均值
                    .mapToInt(Integer::intValue)
                    .average()
                    .orElse(0.0)))
            .toList();
        
        System.out.println("滑动窗口平均值: " + averages);
        // 输出: [2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]
    }
}

2、去除连续重复元素

需要去除列表中连续重复的元素?Gatherers提供了现成的解决方案,注意这里与传统的distinct()方法不同,distinctConsecutive()只去除连续重复的元素,如果同样的元素在列表中不相邻出现,则会保留。

import java.util.List;
import java.util.stream.Gatherers;

public class DistinctConsecutiveExample {
    public static void main(String[] args) {
        List<String> words = List.of("apple", "apple", "banana", "banana", "apple");
        
        // 去除连续重复元素
        List<String> distinct = words.stream()
            .gather(Gatherers.distinctConsecutive())
            .toList();
        
        System.out.println("原始列表: " + words);
        System.out.println("去除连续重复后: " + distinct);
        // 输出: [apple, banana, apple]
    }
}

3、自定义Gatherer - 分组收集

Gatherers真正的威力在于可以创建自定义的转换操作。以下是一个将元素按指定大小分组的示例:

这个例子创建了一个自定义的Gatherer,它将流中的元素每3个一组收集成子列表。最后一组可能不足3个元素。

import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
import java.util.stream.Gatherer;

public class CustomGathererExample {
    public static void main(String[] args) {
        List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        
        // 自定义Gatherer: 将元素按照指定大小分组
        Gatherer<Integer, List<Integer>, List<Integer>> chunking = Gatherer.of(
            // 初始状态提供者(创建一个空的ArrayList作为初始"积累器")
            (Supplier<List<Integer>>) ArrayList::new,
            
            // 处理元素的核心函数(accumulator, element, downstream)
            (chunk, element, downstream) -> {
                chunk.add(element);  // 将当前元素添加到积累器中
                
                // 当chunk达到大小3时,发送到downstream并创建新的chunk
                if (chunk.size() == 3) {
                    downstream.push(List.copyOf(chunk));  // 发送不可变的副本
                    chunk.clear();  // 清空积累器,准备收集下一组
                }
                return true;  // 继续处理后续元素
            },
            
            // 完成处理时的函数(处理可能剩余的元素)
            (chunk, downstream) -> {
                if (!chunk.isEmpty()) {
                    downstream.push(List.copyOf(chunk));
                }
            }
        );
        
        // 使用自定义Gatherer
        List<List<Integer>> chunks = numbers.stream()
            .gather(chunking)
            .toList();
        
        System.out.println("分组结果: " + chunks);
        // 输出: [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
    }
}

4、使用fold简化聚合操作

Gatherers还提供了fold方法,简化了一些聚合操作:

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Gatherers;

public class FoldExample {
    public static void main(String[] args) {
        List<String> fruits = List.of("apple", "banana", "apple", "cherry", "banana", "apple");
        
        // 使用fold统计每个水果出现的频率
        Map<String, Integer> frequencies = fruits.stream()
            .gather(Gatherers.fold(
                HashMap::new,  // 初始状态
                (map, fruit) -> {  // 累加函数
                    map.put(fruit, map.getOrDefault(fruit, 0) + 1);
                    return map;
                }
            ));
        
        System.out.println("水果出现频率: " + frequencies);
        // 输出: {banana=2, apple=3, cherry=1}
    }
}

这个例子使用fold操作将流中的元素收集到一个Map中,统计每个元素出现的次数。

在这里插入图片描述

5、与传统Stream API的对比

为了更清晰地展示Stream Gatherers的优势,我们来比较一下实现滑动窗口的两种方式:

// 传统方式实现滑动窗口 - 代码较复杂
List<Double> traditionalWay = IntStream.range(0, numbers.size() - 2)
    .mapToObj(i -> numbers.subList(i, i + 3))
    .map(window -> window.stream()
        .mapToInt(Integer::intValue)
        .average()
        .orElse(0.0))
    .collect(Collectors.toList());

// 使用Gatherers实现 - 代码更简洁、更直观
List<Double> withGatherers = numbers.stream()
    .gather(Gatherers.windowSliding(3)
        .map(window -> window.stream()
            .mapToInt(Integer::intValue)
            .average()
            .orElse(0.0)))
    .toList();

四、Stream Gatherers的实际应用场景

1、金融分析师经常需要计算各种技术指标如移动平均线、相对强弱指数(RSI)等。

这个例子展示了如何使用滑动窗口计算股票的5日和20日移动平均线,这在传统方法中需要编写大量样板代码。

import java.util.*;
import java.time.LocalDate;
import java.util.stream.Gatherers;

public class StockAnalysisExample {
    record StockPrice(LocalDate date, double price) {}
    record MAResult(LocalDate date, double price, double ma5, double ma20) {}
    
    public static void main(String[] args) {
        // 股票历史价格数据
        List<StockPrice> prices = List.of(
            new StockPrice(LocalDate.of(2024, 1, 1), 150.25),
            new StockPrice(LocalDate.of(2024, 1, 2), 152.50),
            // ... 更多数据
            new StockPrice(LocalDate.of(2024, 1, 30), 168.75)
        );
        
        // 使用Gatherers计算5日和20日移动平均线
        List<MAResult> movingAverages = prices.stream()
            .gather(Gatherers.windowSliding(20)
                .map(window -> {
                    StockPrice latest = window.get(window.size() - 1);
                    
                    // 计算5日均线
                    double ma5 = window.size() >= 5 ? 
                        window.subList(window.size() - 5, window.size()).stream()
                            .mapToDouble(StockPrice::price)
                            .average()
                            .orElse(0) : 0;
                    
                    // 计算20日均线
                    double ma20 = window.size() == 20 ?
                        window.stream()
                            .mapToDouble(StockPrice::price)
                            .average()
                            .orElse(0) : 0;
                    
                    return new MAResult(latest.date(), latest.price(), ma5, ma20);
                }))
            .toList();
            
        // 输出结果
        movingAverages.forEach(System.out::println);
    }
}

金融监控系统需要检测价格异常波动:

public static List<StockPrice> detectPriceAnomalies(List<StockPrice> prices, double threshold) {
    return prices.stream()
        .gather(Gatherers.scan(
            new double[]{0, 0},  // 初始值:[前一天价格, 变化百分比]
            (state, price) -> {
                double previousPrice = state[0];
                double percentChange = previousPrice > 0 ? 
                    (price.price() - previousPrice) / previousPrice * 100 : 0;
                
                // 更新状态
                state[0] = price.price();
                state[1] = percentChange;
                
                return state;
            })
            .filter(result -> Math.abs(result[1]) > threshold)
            .map(result -> prices.get((int)result[0])))
        .toList();
}

2、在Web服务器日志分析中,需要将用户点击流分组为会话:

import java.time.*;
import java.util.*;
import java.util.stream.Gatherers;

record LogEntry(String userId, Instant timestamp, String action) {}
record UserSession(String userId, List<LogEntry> activities, Duration duration) {}

public class LogAnalysis {
    public static List<UserSession> identifySessions(List<LogEntry> logs, Duration sessionTimeout) {
        // 首先按用户ID和时间排序
        List<LogEntry> sortedLogs = logs.stream()
            .sorted(Comparator.comparing(LogEntry::userId)
                .thenComparing(LogEntry::timestamp))
            .toList();
        
        return sortedLogs.stream()
            .gather(Gatherers.fold(
                HashMap::new, // 用户ID -> 当前会话
                (sessions, log) -> {
                    String userId = log.userId();
                    List<LogEntry> currentSession = sessions
                        .computeIfAbsent(userId, k -> new ArrayList<>());
                    
                    // 检查是否需要开始新会话
                    if (!currentSession.isEmpty()) {
                        LogEntry lastLog = currentSession.get(currentSession.size() - 1);
                        Duration gap = Duration.between(
                            lastLog.timestamp(), log.timestamp());
                            
                        if (gap.compareTo(sessionTimeout) > 0) {
                            // 会话超时,创建新会话
                            Instant start = currentSession.get(0).timestamp();
                            Instant end = lastLog.timestamp();
                            Duration sessionDuration = Duration.between(start, end);
                            
                            UserSession completedSession = new UserSession(
                                userId, 
                                new ArrayList<>(currentSession),
                                sessionDuration
                            );
                            
                            currentSession.clear(); // 重置当前会话
                            currentSession.add(log); // 添加到新会话
                            return completedSession;
                        }
                    }
                    
                    // 添加到当前会话
                    currentSession.add(log);
                    return null;
                },
                // 处理剩余的会话
                sessions -> {
                    List<UserSession> result = new ArrayList<>();
                    for (Map.Entry<String, List<LogEntry>> entry : sessions.entrySet()) {
                        if (!entry.getValue().isEmpty()) {
                            String userId = entry.getKey();
                            List<LogEntry> activities = entry.getValue();
                            
                            Instant start = activities.get(0).timestamp();
                            Instant end = activities.get(activities.size() - 1).timestamp();
                            Duration sessionDuration = Duration.between(start, end);
                            
                            result.add(new UserSession(userId, activities, sessionDuration));
                        }
                    }
                    return result;
                }
            ))
            .flatMap(List::stream)
            .toList();
    }
}

五、总结

Stream Gatherers作为JDK 24引入的重要API增强,为Java流处理提供了全新的范式。 它突破了传统Stream API在有状态操作和输入输出映射上的局限性,使开发者能够用更直观的方式表达复杂的数据处理逻辑。

通过本文介绍的滑动窗口、连续去重、自定义Gatherer和fold聚合等核心功能,我们可以看到Stream Gatherers在实际应用中的强大潜力,尤其是在金融分析、日志处理等需要维护状态或处理变长输出的场景中。

对于Java开发团队而言,掌握Stream Gatherers将成为提升数据处理效率的关键技能。在微服务、大数据分析和实时处理等现代应用架构中,Stream Gatherers的价值将更加凸显。随着JDK 24的正式发布,建议开发团队及早规划相关技术升级和知识培训,以充分利用这一强大特性带来的技术红利。

六、国内直接使用最新GPT-4.5、满血ChatGPT4o、o1、o3-mini-high、满血DeepSeek R1、马斯克Grok 3

✅️ChatGPT使用地址:www.nezhasoft.cloud

在这里插入图片描述

1、纯原版ChatGPT、Claude

✅️官网原生页面

✅️真实Team会员账号

2、技术支持

✔️支持最新ChatGPT-4.5、满血ChatGPT-4o、o1、o3-mini、o3-mini-high、o1 pro

✔️满血DeepSeek R1、马斯克Grok 3

✔️无需魔法、个人独享

3、支持所有GPTs + 自定义插件

支持ChatGPT所有插件,可创建自己的ChatGPT插件,使用朋友分享的自定义插件。

例如最强编程插件Code Copilot、AI绘画插件DALL-E、论文专属Consensus。

在这里插入图片描述

GPU:NVIDIA GPU的发展历史,nvidia-smi的简介、安装、使用方法之详细攻略 GPU:NVIDIA GPU的发展历史,nvidia-smi的简介、安装、使用方法之详细攻略 目录 NVIDIA GPU的发展历史 nvidia-smi的简介 1、nvidia-smi是nvidia 的系统管理界面解释相关参数含义 2、NVIDIA系统管理接口——v388.73 3、支持产品: nvidia-smi的安装 nvidia-smi的使用方法 1、列出所有可用的 NVIDIA 设备命令 2、nvidia-smi的基础命令用法 NVIDIA GPU的发展历 阅读详情

相关推荐

MT6771 Android13 背光曲线调试与光感数据校准实战

本文详细介绍了MT6771平台在Android 13系统上进行背光曲线调试与光感数据校准的实战经验。针对高亮度环境下背光误调节问题,深入分析了光感数据上报机制,并提供了驱动层配置修改、背光曲线优化及常见问题解决方案,帮助开发者快速定位并解决类似问题。

moon9的博客 287

对比jdk1.8,看jdk24 Stream Gatherers牛逼在哪?

JDK 1.8 的 Stream API 提供了一组固定的中间操作,开发者若需实现自定义逻辑,往往需要使用状态化的 lambda 表达式或外部库,这通常导致代码复杂且难以维护。Stream Gatherers 引入了 gather 方法,接受一个 Gatherer 对象。Gatherer 类似于 Collector,但用于中间操作而非终端操作。

学Java,找哪吒 1650

HybridCLR热更新全流程实操:用Addressables实现资源+代码双热更(Unity 2021版)

本文详细介绍了在Unity 2021 LTS版本中,如何结合HybridCLR代码热更新与Addressables资源管理系统,实现资源与代码的双热更解决方案。通过环境配置、技术架构设计、实战案例和性能优化,帮助开发者解决中大型项目中的依赖管理和版本协同问题,提升游戏迭代效率。

cc789的博客 845

Java 23:新功能正式公布

最新版本的 Java 开发工具包 23 (JDK) 在最新版本中具有四个新功能。根据此功能背后的 OpenJDK 提案,Java 平台应该定义和实现一个标准的类文件 API,该 API 与类文件格式一起发展,该格式可以轻松地更改或发展大约每六个月一次。自Java Development Kit 16发布以来, Vector API一直在Java的早期版本中孵化,一直到最新版本22。Java CodeBuilder 删除了与低级方法重复的中级方法,或者更糟糕的是,不经常使用的中级方法。

极道Jdon的技术博客 4490

SAP ABAP实战:手把手教你用BAPI_BILLINGDOC_CREATEMULTIPLE批量开票(附完整代码与避坑指南)

本文详细解析了SAP ABAP中BAPI_BILLINGDOC_CREATEMULTIPLE批量开票的全流程,包括参数配置、事务控制、错误处理及性能优化。通过实战案例和完整代码示例,帮助开发者高效处理大批量发票生成任务,避免常见陷阱,提升开发效率。

weixin_34101914的博客 265

合成孔径雷达(SAR)的常见工作模式

随着星载SAR技术研究的深入发展,单一的条带模式已经无法满足当今时代的需求,因此许多新的工作模式相继被提出。这些新模式在分辨率和测绘宽度等方面都有所提高,接下来将简要介绍几种常用的工作模式。

m0_51390495的博客 2314

gatherers4j:Java 24+ 流处理利器

gatherers4j:Java 24+ 流处理利器 在Java编程中,流(Stream)是一个强大的抽象,允许开发者以声明式方式处理数据集合。gatherers4j 是一个开源库,为 Java 24+ 提供了一系列实用的流收集器(custom intermediate operations),这些收集器能够极大丰富流的操作,使得复杂的数据处理任务变得更加简单和直观。 项目介绍 gatherers...

gitblog_00108的博客 488

Arxml文件可视化:当汽车软件架构遇见交互式设计工具

本文探讨了Arxml文件在汽车电子系统开发中的可视化技术,结合AUTOSAR架构标准,介绍了如何利用现代Web技术构建交互式设计工具。通过三维组件关系图、动态数据流展示和版本对比等功能,显著提升开发效率和架构评审质量,适用于MBD和ASPICE开发流程。

weixin_29050271的博客 427

Java 23新特性:流收集器

流收集器该特性为第二次预览,在Java 22中首次预览,并将在Java 24中成为正式特性。Java 8时引入的首个lambda表达式API,java.util.stream,该特性的目的是为Stream API提供自定义的中间操作。在该特性之前,Stream提供了一些固有的操作,如过滤,排序等,然而稍复杂的逻辑就很难用Stream实现。假设有这样的场景,在月销售统计数据中找到连续两个月增长的数据。

leonidZhao的博客 288

华为校招&实习&留学生机试真题目录+算法分类+在线OJ+通过率+视频讲解

全网最新最全华为校招&实习&留学生机试真题题库

m0_73659489的博客 6863

基于深度学习的番茄成熟度检测系统——YOLOv5、YOLOv8、YOLOv10及UI界面的实现

YOLO是一种快速且准确的目标检测模型,近年来,YOLOv5、YOLOv8和YOLOv10作为YOLO系列的重要版本,分别在速度、精度和效率上进行了优化。下面我们简要介绍这些模型。本文介绍了如何基于YOLOv5、YOLOv8和YOLOv10等深度学习模型,结合PyQt5设计一个番茄成熟度检测系统。通过训练模型、优化算法和设计用户友好的界面,我们能够构建一个高效且准确的番茄成熟度检测系统,广泛应用于农业自动化和智能化管理中。

YOLO 1002

Java 22 新增利器: 使用 Java Stream Gather 优雅地处理流中的状态

本文我们分析了 什么 是 “流”,对比了 Java 上几种常见的 “流”库,引入和详细介绍了 Java 22 中的 Stream Gather API 。同时也简单分享了利用 虚拟线程 如何简化 StreammapConcurrent操作符的实现。背景Java Stream 自从 Java 1.8 引入以来,迅速成为了各位开发者手中信手拈来的工具,大家日常在工作中谈论起来也是如数家珍。但由于 Ja...

淘系技术 1223

leetcode134 加油站

题目如下 在一条环路上有 N 个加油站,其中第 i 个加油站有汽油 gas[i] 升。 你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。 如果你可以绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1。 说明: 如果题目有解,该答案即为唯一答案。 输入数组均为非空数组,且长度相同。 输...

ayang818 's blog 233

Spring AI + GPT-5.5 + Ollama 配置教程:Base URL、超时与流式调用

由于不同 Spring AI、Spring Boot 小版本之间仍可能存在差异,创建项目时应检查 Spring Initializr、Spring AI BOM 和官方兼容矩阵,不要直接复制旧教程中的 Starter 名称和版本号。多人项目最好隔离不同客户端,并在脱敏前提下记录最终 URL、状态码、请求耗时、请求 ID 和模型 ID。Spring AI 接入模型 API,至少要同时确认 Starter、Base URL、请求路径、API Key、模型 ID、连接超时、读取超时和流式客户端这 8 项。

2601_95893075的博客 221

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

V8 机制、手写核心函数与 TypeScript 类型体操

或固定初始化(如数组先定长、对象先给全字段)保持类型与形状稳定;这些都比"换框架"更基础。只能处理纯数据(丢函数、Date、RegExp、循环引用报错)。生产级深拷贝要处理:原始值短路、循环引用、V8(Chrome / Node 的 JS 引擎)不是"解释一行跑一行"那么简单,它用。图:V8 执行流程——解释执行 + 热点优化,优化失败会 Deopt 回退。JS 内存自动管理,但"自动"不等于"不会漏"。是"固定间隔最多执行一次"。手写 Promise 是"懂异步"的试金石。是"停下后才执行最后一次",

qq_38468358的博客 328

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

【JVM】对象内存布局

HotSpot JVM 中,Java 对象内存布局由对象头(12字节,含Mark Word与压缩Klass Pointer)、实例数据及对齐填充构成,总大小为8字节倍数。对象头支持锁状态动态复用,指针压缩使引用仅4字节,但堆超32GB时失效。实例字段按类型优先级重排序以减少间隙,最小对象大小为16字节。通过JOL工具可精准验证布局,理解锁机制、GC、伪共享等底层行为。

2301_79732484的博客 149

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

Java EE 进阶:8.MyBatis 操作数据库(入门)(第一弹)

Java EE 进阶:8.MyBatis 操作数据库(入门)(第一弹)

要努力去发光,而不是被照亮~ 115

Spring Boot 数据源与 MyBatis(-Plus) 自定义配置详解

本文详解 Spring Boot 中单数据源环境下 HikariCP 与 MyBatis-Plus 的自定义配置。通过手动声明 SqlSessionFactory,实现下划线转驼峰、日志输出、一级缓存策略等精细化控制。结合 HikariCP 核心参数调优(如最大连接数、连接生命周期),确保高性能与稳定性。适用于仅需访问单一数据库的场景,避免多数据源复杂性,兼顾性能与可维护性。

BADAO_LIUMANG_QIZHI的博客 192

LeetCode Hot 100 二叉树专题(二)3 题(Java)

本篇文章共 3 题:543. 二叉树的直径、102. 二叉树的层序遍历、108. 将有序数组转换为二叉搜索树。 每道题都统一按「① 题目分析 & 解题思路 → ② 常见解法(附代码)及讲解 → ③ 知识点总结」的顺序组织;代码使用 Java 编写,节点定义沿用 LeetCode 默认的 TreeNode。

2401_88612756的博客 362

Decorator

TaskDecorator 是异步场景下"跨线程传递上下文"的标准方案,主要用于传递 MDC、用户信息、数据源路由等上下文数据,核心价值是让异步任务的日志链路不中断、业务上下文不丢失。TaskDecorator 是 Spring 提供的一个钩子接口,用于在异步任务执行前对 Runnable 进行包装,常用于跨线程传递上下文。如果你在项目中遇到具体的异步上下文传递问题,可以把代码贴出来,我帮你给出最合适的 Decorator 方案 👍。✅ 核心能力:在线程切换时,把"父线程的上下文"搬到"子线程"

wlwork66的博客 102

JDK 下载安装:装完 Java 提示「不是内部或外部命令」?环境变量没配

JDK 是写 Java 程序必须装的东西。它包含运行 Java 的虚拟机(JRE)和编译 Java 的编译器(javac)——装了它,能跑、.java文件能编译成可执行程序。免费,学习和小规模生产都不花钱。

科小怪的博客 625

数据库乐观锁深度解析:MySQL、PostgreSQL 实战 + Spring Boot 集成指南

Oracle 提供了ORA_ROWSCN伪列(System Change Number),记录最后修改行的 SCN,类似 PostgreSQL 的xmin。实践中通常仍使用 version 字段方案,逻辑与 MySQL 完全相同。-- Oracle:通过 ORA_ROWSCN 实现乐观锁-- 更新时比对 SCN// 自定义注解// AOP 切面@Aspect@Component@Slf4jtry {

yjc_1111的专栏 396

C++ 多态详解:作用、原理与实战用法

多态是C++面向对象的核心特性,通过虚函数实现运行期动态绑定,使同一接口在不同对象上表现出不同行为。其核心作用包括统一接口、提升可扩展性、降低耦合、支持运行时分派与批量处理。实现依赖虚函数表(vtable)和虚指针(vptr),需注意虚析构函数、对象切片等陷阱。相比编译期多态(模板),运行期多态灵活性高但有调用开销。合理结合两者,可兼顾代码的灵活性与性能,是构建可扩展、低耦合系统的关键。

2402_85743155的博客 376

java框架大全

java框架大全

qq_39326137的博客 183

Java 多态 学习笔记

多态是面向对象编程的重要特性,指同一操作作用于不同对象时产生不同行为。其核心在于“父类引用指向子类对象”,结合方法重写实现运行时动态绑定。多态使代码更灵活、可扩展,如用Person p = new Student();统一处理各类人员注册,无需修改调用逻辑。但多态无法直接调用子类特有方法,需通过instanceof判断并强制转换。编译时看左边(类型),运行时看右边(实际对象),实现解耦与维护便利。

AA_AA114514的博客 349

SecureRandom做随机源,这个Java随机字符串工具类有3个方法

本文分享一款JDK17环境下的Java随机字符串工具类,内置3个开箱即用的方法,全部采用SecureRandom加密安全随机源,不存在弱随机、可预测、取模偏差等问题。工具类支持默认62字符集随机串、纯数字随机串、自定义字符集随机串三种生成模式,支持Unicode码点级别的字符集处理,兼容Emoji等增补字符,边界处理严格,异常信息明确,适合验证码、邀请码、盐值、随机口令、短链码等场景,源码可直接复制使用。

Java后端 | AI智能体应用实战派 | 电脑技能行家 294
上一篇: 华为OD机试2025A卷七日集训第2期 - 按算法分类,由易到难,循序渐进,玩转OD(Python/JS/C/C++)
下一篇: 华为OD机试 - 数组去重和排序(Python/JS/C/C++ 2025 A卷 100分)
哪 吒
哪 吒 2022年度博客之星TOP 1 2022年度博客之星TOP 1 领域专家: 后端开发技术领域 领域专家: 后端开发技术领域
博客等级 码龄9年 59万+粉丝 2933原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哪 吒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值