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

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

导读

 

唐宋八大家之一欧阳修在《卖油翁》中写道:

 

| 翁取一葫芦置于地,以钱覆其口,徐以杓酌油沥之,自钱孔入,而钱不湿。因曰:“我亦无他,唯手熟尔。”

 

编写代码的老司机也是如此,老司机之所以被称为老司机”,原因也是无他,唯手熟尔。编码过程中踩过的坑多了,获得的编码经验也就多了,总结的编码技巧也就更多了。总结的编码技巧多了,凡事又能够举一反三,编码的速度自然就上来了。笔者从数据结构的角度,整理了一些Java编程技巧,以供大家学习参考。


一、 使用HashSet判断主键是否存在

 

HashSet实现Set接口,由哈希表(实际上是HashMap)实现,但不保证set的迭代顺序,并允许使用null元素。HashSet的时间复杂度跟HashMap一致,如果没有哈希冲突则时间复杂度为O1,如果存在哈希冲突则时间复杂度不超过On。所以,在日常编码中,可以使用HashSet判断主键是否存在。

 

案例

 

给定一个字符串不一定全为字母,请返回第一个重复出现的字符。

 

image.png

 

其中,由于Set的add函数有个特性——如果添加的元素已经再集合中存在,则会返回false。可以简化代码为:

 

image.png

 

二、 使用HashMap存取键值映射关系

 

简单来说,HashMap由数组和链表组成的,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的。如果定位到的数组位置不含链表,那么查找、添加等操作很快,仅需一次寻址即可,其时间复杂度为O1;如果定位到的数组包含链表,对于添加操作,其时间复杂度为On——首先遍历链表,存在即覆盖,不存在则新增;对于查找操作来讲,仍需要遍历链表,然后通过key对象的equals方法逐一对比查找。从性能上考虑,HashMap中的链表出现越少,即哈希冲突越少,性能也就越好。所以,在日常编码中,可以使用HashMap存取键值映射关系。

 

案例

 

给定菜单记录列表,每条菜单记录中包含父菜单标识(根菜单的父菜单标识为null),构建出整个菜单树。

 

/** 菜单DO类 */

@Setter

@Getter

@ToString

public static class MenuDO {

    /** 菜单标识 */

    private Long id;

    /** 菜单父标识 */

    private Long parentId;

    /** 菜单名称 */

    private String name;

    /** 菜单链接 */

    private String url;

}

 

/** 菜单VO类 */

@Setter

@Getter

@ToString

public static class MenuVO {

    /** 菜单标识 */

    private Long id;

    /** 菜单名称 */

    private String name;

    /** 菜单链接 */

    private String url;

    /** 子菜单列表 */

    private List<MenuVO> childList;

}

 

/** 构建菜单树函数 */

public static List<MenuVO> buildMenuTree(List<MenuDO> menuList) {

    // 检查列表为空

    if (CollectionUtils.isEmpty(menuList)) {

        return Collections.emptyList();

    }

 

    // 依次处理菜单

    int menuSize = menuList.size();

    List<MenuVO> rootList = new ArrayList<>(menuSize);

    Map<Long, MenuVO> menuMap = new HashMap<>(menuSize);

    for (MenuDO menuDO : menuList) {

        // 赋值菜单对象

        Long menuId = menuDO.getId();

        MenuVO menu = menuMap.get(menuId);

        if (Objects.isNull(menu)) {

            menu = new MenuVO();

            menu.setChildList(new ArrayList<>());

            menuMap.put(menuId, menu);

        }

        menu.setId(menuDO.getId());

        menu.setName(menuDO.getName());

        menu.setUrl(menuDO.getUrl());

 

        // 根据父标识处理

        Long parentId = menuDO.getParentId();

        if (Objects.nonNull(parentId)) {

            // 构建父菜单对象

            MenuVO parentMenu = menuMap.get(parentId);

            if (Objects.isNull(parentMenu)) {

                parentMenu = new MenuVO();

                parentMenu.setId(parentId);

                parentMenu.setChildList(new ArrayList<>());

                menuMap.put(parentId, parentMenu);

            }

            

            // 添加子菜单对象

            parentMenu.getChildList().add(menu);

        } else {

            // 添加根菜单对象

            rootList.add(menu);

        }

    }

 

    // 返回根菜单列表

    return rootList;

}

 

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

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