Java集合类——数据结构入门

前言

  要谈集合类,那必然绕不开数据结构。像ArrayList底层由数组实现,使用的是线性表的顺序存储结构;LinkedList使用的是线性表的链式存储结构;而HashMap则使用了散列存储结构......,等等这些,不一而足。可见集合类和数据结构之间关系之紧密。

  很明显,想要深入集合类的源码,必须具备一定程度的数据结构经验,这样才能起到事半功倍效果

一、数据结构

  数据结构是相互之间存在一种或多种特定关系的数据元素的集合(这是严蔚敏版《数据结构》给出的经典定义)。简单来说,只要存在一堆数据,这些数据就属于某一种数据结构了。可以根据这些数据之间的关系不同,把它们分成如下几种不同结构类型:

  其中线性结构和树形结构是需要重点关注的,集合类中常用的也是这两种数据结构。

  上述所说的数据结构(包括那个定义)我觉得更准确的描述应该是"数据间的结构",它更多的是从数据间的关系来阐述的(相当于后面叙述的逻辑结构)。但是从计算机的角度来说,能让计算机使用的数据才是有用的,否则都只能是空中楼阁。所以从数据结构这门学科来说,从广义的概念来说,数据结构往下可以分成两个大类:分别是"逻辑结构"和"存储结构"。

  逻辑结构描述的是数据之间的关系,与其如何存储无关。比如就队列这个概念来说,它的定义是先进先出的线性表。只要某数据集合中的数据符合该条件,那么它们的逻辑结构就是队列,与这些数据怎么存、存在哪都没有关系。

  存储结构描述的显然就应该是数据如何进行存储了。比如单向链表就是一个存储结构。单向链表一般由多个节点链接组成,每个节点包含两个域(数据域和指针域),前一个节点的指针域指向后一个节点,既前一个节点的指针域的值就是后一个节点的地址。这个概念中用到了地址,那么很明显单向链表是教我们如何存储数据的,所以单向链表是一种存储结构。

  在《数据结构》一书中出现了很多的概念,其中有些属于逻辑结构,有些属于存储结构,这些概念往往混在一起,让人无法区分。这里可以描述一个简单的区分方式:如果一个概念中包含了地址、引用地址计算、对存储位置有一定的要求等等这些,那么它描述的就是存储结构。因为这明显是在说应该怎样存储数据,把数据放到哪一个指定的位置(也就是地址)上更合适;如果某概念是以数据的特征、数据间的关系、数据可以进行的操作来做定义,定义中压根没有提到应该如何存放,那么它表就是一个逻辑结构的定义。

  下面简单举几个例子。

  第一个是数组。数组其实就是一堆有先后顺序的同类型的数据元素的集合。那显然它就是一个逻辑结构的概念。在绝大多数语言中,创建数组的时候,总会使用一片地址连续的存储空间来存放数组,但这并不意味着创建数组就一定要使用连续的地址空间。当然使用连续的地址是这些语言中设定好的规则(不像队列这种需要自己定义其数据类型,实现各种操作),这是由更加底层的代码来实现的,我们无法在编程中进行修改。不过如果语言的创建者愿意的话,我相信数组也是可以使用链式存储来实现的。综上用一句话来概括,就是数组这种逻辑结构是用顺序存储结构来实现的。

  第二个是循环队列。这是一个很特殊的概念。队列本身属于逻辑结构,但是循环队列却属于存储结构。了解这个概念的人都知道,想要构建循环队列,对存储形式和地址是有一定的要求的。首先要求得使用顺序存储结构,另外也不支持数组长度的动态扩展,而且还需要设置两个指针来判断队列是否已满(在C语言中这两个指针应该指向地址,java中一般指向引用的对象)。可以看到循环队列对如何存储做出了要求,并对数据地址也会有一定的判断,那么它就是一个存储结构。这是个较特殊的概念,如果考试此处会有坑。

  说了这么多,下面来看下常用的概念中哪些是逻辑结构,哪些是存储结构。

二、逻辑结构和存储结构的关系

  再来应该谈下逻辑结构和存储结构的关系。逻辑结构是人们想出来的数据之间的关系,其本质和计算机无关,然后又按照不同的类型被分成了如上图所示的几大类。当某些数据之间的关系符合上面某种类型定义的时候,我们就会说这些数据应该符合某种逻辑结构。

  比如我们的数据是军队的层级关系,那么就符合树形结构。一个军长下面会有多个师长,一个师长下面又有多个旅长这样。再比如数据是家庭成员关系,因为一个人可能有多个角色,比如是儿子,又是爸爸,和不同的人进行连线会有不同的关系。很显然这是一个多对多的关系,那么应该符合图状结构或网状结构。

  从这里也可以看出,逻辑结构的概念是与计算机无关的。

  但当我们想把这些数据,这种关系在计算机中表现出来的时候,那么就要和存储结构打交道了。因为存储结构能告诉我们如何把这些数据合理的存储到计算机中。通俗的来说,就是使用计算机语言(各种编程语言)把这些数据和逻辑关系表达出来。

  可以看出,对于计算机来说,特别是对于编程来说,逻辑结构和存储结构是相互依存的关系,它们紧密相连,缺一不可。所以我们经常会有这样的表述:"xx逻辑结构的xx存储结构的表示和实现",或者说"使用xx存储结构实现了xx逻辑结构"。比如"线性表的链式表示和实现";"线性表的顺序表示和实现";"使用循环队列实现了队列";"使用顺序存储实现了队列","使用顺序存储实现了数组"等等......

三、逻辑结构和存储结构对程序的影响

  下面说说这两种结构对程序的影响。谈影响,那么就不得不提到两个概念:时间复杂度和空间复杂度。这两个概念讲起来非常简单。

  时间复杂度代表运行这段程序需要多长时间,很明显越短越好;空间复杂度代表运行这段程序需要多大的存储空间,自然是越小越好。不过这两者一般来说就像是鱼和熊掌不可兼得。要不空间换时间,要不时间换空间,除此无他。在硬件容量越来越大,也越来越便宜的当下,可以说99%以上的算法都是仅考虑时间复杂度,不考虑空间复杂度。

  为什么上面不说100%,那是因为不是所有的硬件都便宜,有些特殊情况下工作的硬件很贵,比如飞出地球的那种,那种需要防辐射抗干扰,一颗CPU造价就高达十几万,频率还低,内存啥的自然也不便宜。这些情况暂时不谈。

  一个算法花费时间的长短,和它采用的逻辑结构还有存储结构都密切相关。比如我们要查找数组中的数据,在提供数组下标的情况下,时间复杂度为O(1),表示一次查找就可以了。但是当我们要删除一个数据的时候,时间复杂度就变成了O(n),这里的n指代数组中的数据量。因为我们删除一个元素之后,在该元素之后的所有元素都需要往前移动一位,很明显这个操作和数组本身的数据量有关,数据越多越慢。这个特性就是由数组所采用的存储结构决定的。顺序存储结构的特点就是查找快(有下标查找)、增删慢。这也是ArrayList的性质。

  如果一组数据采用树形结构来构建,那么这些数据一般也会有查找快的特点。这是由它的逻辑结构决定的。树的构建一般都有其规律,比如二叉查找树。该树的特点是节点左子树的元素比其小,右子树的元素比其大。按照此规律一般我们不需要遍历所有元素就能查找到我们想要的元素(前提是不要退化成链表)。同时如果采用链式存储的方式实现二叉查找树的话,那么它的增删也是很快的,这是链式存储结构所拥有的特性。

  可以说逻辑结构和存储结构加在一起,基本上就决定了程序的时间复杂度。剩下的一点点因素一般可以忽略不计,那就是计算机的硬件。比如CPU贼慢,1s计算1次这种,此时什么样的数据结构来也没用。当然现实来看这是不可能的。

  后面学习java中的集合类都是围绕这两大块进行的,从逻辑结构和存储结构的角度来看java中的集合类到底是如何实现的。

原文地址:https://www.cnblogs.com/Bingfengwangzuo/p/12149715.html

时间: 2024-10-15 04:24:11

Java集合类——数据结构入门的相关文章

Java集合类: Set、List、Map、Queue使用

目录 1. Java集合类基本概念 2. Java集合类架构层次关系 3. Java集合类的应用场景代码 1. Java集合类基本概念 在编程中,常常需要集中存放多个数据.从传统意义上讲,数组是我们的一个很好的选择,前提是我们事先已经明确知道我们将要保存的对象的数量.一旦在数组初始化时指定了这个数组长度,这个数组长度就是不可变的,如果我们需要保存一个可以动态增长的数据(在编译时无法确定具体的数量),java的集合类就是一个很好的设计方案了. 集合类主要负责保存.盛装其他数据,因此集合类也被称为容

针对Java集合类的小总结

Java集合类包位于java.util下,有很多常用的数据结构:数组.链表.队列.栈.哈希表等等.了解不同的集合类的特性在开发过程中是比较重要的,感谢@兰亭风雨的专栏分析,这里我也根据自己的理解做轻度的总结,不再进行分析,因为上面的博客分析已经相当优秀. List接口实现,一般常用的为ArrayList和LinkedList,还有不太常用的Vector,Stack.比如JDK文档声明 Deque 接口及其实现提供了 LIFO 堆栈操作的更完整和更一致的 set,应该优先使用此 set,而非Sta

Java集合类汇总记录-- apache.commons4(TreeList)

通常,Tree是Tree,List是List,两者不太可能混在一起.但apache-commons库却用tree实现了实现了List的接口,也就是TreeList类.与标准的LinkedList相比,TreeList稍微浪费一点空间,但常用操作的时间复杂度均降低到了O(log N),值得在开发中权衡利弊.合理应用. 内部数据结构 TreeList内部包含了一个Thread AVL Tree.AVL Tree很常见了,是一种典型的Balanced Binary Tree,但下面简单介绍下Threa

Java集合类相关面试题

1.Collection和Collections的区别 java.util.Collection 是一个集合接口,Collection接口在Java类库中有很多具体的实现,例如List.Set java.util.Collections 是针对集合类的一个帮助类,它提供了一系列的静态方法实现对各种集合的搜索.排序.线程安全化等操作. 2.ArrayList与Vector的区别 这两个类都实现了List接口(List接口继承自Collection接口).它们都是有序集合,它们内部的元素都是可以重复

Java集合类汇总记录--guava篇

BiMap HashBiMap<K,V> 实现了两份哈希表数据结构(本类独立实现),分别负责两个方向的映射. EnumBiMap<K,V> 两个EnumMap对象分别负责两个方向的映射. EnumHashBiMap<K,V> 一个EnumMap对象负责K到V映射,一个HashMap对象负责V到K的影身. MultiMap HashMultimap<K,V> 使用HashMap<K,HashSet<V>>对象实现. TreeMultim

[Java] 集合类(List、Set、Map的基本使用)

数组是一种很常见的数据结构,开始接触编程的时候多数程序都和数组相关.刚开始接触Java时也是一直使用数组写一些程序,后来越来越觉得... 数组是一种很常见的数据结构,开始接触编程的时候多数程序都和数组相关.刚开始接触Java时也是一直使用数组写一些程序,后来越来越觉得数组这东西没法满足需求了,这时一位"前辈"对我说了一句:不会用集合类就等于没学过Java.然后才知道有集合类. 想想已经是3.4年前的事了,时间如白驹过隙啊. 什么时候数组会显得力不从心,没法满足需求,需要集合类呢? 不知

Java集合类: Set、List、Map、Queue使用场景梳理

Java集合类: Set.List.Map.Queue使用场景梳理 本文主要关注Java编程中涉及到的各种集合类,以及它们的使用场景 相关学习资料 http://files.cnblogs.com/LittleHann/java%E9%9B%86%E5%90%88%E6%8E%92%E5%BA%8F%E5%8F%8Ajava%E9%9B%86%E5%90%88%E7%B1%BB%E8%AF%A6%E8%A7%A3%28collection%E3%80%81list%E3%80%81map%E3%

一张图让你看清Java集合类(Java集合类的总结)

如今关于Java集合类的文章非常多,可是我近期看到一个非常有意思图片,基本上把Java集合的整体框架都给展现出来了.非常直观. watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaWFtenAyMDA4/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" align="middle" > 假设发现图片看不清楚.点此处看大图 在这里,

【深入浅出】JAVA及安卓入门1-我的失败面试之行

前言                                                                                      虽然我已经被华硕研发中心录用,只等将三方协议交给华硕了,但是我还是一个闲不住的人,在学习java的过程中,我还去了诚迈面试,当时只是去试试,看看这些外包公司到底是咋么样的?需要我们这些本科生具备什么样的能力,然后在我完成了他们的笔试题以后,然后参加了他们的面试,面试官可能是临时拉过来面试的吧~~老感觉他不太乐意~~~然后面