Java 数据结构

Wesley13
• 阅读 803

简要

本文主要介绍数据结构以及在 Java 中有哪些直接可用的数据结构(不涉及并发编程使用场景)。

常见的数据结构

下面直接介绍的常见的数据结构:数组(Array)、栈(Stack)、队列(Queue)、链表(Linked List)、树(Tree)、堆(Heap)、散列表(Hash)、图(Graph)

数组(Array)

数组是最基本的数据结构,有一维数组,二维数组等等,底层存储方式是连续的内存。 Java 中的使用:

int[] array1 = new int[10];
int[][] array2 = new int[10][10];
array1[1] = 10;
array2[0][10] = 11;

栈(Stack)

栈是先进后出(FILO,First In Last Out)的数据结构。 Stack 类在 java.util 包下,使用:

import java.util.Stack;

public class UseStack {
    public static void main(String[] args) {
        Stack<Integer> stack = new Stack<>();
        // 入栈,push
        stack.push(1);
        stack.push(2);
        // 瞥一眼,但不会弹出
        Integer peek = stack.peek();
        // 只要不是空,就继续弹
        while (!stack.isEmpty()){
            // 出栈,pop
            Integer pop = stack.pop();
        }
    }
}

队列(Queue)

队列是先进先出(FIFO)结构。 队列在 Java 中没有直接的实现,只是定义了接口。一般使用 LinkedList 类去充当队列使用。 实现了 Queue 接口的常见类有:LinkedList 类,PriorityQueue 类(优先级队列,即堆)。

import java.util.LinkedList;
import java.util.Queue;

public class UseQueue {
    public static void main(String[] args) {
        Queue<Integer> queue = new LinkedList<>();
        // 加入队列
        queue.add(1);
        queue.add(2);
        queue.add(3);
        // peek,瞥一眼但不会弹出
        Integer peek = queue.peek();
        while (!queue.isEmpty()){
            // 出队
            Integer poll1 = queue.poll();
        }
    }
}

链表(Linked List)

在 java 的实现中,LinkedList 直接是可以当成双向链表使用。Java 中也有 ArrayList,是使用数组的方式去实现的链表。 由于双向链表的特殊性,所以可以当成队列,也可以当成栈使用,在 Java 中都实现了这些方法。 在这里为了避免理解造成歧义,还是用比较符合人的常规理解去使用他比较好,示例:

import java.util.LinkedList;

public class UseLinkedList {
    public static void main(String[] args) {
        LinkedList<Integer> linkedList = new LinkedList<>();
        // 添加到头部
        linkedList.addFirst(1);
        linkedList.addFirst(2);
        // 添加到尾部
        linkedList.addLast(3);
        linkedList.addLast(4);
        // 此时应该是2-1-3-4,分别瞥见头部和尾部应该是2,4
        System.out.println(linkedList.peekFirst());
        System.out.println(linkedList.peekLast());
        // 弹出头部
        linkedList.removeFirst();
        // 弹出尾部
        linkedList.removeLast();
        while (!linkedList.isEmpty()) {
            // 一直从头部弹出,直至结束
            linkedList.removeFirst();
        }
    }
}

树(Tree)

树是典型的非线性结构。 树的使用在做题中很常见,在题目中最常见的是二叉树,二叉树有广度遍历(按层遍历)和深度遍历(先序、中序、后序)。 关于按层遍历,主要实现方式是使用一个队列即可。 关于代码实现的方式可以是递归(系统压栈),使用栈,这些都是要额外空间复杂度的,还有空间复杂度为 O(1) 的遍历方法即 Morris 遍历。 Java 中没有 Tree 的数据结构,不过我们可以自己写一个,至于拓展,自己可以随便玩:

class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;

    TreeNode(int x) {
        this.val = x;
    }
}

堆(Heap)

堆分为大根堆和小根堆,大根堆是大的在根部上,小根堆是小的在根部上。每次加入或者弹出新的元素,内部通过调整维持优先级顺序,其实也就是优先级队列。 在 Java 中,直接就是优先级队列。 默认小根堆,也可以改默认,构造时传入比较器即可,使用示例:

import java.util.Comparator;
import java.util.PriorityQueue;

public class UseHeap {
    public static void main(String[] args) {
        PriorityQueue<Integer> minHeap = new PriorityQueue<>();
        minHeap.add(5);
        minHeap.add(0);
        minHeap.add(10);
        // 瞥一眼,不会弹出,此时根部应该是0
        Integer peekMin = minHeap.peek();
        while (!minHeap.isEmpty()) {
            // 依次弹出0、5、10
            System.out.println(minHeap.poll());
        }
        
        // 大根堆,传入比较器,反转顺序
        PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Comparator.reverseOrder());
        maxHeap.add(5);
        maxHeap.add(0);
        maxHeap.add(10);
        // 瞥一眼,不会弹出,此时根部应该是10
        Integer peekMax = maxHeap.peek();
        while (!maxHeap.isEmpty()) {
            // 依次弹出10、5、0
            System.out.println(maxHeap.poll());
        }
    }
}

散列表(Hash)

散列表就是一个 Key-Value 结构。Key 通过哈希函数(Hash Function)映射到某个存储位置,从而实现查询时间复杂度为 O(1)。 哈希冲突的解决方法常见的有线性探测法,拉链法等。 在 Java 中其叫做 HashMap,使用示例:

import java.util.HashMap;

public class UseHashMap {
    public static void main(String[] args) {
        // 构造函数可传入初始容量(默认是16),如果需要比较大的容量,可以避免动态拓展带来的性能消耗
        HashMap<Integer, String> hashMap = new HashMap<>();
        // 存入key-value对
        hashMap.put(1, "张三");
        hashMap.put(2, "李四");
        hashMap.put(3, "王五");
        // 是否包含key,这里是true
        System.out.println(hashMap.containsKey(1));
        String name = hashMap.get(2);
        // 没有key默认"佚名"
        hashMap.getOrDefault(10,"佚名");
        // 移除key-value对
        hashMap.remove(1);
    }
}

图(Graph)

Java 中也没有图,图用的相对少,以后用到再补充。

Java的中的容器类

Java 中的容器类(常见的一些数据结构,数据结构就是数据的容器),一般放在 java.util 包下。 主要有两大类集合(Collection)和 映射(Map)。

集合

实现集合接口主要有三大接口:

  • Set:常见实现类,TreeSet,HashSet,LinkedHashSet
  • List:常见实现类,ArrayList,LinkedList
  • Queue:常见实现类,LinekdList,PriorityQueue

分别介绍:

  • TreeSet:key 有序,底层实现是红黑树去维持 key 的顺序,插入和查询的时间复杂度会上升但 key 有序
  • HashSet:key 查询快,底层实现是使用哈希表的方式,value 是一个 Object 对象,移除的时候如果是 null 不好判断是否移除成功
  • LinkedHashSet:比 HashSet 多了一个功能,那就是使用双向链表维护添加 key 的顺序
  • ArrayList:链表的实现方式,顺序存储。查询快,插入慢
  • LinkedList:链表的实现方式,链式存储。查询慢,插入快
  • PriorityQueue:优先级队列,底层实现使用数组实现

映射

实现 Map 接口的常见类有:HashMap,LinkedHashMap,TreeMap

分别介绍:

  • HashMap:最常用的
  • LinkedHashMap:使用双向链表维护添加顺序,可以是插入顺序和 LRU 顺序,通过继承该类,重写 removeEldestEntry 方法可以实现一个 LRU 缓存
  • TreeMap:有序的映射,底层实现是红黑树,插入和查询的时间复杂度会降低,但 key 有序
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
待兔 待兔
3个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Stella981 Stella981
3年前
50道Java集合经典面试题(收藏版)
前言来了来了,50道Java集合面试题来了!1\.Arraylist与LinkedList区别可以从它们的底层数据结构、效率、开销进行阐述哈ArrayList是数组的数据结构,LinkedList是链表的数据结构。随机访问的时候,ArrayList的效率比较高,因为LinkedList要移动指针,而
Wesley13 Wesley13
3年前
PHP中HASH函数的优化技巧
Hash数据结构是一种非常常见的数据结构,作为一个程序员,你可能每天都在和它接触,尽管很多时候你可能没有意识到。Hash在PHP内核中扮演了非常重要的角色,数组、变量作用域、函数参数列表等均是基于Hash实现。所以,在PHP里你能看到各种对于Hash的优化。Hash数据结构Hash数据结构,本质上为了解决计算机中真正意义的数组只能使用数字作
Wesley13 Wesley13
3年前
Java 中常见的数据结构
1、数据结构有什么作用?当使用Java里面的容器类时,你有没有想过,怎么ArrayList就像一个无限扩充的数组,也好像链表之类的。很好使用,这就是数据结构的用处,只不过你在不知不觉中使用了。数据结构内容比较多,细细的讲解也是相对费功夫的,不可能达到一蹴而就。我就将常见的数据结构:堆栈、队列、数组、链表和红黑树给大家介绍一下,作
Wesley13 Wesley13
3年前
Java学习系列——第3课Java 高级教程
java数据结构  1)【概述】  Java的工具包提供了强大的数据结构在的Java中的数据结构主要包括以下几种接口和类:枚举(枚举)位集合(位集合)向量(矢量)栈(栈)字典(词典)哈希表(哈希表)属性(属性)
Wesley13 Wesley13
3年前
Java数据结构和算法(二)——数组
  上篇博客我们简单介绍了数据结构和算法的概念,对此模糊很正常,后面会慢慢通过具体的实例来介绍。本篇博客我们介绍数据结构的鼻祖——数组,可以说数组几乎能表示一切的数据结构,在每一门编程语言中,数组都是重要的数据结构,当然每种语言对数组的实现和处理也不相同,但是本质是都是用来存放数据的的结构,这里我们以Java语言为例,来详细介绍Java语言中数组的用法。
Wesley13 Wesley13
3年前
Java基础之数组队列及Java堆外内存学习笔记[图]
Java基础之数组队列及Java堆外内存学习笔记\图\1.数组1.1数组基本概念:数组是一个容器,可以存储同一数据类型的N个数据;数组是一个数据结构,是数据结构中访问速度最快的;数组是直接通过下标进行定位;数组是属于引用数据类型(数组名中存储的是内存首地址);数组本身只有有length属性(获取数组能存储的数据个数),但是