Java集合的十大问题总结

1.何时在ArrayList上使用LinkedList?

ArrayList本质上是一个数组。它的元素可以通过索引直接访问。但是,如果数组已满,则需要一个更大的新数组来分配,并将所有元素移动到新数组将花费O(n)时间。另外,添加或删除元素都需要移动数组中的现有元素。这可能是使用ArrayList的最大缺点。
LinkedList是一个双链表。因此,要访问中间的元素,必须从列表的开头进行搜索。另一方面,在LinkedList中添加和删除元素的速度更快,因为它仅在本地更改列表。
总而言之,时间复杂度比较的最坏情况如下:

| Arraylist | LinkedList

get(index) | O(1) | O(n)
add(E) | O(n) | O(1)
add(E, index) | O(n) | O(n)
remove(index) | O(n) | O(n)
Iterator.remove() | O(n) | O(1)
Iterator.add(E) | O(n) | O(1)
尽管运行时间很长,但对于大型列表,也应该考虑内存使用情况。在LinkedList中,每个节点至少需要两个额外的指针才能链接上一个节点和下一个节点。而在ArrayList中,仅需要一个元素数组。

2.有效的等效项,用于在迭代Collection时删除元素

迭代时修改集合的唯一正确方法是使用Iterator。remove()。例如,
Iterator itr = list.iterator();while(itr.hasNext()) {
// do something
itr.remove();}
一种最常见的错误代码是
for(Integer i: list) {
list.remove(i);}

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

最简单的方法可能会使用ArrayUtils在Apache Commons库。
int[] array = ArrayUtils.toPrimitive(list.toArray(new Integer[0]));
在JDK中,没有捷径。请注意,您不能使用List。toArray(),因为它将转换List到Integer []。正确的方法是,
int[] array = new int[list.size()];for(int i=0; i < list.size(); i++) {
array[i] = list.get(i);}

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

最简单的方法可能仍然是使用ArrayUtils在Apache Commons库,如下所示。
List list = Arrays.asList(ArrayUtils.toObject(array));
在JDK中,也没有捷径。
int[] array = {1,2,3,4,5};
List list = new ArrayList();for(int i: array) {
list.add(i);}

5.过滤集合的最佳方法是什么?

同样,您可以使用第三方软件包(例如Guava或Apache Commons Lang)来完成此功能。两者都提供一个过滤器()方法(在Collections2番石榴和CollectionUtils的Apache)。所述过滤器()方法将返回匹配给定的元素谓词。
在JDK中,事情变得更加困难。一个好消息是,在Java 8中,将添加谓词。但是现在,您必须使用Iterator遍历整个集合。
Iterator itr = list.iterator();while(itr.hasNext()) {
int i = itr.next();
if (i > 5) { // filter all ints bigger than 5
itr.remove();
}}
当然,您可以通过引入新的接口Predicate来模仿Guava和Apache所做的事情。大多数高级开发人员也可能会这样做。
public interface Predicate {
boolean test(T o);}
public static void filter(Collection collection, Predicate predicate) {
if ((collection != null) && (predicate != null)) {
Iterator itr = collection.iterator();
while(itr.hasNext()) {
T obj = itr.next();
if (!predicate.test(obj)) {
itr.remove();
}
}
}}
然后,我们可以使用以下代码来过滤集合:
filter(list, new Predicate() {
public boolean test(Integer i) {
return i <= 5;
}});

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

有两种方法,具体取决于您要如何定义相等。第一部分代码将列表放入HashSet中。然后主要通过hashCode()来识别重复项。在大多数情况下,它将起作用。但是,如果需要指定比较方式,则最好使用第二段代码来定义自己的比较器。
Set set = new HashSet(list);
Set set = new TreeSet(aComparator);
set.addAll(list);

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

这个问题与上面的问题很相关。
如果您不在乎ArrayList中元素的顺序,那么聪明的方法是将列表放入集合中以删除重复项,然后将其移回列表。这是代码
ArrayList** list = … // initial a list with duplicate elements
Set set = new HashSet(list);
list.clear();
list.addAll(set);
如果您确实关心订单,可以通过将列表放入标准JDK中的LinkedHashSet中来保留订单。

8.排序的集合

有两种方法可以维护Java中的排序集合。它们全部以自然顺序或由指定的比较器提供集合。通过自然排序,还需要在元素中实现Comparable接口。
1.集合。sort()可以对 List进行排序。如javadoc中指定的那样,这种排序是稳定的,并保证 n log(n)性能。
2.PriorityQueue提供有序队列。PriorityQueue和 Collections之间的区别。sort()是, PriorityQueue始终保持订单队列,但是您只能从队列中获取head元素。您不能随机访问其元素,例如 PriorityQueue。get(4)。
3.如果集合中没有重复项,则TreeSet是另一种选择。与PriorityQueue相同,它始终保持有序集。您可以从TreeSet中获取最低和最高元素。但是您仍然不能随机访问其元素。
简而言之,Collections。sort()提供了一个一次性的有序列表。PriorityQueue和TreeSet始终保持有序集合,以不对元素进行索引访问为代价。

9.收藏,emptyList()与新实例

相同的问题适用于emptyMap()和emptySet()。
这两个方法都返回一个空列表,但是返回Collections。emptyList()返回一个不可变的列表。这意味着您不能将新元素添加到“ 空 ”列表中。在后台,每次调用Collections。emptyList()实际上不会创建一个空列表的新实例。相反,它将重用现有的空实例。如果您对设计模式熟悉的Singleton,您应该知道我的意思。因此,如果经常调用,这将为您提供更好的性能。

10收藏,复制

有两种方法可以将源列表复制到目标列表。一种方法是使用ArrayList构造函数
ArrayList < Integer > dstList = new ArrayList < Integer > ( srcList );
另一种是使用Collections。copy()(如下所示)。注意第一行,我们分配的列表至少与源列表一样长,因为在Collections的javadoc中,它说目标列表必须至少与源列表一样长。
ArrayList dstList = new ArrayList(srcList.size());Collections.copy(dstList, srcList);

最后,开发这么多年我也总结了一套学习Java的资料与面试题,如果你在技术上面想提升自己的话,可以关注我,私信发送领取资料或者在评论区留下自己的联系方式,有时间记得帮我点下转发让跟多的人看到哦。Java集合的十大问题总结