《Java工程师必读手册》——Java编程技巧系列——Java编程技巧之数据结构(4)

简介: 《Java工程师必读手册》——Java编程技巧系列——Java编程技巧之数据结构(4)

接上篇:https://developer.aliyun.com/article/1228148?spm=a2c6h.13148508.setting.27.21084f0eNCKPti


六、 定义Holder类实现参数的输出

 

在很多语言中,函数的参数都有输入(in)、输出(out)和输入输出(inout)之分。在C/C++语言中,可以用对象的引用(&)来实现函数参数的输出(out)和输入输出(inout)。

 

但在Java语言中,虽然没有提供对象引用类似的功能,但是可以通过修改参数的字段值来实现函数参数的输出(out)和输入输出(inout)。

 

这里,我们叫这种输出参数对应的数据结构为Holder(支撑)类。

 

1. Holder类实现代码

 

image.png 

 

2. Holder类使用案例

 

image.png 

 

其实,可以实现一个泛型支撑类,适用于更多的数据类型。

 

七、 定义Union类实现数据体的共存

 

在C/C++语言中,联合体(union),又称共用体,类似结构体(struct)的一种数据结构。联合体(union)和结构体(struct)一样,可以包含很多种数据类型和变量,两者区别如下:

 

结构体(struct)中所有变量是“共存”的,同时所有变量都生效,各个变量占据不同的内存空间;

联合体(union)中是各变量是“互斥”的,同时只有一个变量生效,所有变量占据同一块内存空间。

 

当多个数据需要共享内存或者多个数据每次只取其一时,可以采用联合体(union)。

 

在Java语言中,没有联合体(union)和结构体(struct)概念,只有类(class)的概念。众所众知,结构体(struct)可以用类(class)来实现。其实,联合体(union)也可以用类(class)来实现。但是,这个类不具备“多个数据需要共享内存”的功能,只具备“多个数据每次只取其一”的功能。

 

这里,以微信协议的客户消息为例说明。根据我多年来的接口协议封装经验,主要有以下两种实现方式。

 

1. 使用函数方式实现Union

 

1) Union类实现

 

/** 客户消息类 */

@ToString

public class CustomerMessage {

 

    /** 属性相关 */

    /** 消息类型 */

    private String msgType;

    /** 目标用户 */

    private String toUser;

 

    /** 共用体相关 */

    /** 新闻内容 */

    private News news;

    ...

 

    /** 常量相关 */

    /** 新闻消息 */

    public static final String MSG_TYPE_NEWS = "news";

    ...

 

    /** 构造函数 */

    public CustomerMessage() {}

 

    /** 构造函数 */

    public CustomerMessage(String toUser) {

        this.toUser = toUser;

    }

 

    /** 构造函数 */

    public CustomerMessage(String toUser, News news) {

        this.toUser = toUser;

        this.msgType = MSG_TYPE_NEWS;

        this.news = news;

    }

 

    /** 清除消息内容 */

    private void removeMsgContent() {

        // 检查消息类型

        if (Objects.isNull(msgType)) {

            return;

        }

 

        // 清除消息内容

        if (MSG_TYPE_NEWS.equals(msgType)) {

            news = null;

        } else if (...) {

        ...

}

        msgType = null;

    }

 

    /** 检查消息类型 */

    private void checkMsgType(String msgType) {

        // 检查消息类型

        if (Objects.isNull(msgType)) {

            throw new IllegalArgumentException("消息类型为空");

        }

 

        // 比较消息类型

        if (!Objects.equals(msgType, this.msgType)) {

            throw new IllegalArgumentException("消息类型不匹配");

        }

    }

 

    /** 设置消息类型函数 */

    public void setMsgType(String msgType) {

        // 清除消息内容

        removeMsgContent();

 

        // 检查消息类型

        if (Objects.isNull(msgType)) {

            throw new IllegalArgumentException("消息类型为空");

        }

 

        // 赋值消息内容

        this.msgType = msgType;

        if (MSG_TYPE_NEWS.equals(msgType)) {

            news = new News();

        } else if (...) {

        ...

} else {

            throw new IllegalArgumentException("消息类型不支持");

        }

    }

 

    /** 获取消息类型 */

    public String getMsgType() {

        // 检查消息类型

        if (Objects.isNull(msgType)) {

            throw new IllegalArgumentException("消息类型无效");

        }

 

        // 返回消息类型

        return this.msgType;

    }

 

    /** 设置新闻 */

    public void setNews(News news) {

        // 清除消息内容

        removeMsgContent();

 

        // 赋值消息内容

        this.msgType = MSG_TYPE_NEWS;

        this.news = news;

    }

 

    /** 获取新闻 */

    public News getNews() {

        // 检查消息类型

        checkMsgType(MSG_TYPE_NEWS);

 

        // 返回消息内容

        return this.news;

    }

    

    ...

}

 

2) Union类使用

 

image.png

 

3) 主要优缺点

 

优点:更贴近C/C++语言的联合体(union);

缺点:实现逻辑较为复杂,参数类型验证较多。

 

2. 使用继承方式实现Union

 

1) Union类实现

 

/** 客户消息类 */

@Getter

@Setter

@ToString

public abstract class CustomerMessage {

    /** 属性相关 */

    /** 消息类型 */

    private String msgType;

    /** 目标用户 */

    private String toUser;

 

    /** 常量相关 */

    /** 新闻消息 */

    public static final String MSG_TYPE_NEWS = "news";

    ...

 

    /** 构造函数 */

    public CustomerMessage(String msgType) {

        this.msgType = msgType;

    }

 

    /** 构造函数 */

    public CustomerMessage(String msgType, String toUser) {

        this.msgType = msgType;

        this.toUser = toUser;

    }

}

 

/** 新闻客户消息类 */

@Getter

@Setter

@ToString(callSuper = true)

public class NewsCustomerMessage extends CustomerMessage {

 

    /** 属性相关 */

    /** 新闻内容 */

    private News news;

 

    /** 构造函数 */

    public NewsCustomerMessage() {

        super(MSG_TYPE_NEWS);

    }

 

    /** 构造函数 */

    public NewsCustomerMessage(String toUser, News news) {

        super(MSG_TYPE_NEWS, toUser);

        this.news = news;

    }

}

 

2) Union类使用

 

image.png

 

3) 主要优缺点

 

优点:使用虚基类和子类进行拆分,各个子类对象的概念明确;

缺点:与C/C++语言的联合体(union)差别大,但是功能上大体一致。

 

在C/C++语言中,联合体并不包括联合体当前的数据类型。但在上面实现的Java联合体中,已经包含了联合体对应的数据类型。所以,从严格意义上说,Java联合体并不是真正的联合体,只是一个具备“多个数据每次只取其一”功能的类。


 接下篇:https://developer.aliyun.com/article/1228146?groupCode=java

 

相关文章
|
7月前
|
前端开发 Java
java实现队列数据结构代码详解
本文详细解析了Java中队列数据结构的实现,包括队列的基本概念、应用场景及代码实现。队列是一种遵循“先进先出”原则的线性结构,支持在队尾插入和队头删除操作。文章介绍了顺序队列与链式队列,并重点分析了循环队列的实现方式以解决溢出问题。通过具体代码示例(如`enqueue`入队和`dequeue`出队),展示了队列的操作逻辑,帮助读者深入理解其工作机制。
249 1
|
5月前
|
搜索推荐 算法 Java
2025 年互联网大厂校园招聘 JAVA 工程师笔试题及备考要点解析
本文针对互联网大厂校招Java工程师笔试题进行解析,涵盖基础知识、面向对象编程、数据结构与算法、异常处理及集合框架等核心内容。从数据类型、运算符到流程控制语句,从类与对象、继承多态到数组链表、排序算法,再到异常捕获与集合框架应用,结合实际案例深入剖析,助你系统掌握考点,提升应试能力。资源链接:[点此获取](https://pan.quark.cn/s/14fcf913bae6)。
245 9
|
5月前
|
Java 数据库连接 API
互联网大厂校招 JAVA 工程师笔试题解析及常见考点分析
本文深入解析互联网大厂校招Java工程师笔试题,涵盖基础知识(数据类型、流程控制)、面向对象编程(类与对象、继承与多态)、数据结构与算法(数组、链表、排序算法)、异常处理、集合框架、Java 8+新特性(Lambda表达式、Stream API)、多线程与并发、IO与NIO、数据库操作(JDBC、ORM框架MyBatis)及Spring框架基础(IoC、DI、AOP)。通过技术方案讲解与实例演示,助你掌握核心考点,提升解题能力。
240 2
|
5月前
|
存储 安全 Java
Java 集合面试题从数据结构到 HashMap 源码剖析详解及长尾考点梳理
本文深入解析Java集合框架,涵盖基础概念、常见集合类型及HashMap的底层数据结构与源码实现。从Collection、Map到Iterator接口,逐一剖析其特性与应用场景。重点解读HashMap在JDK1.7与1.8中的数据结构演变,包括数组+链表+红黑树优化,以及put方法和扩容机制的实现细节。结合订单管理与用户权限管理等实际案例,展示集合框架的应用价值,助你全面掌握相关知识,轻松应对面试与开发需求。
300 3
|
存储 Java
Java中的HashMap和TreeMap,通过具体示例展示了它们在处理复杂数据结构问题时的应用。
【10月更文挑战第19天】本文详细介绍了Java中的HashMap和TreeMap,通过具体示例展示了它们在处理复杂数据结构问题时的应用。HashMap以其高效的插入、查找和删除操作著称,而TreeMap则擅长于保持元素的自然排序或自定义排序,两者各具优势,适用于不同的开发场景。
146 1
|
7月前
|
存储 Java 编译器
Java 中 .length 的使用方法:深入理解 Java 数据结构中的长度获取机制
本文深入解析了 Java 中 `.length` 的使用方法及其在不同数据结构中的应用。对于数组,通过 `.length` 属性获取元素数量;字符串则使用 `.length()` 方法计算字符数;集合类如 `ArrayList` 采用 `.size()` 方法统计元素个数。此外,基本数据类型和包装类不支持长度属性。掌握这些区别,有助于开发者避免常见错误,提升代码质量。
770 1
|
9月前
|
机器学习/深度学习 Java PyTorch
Java工程师如何理解张量?
刚接触AI和PyTorch,理解“张量(Tensor)”是入门关键。张量可类比为Java中的多维数组,但更强大,尤其在AI领域支持GPU加速、自动求导等特性。它不仅能高效存储数据,还能进行复杂运算,是深度学习的核心数据结构。掌握张量的维度、数据类型及GPU加速特性,对学习PyTorch至关重要。
258 3
|
11月前
|
存储 缓存 安全
Java 集合江湖:底层数据结构的大揭秘!
小米是一位热爱技术分享的程序员,本文详细解析了Java面试中常见的List、Set、Map的区别。不仅介绍了它们的基本特性和实现类,还深入探讨了各自的使用场景和面试技巧,帮助读者更好地理解和应对相关问题。
181 5
|
缓存 算法 Java
本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制
在现代软件开发中,性能优化至关重要。本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制。通过调整垃圾回收器参数、优化堆大小与布局、使用对象池和缓存技术,开发者可显著提升应用性能和稳定性。
218 6
|
存储 Java 索引
Java中的数据结构:ArrayList和LinkedList的比较
【10月更文挑战第28天】在Java编程世界中,数据结构是构建复杂程序的基石。本文将深入探讨两种常用的数据结构:ArrayList和LinkedList,通过直观的比喻和实例分析,揭示它们各自的优势与局限,帮助你在面对不同的编程挑战时做出明智的选择。