小菜鸟

java菜鸟号正在起航

Java 时间操作全解析:从传统类到 Java 8 新 API

在 Java 中,时间操作是日常开发的常见需求,包括获取当前时间、格式化时间、计算时间差等。随着 Java 版本的演进,时间 API 也从早期的 DateCalendar 发展到 Java 8 引入的 java.time 系列(如 LocalDateTimeZonedDateTime),后者解决了传统 API 的线程不安全、设计混乱等问题。本文将全面介绍 Java 中操作时间的主要方式及最佳实践。

传统时间类(Java 8 之前)

1. java.util.Date

Date 是最早期的时间类,存储自 1970 年 1 月 1 日 00:00:00(UTC)以来的毫秒数,但大部分方法已被废弃(如 getYear()getMonth()),仅保留少数核心方法(如 getTime())。

示例:创建 Date 对象
import java.util.Date;

public class DateDemo {
    public static void main(String[] args) {
        Date now = new Date(); // 获取当前时间
        System.out.println(now); // 输出:Thu Aug 14 15:30:45 CST 2025
        System.out.println(now.getTime()); // 输出:1755166245000(毫秒时间戳)
    }
}
阅读全文 »

数据结构之线性结构:从基础概念到实现细节

线性结构是数据结构中最基础也最常用的一类,其核心特征是数据元素之间存在一对一的线性关系。常见的线性结构包括线性表(顺序表、链表)、队列、栈等。它们在逻辑上形成一条 “直线”,每个元素(除首尾外)有唯一的前驱和后继。

线性结构的核心特征

线性结构的元素间关系可概括为:

  • 存在唯一的 “首元素”(第一个元素)和 “尾元素”(最后一个元素)。
  • 除首元素外,每个元素有且仅有一个 “前驱”(前一个元素)。
  • 除尾元素外,每个元素有且仅有一个 “后继”(后一个元素)。

这种结构使得数据的遍历可以按线性顺序依次进行(如从首到尾)。

线性表:线性结构的基础

线性表是由零个或多个数据元素组成的有限序列,是线性结构的抽象模型。根据存储方式的不同,线性表可分为顺序表(顺序存储)和链表(链式存储)。

1. 顺序表(Sequential List)

顺序表是用连续的存储空间存储元素的线性表,逻辑上的顺序与物理存储顺序一致(类似数组)。

实现原理
  • 底层依赖数组,元素在内存中连续排列,通过下标直接访问。
  • 容量固定(可动态扩容),元素个数(size)≤ 容量(capacity)。
核心操作及时间复杂度
操作 实现逻辑 时间复杂度
访问(get) 通过下标直接定位元素 O(1)
插入(add) 若插入中间位置,需移动后续元素腾出空间 O(n)
删除(remove) 若删除中间元素,需移动后续元素填补空位 O(n)
扩容(ensureCapacity) 复制原数组到更大的新数组 O (n)(触发时)
阅读全文 »

算法简介:特性、性能分析与复杂度表示

算法是计算机科学的核心,是为解决特定问题而设计的一系列明确、可执行的步骤。一个高效的算法能显著提升程序性能,而理解算法的基本特性和性能分析方法,是设计和优化算法的基础。

算法的五大基本特性

算法必须满足以下五个核心特征,缺一不可:

  1. 有穷性
    算法必须在有限步骤内结束,不能无限循环。例如,求解斐波那契数列的算法需在计算到第 n 项后终止,而不是永远运行。
  2. 确定性
    算法的每一步操作必须无歧义,对于相同的输入,只能产生唯一的输出。例如,“将变量 a 的值增加 1” 是确定的,而 “将 a 的值稍微增加一点” 则不符合确定性。
  3. 输入
    算法可以有0 个或多个输入(从外部获取的数据)。例如,计算两个数的和需要 2 个输入,而打印 “Hello World” 则不需要输入。
  4. 输出
    算法必须有1 个或多个输出(与输入相关的结果)。输出是算法解决问题的体现,例如排序算法的输出是有序数组。
  5. 可行性
    算法的每一步操作必须能够通过有限次基本运算实现(如算术运算、逻辑判断等)。例如,“一步登天” 在现实中不可行,同理算法中不能包含无法执行的步骤。

算法性能分析:时间与空间复杂度

评价算法的优劣主要看其对时间和空间资源的占用,即时间复杂度和空间复杂度。它们不依赖具体硬件环境,而是通过数学模型描述算法的效率。

阅读全文 »

Kafka 核心 API 详解与实践:主题管理

Kafka 提供了四类核心 API 用于消息生产、消费、流处理和外部系统集成。其中,通过 kafka-clients 库的 AdminClient API 可实现对 Kafka 主题(Topic)的全生命周期管理,包括创建、查询、修改、删除及分区调整等操作。本文将详细介绍这些操作的实现方式,并提供完整代码示例。

Kafka 核心 API 概述

Kafka 的四类核心 API 分别面向不同场景:

API 类型 作用描述
Producer API 用于生产者发送消息到 Kafka 集群,支持自定义分区策略、消息压缩等特性。
Consumer API 用于消费者从 Kafka 集群拉取消息,支持消费组管理、偏移量控制等功能。
Streams API 用于构建流处理应用,实现对实时数据流的转换、聚合等操作。
Connect API 用于连接 Kafka 与外部系统(如数据库、文件系统),实现数据导入 / 导出。

本文重点介绍基于 AdminClient 的主题管理操作,需引入以下依赖:

<dependencies>
    <dependency>
        <groupId>org.apache.kafka</groupId>
        <artifactId>kafka-clients</artifactId>
        <version>2.3.1</version> <!-- 版本可根据实际需求调整 -->
    </dependency>
</dependencies>

主题管理实践

初始化 AdminClient

所有主题操作均需通过 AdminClient 完成,其初始化需要指定 Kafka 集群的 bootstrap 服务器地址:

阅读全文 »

Kafka 消费者 API 详解与实践

Kafka 消费者(Consumer)是消息的接收端,负责从 Kafka 集群拉取并处理消息。与生产者相比,消费者的核心挑战在于可靠地消费消息(避免丢失或重复)、高效地分配分区负载以及灵活地管理消费位置。本文将详细解析 Kafka 消费者 API 的使用方法,包括配置、订阅方式、偏移量管理及多线程消费等关键场景。

消费者核心配置与初始化

必选配置参数

创建消费者时,需通过 Properties 配置以下核心参数:

参数名 作用 示例值
bootstrap.servers Kafka 集群地址 localhost:9092
group.id 消费者组 ID(同一组内的消费者共同消费主题,避免重复) order-consumer-group
key.deserializer 消息键(Key)的反序列化类 org.apache.kafka.common.serialization.StringDeserializer
value.deserializer 消息值(Value)的反序列化类 org.apache.kafka.common.serialization.StringDeserializer

关键可选配置

参数名 作用 默认值
enable.auto.commit 是否自动提交偏移量 true(自动提交)
auto.commit.interval.ms 自动提交偏移量的间隔(毫秒) 5000
auto.offset.reset 偏移量无效时的重置策略(earliest:从最早消息开始;latest:从最新消息开始) latest
fetch.min.bytes 拉取消息的最小字节数(不足时等待) 1
fetch.max.wait.ms 拉取消息的最大等待时间(毫秒) 500
max.poll.records 一次 poll() 调用返回的最大消息数 500

初始化消费者

import org.apache.kafka.clients.consumer.KafkaConsumer;
import java.util.Properties;

public class KafkaConsumerDemo {
    private static KafkaConsumer<String, String> initConsumer() {
        Properties props = new Properties();
        // 必选配置
        props.put("bootstrap.servers", "localhost:9092");
        props.put("group.id", "test-group");
        props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
        props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
        
        // 可选配置:关闭自动提交,使用手动提交
        props.put("enable.auto.commit", "false");
        // 偏移量无效时从最早消息开始消费
        props.put("auto.offset.reset", "earliest");
        
        return new KafkaConsumer<>(props);
    }
}

订阅主题的四种方式

Kafka 提供了灵活的主题订阅方式,支持按主题名、正则表达式订阅,还可指定重平衡监听器。

按主题名订阅(基础方式)

通过 subscribe(Collection<String> topics) 订阅一个或多个主题:

阅读全文 »
0%