关于Java集合的十大问题

85 篇文章 0 订阅
82 篇文章 0 订阅

伙伴们注意了!

小编在这里给大家送上关注福利:

搜索微信号“suxueJava”即可领取小编精心准备的资料一份!

以下是在Stackoverflow上询问和讨论的Java集合最流行的问题。
在查看这些问题之前,最好先查看类层次图。

1. 什么时候使用LinkedList而不是ArrayList?

ArrayList本质上是一个数组。
它的元素可以通过索引直接访问。
但如果数组已满,则需要一个更大的新数组来分配和移动所有元素到新数组将花费O(n)时间。
添加或删除元素还需要移动数组中的现有元素。
这可能是使用ArrayList的最大缺点。

LinkedList是一个双链表。
因此,要访问中间的元素,必须从列表的开头进行搜索。
另一方面,在LinkedList中添加和删除元素更快,因为它只在本地更改列表。

综上所述,时间复杂度比较最坏的情况如下:

尽管运行时间很长,但是对于大型列表来说,内存的使用也应该被考虑在内。在LinkedList中,每个节点至少需要两个额外的指针来链接上一个和下一个节点;而在ArrayList中,只需要一个元素数组。

2. 在迭代集合时删除元素的有效等效方法

在迭代时修改集合的惟一正确方法是使用Iterator.remove()。例如,

最常见的错误代码是

通过运行上面的代码,您将获得一个ConcurrentModificationException异常。
这是因为已经生成了一个迭代器(在for语句中)来遍历列表,但同时list被iterator .remove()更改。
在Java中,“通常不允许一个线程在另一个线程遍历集合时修改该集合”。

3.如何将List转换为int[]?

最简单的方法可能是在Apache Commons Lang库中使用ArrayUtils。

在JDK中,没有捷径。
注意,您不能使用List. toarray(),因为这会将List转换为Integer[]。
正确的方法如下,

4.如何将int[]转换为List?

最简单的方法可能仍然是在Apache Commons Lang库中使用ArrayUtils,如下所示。

在JDK中,也没有捷径。

5.筛选集合的最佳方法是什么?

同样,您可以使用第三方包,如Guava或Apache Commons Lang来完成此功能。

两者都提供了filter()方法(在番石榴的Collections2和Apache的CollectionUtils中)。

filter()方法将返回与给定谓词匹配的元素。

在JDK中,事情变得更加困难。

好消息是,在Java 8中,将添加谓词。

但是现在您必须使用Iterator来遍历整个集合。

当然,您可以通过引入新的接口谓词来模仿番石榴和Apache的做法。
这可能也是大多数高级开发人员将要做的事情。

 然后我们可以使用下面的代码来过滤一个集合:

6. 将列表转换为集合的最简单方法?

有两种方法可以这样做,这取决于您希望如何定义等号。第一部分代码将一个列表放入一个HashSet中。

然后,重复主要由hashCode()标识。在大多数情况下,这是可行的。但是如果您需要指定比较的方式,最好使用第二段代码,其中可以定义自己的比较器。

7. 如何从ArrayList中删除重复的元素?

这个问题和上面的问题有很大的关系。

如果您不关心ArrayList中元素的顺序,一个聪明的方法是将列表放入一个集合中以删除重复,然后将其移回列表中。下面是代码

如果您确实关心排序,那么可以通过将一个列表放入标准JDK中的Linkedhashset中来保留顺序。

8.分类收集

有几种方法可以在Java中维护排序的集合。它们都以自然顺序或通过指定的比较器提供了一个集合。通过自然排序,您还需要在元素中实现可比较的接口。

collections.sort()可以对列表进行排序。正如JavaDoc中指定的那样,这种排序是稳定的,并保证n个日志(n)的性能。
PriorityQueue提供有序队列。priorityQueue和collections.sort()的区别在于priorityQueue始终维护一个订单队列,但只能从队列中获取head元素。您不能随机访问它的元素,如priorityqueue.get(4)。

如果集合中没有重复项,则TreeSet是另一个选择。与PriorityQueue相同,它始终维护有序集。你可以从树集中得到最低和最高的元素。但您仍然不能随机访问它的元素。

总之,collections.sort()提供了一个一次性的有序列表。PriorityQueue和Treeset始终维护有序的集合,而不需要对元素进行索引访问。

9.collections.emptylist()与新实例

同样的问题也适用于emptymap()和emptyset()。

两个方法都返回空列表,但collections.empty list()返回不可变的列表。这意味着您不能将新元素添加到“空”列表中。在后台,每次调用collections.empty list()实际上不会创建空列表的新实例。相反,它将重用现有的空实例。如果你对设计模式很熟悉,你应该知道我的意思。因此,如果经常打电话,这将给您带来更好的性能。

10 Collections.copy

有两种方法可以将源列表复制到目标列表。一种方法是使用arraylist构造函数

另一个是使用collections.copy()(如下所示)。注意第一行,我们分配的列表至少与源列表一样长,因为在集合的javadoc中,它表示目标列表必须至少与源列表一样长。

这两种方法都是肤浅的复制。那么这两种方法有什么区别呢?
首先,collections.copy()不会重新分配dstlist的容量,即使dstlist没有足够的空间来包含所有srcList元素。相反,它将抛出indexoutofboundsException。人们可能会质疑它是否有任何好处。一个原因是它保证了方法在线性时间内运行。另外,当您希望重用数组而不是在arraylist的构造函数中分配新内存时,它也非常适合。
collections.copy()只能接受list作为源和目标,而arraylist接受collection作为参数,因此更通用。 

 

最后,想学习Java的小伙伴们!

关注下方速学java公众号就可以拿到一份我为大家准备的Java学习资料!

对Java感兴趣的小伙伴也可以加 小编V❤: suxuejava

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值