Ari的小跟班

  :: :: 博问 :: 闪存 :: :: :: :: 管理 ::
  65 随笔 :: 1 文章 :: 1 评论 :: 15044 阅读

Java中实现的栈or队列两种方式对比

​ 我们知道,在Java中,可以直接使用Stack来实现栈,这是一种看到名字就会自动想到栈的类,但是现代Java编程中却不推荐使用Stack来实现栈,这是为什么?首先来看一下Java中的Collection接口继承图:

Stack

1.线程安全,但是带来的开销大,效率低

Stack是直接继承自Vector类,对于Vector类,该类是数组的古老实现,它是线程安全的,但是同样的,带来的效率会比较低下,所以在现代Java中不适合被使用。

2.使用数组实现,在频繁增减时效率低,随机查找带来的优势不明显

​ 既然是基于Vector实现,那么Stack的底层数据结构就是数组,对于数组,它具有查找快,删除数据慢的特点。对于栈栈这种只在一端进行数据操作的结构,链表是最适合的。

3.灵活性不好

​ 对于Stack,它只能用来实现栈的功能,而我们对于一些集合、散列表,都会采用面向接口编程(至于为什么普遍采用面向接口编程,这个我会在下面解释),而Stack的实现的接口是List,这就和栈的理念不符合,从接口层面来说,Stack不具备灵活性。

LinkedList

LinkedList是基于双向链表实现的,具有效率较快的对一端的元素进行增删的功能,而且它实现的接口也有QueueDeque,分别代表队列和双端队列,我们可以使用Queue<Integer> queue = new LinkedList<>();方便的创建一个队列,也可以将Queue改为Deque来实现双端队列。

​ 即灵活性好

​ 因为栈本质上就是在一端进行增删,那么这个需求完全可以由Deque这个双端队列来实现,Deque实现了两端的增、删、查的api(addLast. addFirst. removeLast. removeFirst. peekLast. peekFirst )。

public static void main(String[] args) {
Deque<Integer> stack = new LinkedList<>();
stack.addLast(1);
stack.addLast(2);
stack.removeLast();
System.out.println(stack);
}

​ 上面是使用LinkedList构造的一个栈。同样的,可以用这些api来构建队列、双端队列等等。

​ 而且LinkedList本身是线程不安全的,可以省去一些线程同步的开销,当然你也可以把线程同步的这个步骤放在LinkedList之外来做。

为什么建议采用面向接口编程?

​ 上面我说的,为什么大家使用集合类的时候,都喜欢初始化一个接口的引用呢?例如Map<String,Integer> map = new HashMap<>(); List<Integer> list = new ArrayList<>();

​ 而不是直接使用ArrayList<Integre> list = new ArrayList<>()

​ 其实对于功能上来说,这两种写法都是可以的,没有任何问题,并且使用ArrayList<Integre> list = new ArrayList<>()来初始化一个list反而可以使用的方法比使用接口来初始化的要多(它可以使用一些ArrayList特有的方法),比如public void trimToSize(),把一个ArrayList的实际大小缩小为它所持有的对象的数量(节省空间)。

​ 那么究竟为什么提倡采用接口命名呢?

​ 我们考虑一个场景,对于一个ArrayList<Integre> list = new ArrayList<>(),list的引用在初始化后,它就只能指向ArrayList及它的子类,假如你想把list指向另一个也可以提供列表功能的类的对象时,这个时候你就会发现,你做不到。

​ 假如我是用接口命名List<Integer> list = new ArrayList<>();,我的list时属于接口的,它可以指向任何实现了这个List接口的类的对象,灵活性大大增加了,并且接口的规范性,可以让我们忽略每个实现类内部的一些细节,当我只关注我想使用的集合的类型时(比如列表、哈希表等),我完全就可以使用接口命名,而这种场景也是我们在编程中遇到最多的,一言以蔽之:接口可以增加引用指向的灵活性,同时可以帮我们屏蔽一些实现类内部的细节,从而让我们更关注的使用集合的功能

​ 有的朋友就会问了,实现List的类,Java里也就那么几个,而且Vector现在也不用了,那为什么还要用接口呢?那假如我们的项目里用的List接口来实现列表,项目上线并运行了,但是过了一段时间发现这个List无法满足我们的业务需求,这个时候我们就可以使用重写一个实现List接口的类,直接改变引用即可,即我们可能会自己创建一些实现List接口的类,不必局限于Java中的几个实现了List接口的类。

posted on   Ari的小跟班  阅读(31)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示