使用队列来优化递归操作完成文件下载

使用队列来优化递归操作完成文件下载

开发工具与关键技术:eclipse/ 递归&队列
作者:苦行者
撰写时间:2021年4月28日

一、 递归:
问:什么是递归?
答:通俗的讲就是“方法自己调用自己”。
那么它在内存中有什么特点?
递归操作在内存中的原理其实就是一个堆栈的过程,而栈结构的特点是“先进后出”,这与队列的“先进先出”的特性是截然相反的。
在这里插入图片描述

一般的,文件上传和下载需用到递归操作,它可以纵向遍历指定好的某个资源目录,然后把指定目录下的所有文件取出来,拿到对应文件的绝对资源路径,再拼接成一个超链接返回给浏览器供用户进行下载。
说到文件上传和下载就不得不提的是,递归操作它有一个缺点,就是当文件目录层次太深容易导致栈内存溢出,使程序死亡。
在这里插入图片描述

如上图所示:upload资源目录下有a和b两个子目录,而a目录下又有c、c目录下又有d、b目录下也有一个子目录e…这样一层嵌套一层,就跟俄罗斯的套娃一样。
每一级目录下都或多或少会存放着一些资源文件。如果这时候有这么一个需求,说是要把upload目录下的所有文件都下载下来,面对如此层次复杂的目录我们不可能一个个地拿到它们对应的文件路径以超链接的形式返回给浏览器提供下载,这样做不现实,代码量多且不说,而且我相信频繁写重复的代码这对于每一位程序员来说都是一种折磨。
那么要如何实现这一需求呢?自然而然我们都会想到要用递归,让它替我们把这一系列复杂的操作给做了,这样既能减少代码量,又能让程序看起来更具备逻辑性,这是一般的常规做法;
而假如我们的目录结构层次不止上面这么一点点,而是再多个十倍八倍的,这个时候再用递归的话恐怕就显得不那么稳妥,也不严谨,因为上面我们也说了,如果目录层次过深,容易导致内存溢出,使程序死亡,所以,这个时候,我们一般不用递归。
递归也不能用了,那该怎么办?别着急,东厂干不了的事情,不是还有我们西厂吗!
既然纵向遍历的递归不能干,那么我们不妨尝试一下使用队列,看看它与递归有什么不同之处,凭什么它可以而递归就要稍逊一筹?
二、 队列:
在jdk中有一个接口Queue,它有一个实现类叫做LinkedList,上Java基础课的时候曾与我们有过一面之缘,它其实就是一个队列。
在这里插入图片描述
Queue有如下几个方法:
在这里插入图片描述
offer(e)等同于add(e),都是往队列中插入元素,只不过add在操作失败时会抛出异常,而offer则是返回一个特殊值(null或false,具体取决于操作),且是用于专门为有容量限制的Queue实现设计的.。offer通常优于add,后者可能无法插入元素,而只是抛出一个异常。
remove()和poll()方法可移除和返回队列的头。到底从队列中移除哪个元素是队列排序策略的功能,而该策略在各种实现中是不同的。remove()和poll()方法仅在队列为空时其行为有所不同:remove()方法抛出一个异常,而poll()方法则返回一个null。
element()和peek()返回,但不移除队列的头,用于检索元素用的。
如果要使用队列,插入时要使用offer(e),获取时使用的是poll()
在使用队列之前,先让我们来看一下,使用递归是如何完成文件下载操作的,具体实现代码如下图所示:
在这里插入图片描述
打印结果:

在这里插入图片描述

成功打印upload目录下的所有文件名称。代码非常简单,for循环加个判断,再递归调用一下就能完整地实现一个文件下载的功能。只不过在这里我们一般不用它,不管是普通的练习项目还是一个真正的项目,我们都应该根据具体的需求来考虑我们程序功能的最大化,递归的好处毋庸置疑,但是也有局限性,至少它在本次专题里,我们考虑到的可能性以及相关的解决方案它就无法胜任。
递归如今我们都有所了解了,那么接下来就是队列的代码实现,具体代码如下:

在这里插入图片描述

运行结果:
在这里插入图片描述

显然,队列同样能够完成文件下载操作,不仅解决了目录层次过深容易导致内存溢出的问题,而且性能也会有所提升。

相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页