看linkedlist部分底层代码的一些基础体会

看linkedlist部分底层代码的一些基础体会

首先从linkedlist最基本的元素结点node说起

问题1

为何node要设置成私有化的,这是java三大特性封装的优点。我们首先从调用者角度来思考问题。调用者在实际调用linkedlist类的时候,只关心这个list能否被创建(构造器),能否增删(add和remove),能否查找(遍历)。也就是说,他关心如何使用,而不是如何实现这个list中的这些方法。所以这些方法一般都是public,公开化的。调用者并不关心你底层的这个list是用结点实现的还是用数组实现的。所以这个结点类,作为内部类,他是私有化的。

从设计者角度分析,不同的数据结构有着不同的实现类型的结点,比如单向链表和双向链表的结点就不同,那么这个结点并不适合作为一个公用的属性,所以他作为一个单独数据结构的单独私有类,是合情合理的。另一方面,设计者也不需要让调用者知道list的结构单元是什么(也就是不想让调用者知道list底层是数组实现的还是结点实现的),反正他们只要会用就行了。这是一种黑匣子思想。而黑匣子思想也正是java封装特性的精髓。


那么从linkedlist的私有化方法说起

看linkedlist部分底层代码的一些基础体会

看linkedlist部分底层代码的一些基础体会

看linkedlist部分底层代码的一些基础体会


问题2

为何这些方法封装成私有化的

其实这个问题和问题1是一样的,因为我们呈现给调用者的是构造器,增删,遍历的方法,这些方法是公开化的,可以调用。但是这些方法具体如何实现的,调用者并不需要知道,我们也没必要让他们知道,所以我们封装成私有化,供linkedlist内部使用,并实现代码的复用性。

问题3

为何这些方法中创建的局部变量结点的引用是final的呢,我个人认为是这样的(可能不对,欢迎指正):

我们知道,linkedlist不像数组,我们想要查找元素,是比较麻烦的一件事情,数组可以按照下标index精确定位,而linkedlist只能从last或者first结点开始遍历向下查找想要找到的元素。那么这个遍历过程要确保的就是这个遍历路径是唯一的。那么这个路径的唯一性靠什么保证,那只能考结点的next和prev。那么既然next和prev是唯一性的,那么肯定是用final修饰。通俗来说,我们把结点当成目的地,next和prev当成路标。如果路标不唯一,那么你在去往目的地的过程中肯定会走错路,走错路必然到达不了目的地。如果next和prev不是唯一的,那么你在遍历过程中,万一这个结点的next和prev发生了变化,相当于产生了一个错误的岔路口,那么你肯定找不到你真正想要的那个结点。


栈可以用双端队列(双端队列用双向链表来实现)来实现(也就是说可以将Stack new成一个linkedlist),只需要对双端队列的队首进行push和pop操作就可以了。栈也可以用单向链表来实现。