Java 数据结构

简要

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

常见的数据结构

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

数组(Array)

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

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

栈(Stack)

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

1import java.util.Stack; 2 3public class UseStack { 4 public static void main(String[] args) { 5 Stack<Integer> stack = new Stack<>(); 6 // 入栈,push 7 stack.push(1); 8 stack.push(2); 9 // 瞥一眼,但不会弹出 10 Integer peek = stack.peek(); 11 // 只要不是空,就继续弹 12 while (!stack.isEmpty()){ 13 // 出栈,pop 14 Integer pop = stack.pop(); 15 } 16 } 17}

队列(Queue)

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

1import java.util.LinkedList; 2import java.util.Queue; 3 4public class UseQueue { 5 public static void main(String[] args) { 6 Queue<Integer> queue = new LinkedList<>(); 7 // 加入队列 8 queue.add(1); 9 queue.add(2); 10 queue.add(3); 11 // peek,瞥一眼但不会弹出 12 Integer peek = queue.peek(); 13 while (!queue.isEmpty()){ 14 // 出队 15 Integer poll1 = queue.poll(); 16 } 17 } 18}

链表(Linked List)

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

1import java.util.LinkedList; 2 3public class UseLinkedList { 4 public static void main(String[] args) { 5 LinkedList<Integer> linkedList = new LinkedList<>(); 6 // 添加到头部 7 linkedList.addFirst(1); 8 linkedList.addFirst(2); 9 // 添加到尾部 10 linkedList.addLast(3); 11 linkedList.addLast(4); 12 // 此时应该是2-1-3-4,分别瞥见头部和尾部应该是2,4 13 System.out.println(linkedList.peekFirst()); 14 System.out.println(linkedList.peekLast()); 15 // 弹出头部 16 linkedList.removeFirst(); 17 // 弹出尾部 18 linkedList.removeLast(); 19 while (!linkedList.isEmpty()) { 20 // 一直从头部弹出,直至结束 21 linkedList.removeFirst(); 22 } 23 } 24}

树(Tree)

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

1class TreeNode { 2 int val; 3 TreeNode left; 4 TreeNode right; 5 6 TreeNode(int x) { 7 this.val = x; 8 } 9}

堆(Heap)

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

1import java.util.Comparator; 2import java.util.PriorityQueue; 3 4public class UseHeap { 5 public static void main(String[] args) { 6 PriorityQueue<Integer> minHeap = new PriorityQueue<>(); 7 minHeap.add(5); 8 minHeap.add(0); 9 minHeap.add(10); 10 // 瞥一眼,不会弹出,此时根部应该是0 11 Integer peekMin = minHeap.peek(); 12 while (!minHeap.isEmpty()) { 13 // 依次弹出0、5、10 14 System.out.println(minHeap.poll()); 15 } 16 17 // 大根堆,传入比较器,反转顺序 18 PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Comparator.reverseOrder()); 19 maxHeap.add(5); 20 maxHeap.add(0); 21 maxHeap.add(10); 22 // 瞥一眼,不会弹出,此时根部应该是10 23 Integer peekMax = maxHeap.peek(); 24 while (!maxHeap.isEmpty()) { 25 // 依次弹出10、5、0 26 System.out.println(maxHeap.poll()); 27 } 28 } 29}

散列表(Hash)

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

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

图(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 有序
点赞
收藏

评论区

加载中...

相关推荐

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

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

50道Java集合经典面试题(收藏版)

前言来了来了,50道Java集合面试题来了!1\.Arraylist与LinkedList区别可以从它们的底层数据结构、效率、开销进行阐述哈ArrayList是数组的数据结构,LinkedList是链表的数据结构。随机访问的时候,ArrayList的效率比较高,因为LinkedList要移动指针,而

Java 中常见的数据结构

1、数据结构有什么作用?当使用Java里面的容器类时,你有没有想过,怎么ArrayList就像一个无限扩充的数组,也好像链表之类的。很好使用,这就是数据结构的用处,只不过你在不知不觉中使用了。数据结构内容比较多,细细的讲解也是相对费功夫的,不可能达到一蹴而就。我就将常见的数据结构:堆栈、队列、数组、链表和红黑树给大家介绍一下,作

Java数据结构和算法(二)——数组

  上篇博客我们简单介绍了数据结构和算法的概念,对此模糊很正常,后面会慢慢通过具体的实例来介绍。本篇博客我们介绍数据结构的鼻祖——数组,可以说数组几乎能表示一切的数据结构,在每一门编程语言中,数组都是重要的数据结构,当然每种语言对数组的实现和处理也不相同,但是本质是都是用来存放数据的的结构,这里我们以Java语言为例,来详细介绍Java语言中数组的用法。