1.何时在ArrayList上使用LinkedList?
ArrayList本质上是一个数组。它的元素可以通过索引直接访问。但是,如果数组已满,则需要一个更大的新数组来分配,并将所有元素移动到新数组将花费O(n)时间。另外,添加或删除元素都需要移动数组中的现有元素。这可能是使用ArrayList的最大缺点。
LinkedList是一个双链表。因此,要访问中间的元素,必须从列表的开头进行搜索。而另一方面,在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.集合如何在遍历时删除元素
这个不用我说,各位面试应该都经历过吧,在遍历修改集合的唯一正确方法是使用 Iterator.remove()
。 例如:
Iterator<Integer> itr = list.iterator();
while(itr.hasNext()) {
// do something
itr.remove();
}
有时候我们很容易写出下面的错误代码
第一种:
for(Integer i: list) { list.remove(i);}
如果你运行了此代码的话,则会抛出一个java.util.ConcurrentModificationException
异常,在Java中,“通常不允许一个线程修改集合,而另一个线程在其上进行迭代。”
第二种:
for (int i = 0; i < list.size(); i++) { list.remove(list.get(i));}
如果你运行了此代码的话,确实不会报错,但是你总是得不到你想要的结果。
3.如何将int[]转换为List?
是不是很简单
List<int> list = Arrays.asList(array);或List<Integer> list = Arrays.asList(array);
这样你确定你的编译器不报错?O(∩_∩)O哈哈~ 正确的做法是有两种,第一种引入 Apache Commons Lang包
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.11</version></dependency>
List<Integer> list = Arrays.asList(ArrayUtils.toObject(array));
另一种就是循环遍历喽
int[] array = {1,2,3,4,5};List<Integer> list = new ArrayList<Integer>();for(int i: array) { list.add(i);}
4.如何从ArrayList中删除重复的元素?
遇到这个问题,有的同学会想到遍历,但是为什么不想想其它的方法呢,比如Set
就是不重复的啊,我们把元素直接放到Set
里面过滤一遍,再放回去不就好了。
ArrayList** list = ... // initial a list with duplicate elementsSet<Integer> set = new HashSet<Integer>(list);list.clear();list.addAll(set);
5.Collections.emptyList()你用过吗?它的作用是干嘛的?
首先我们先来说说Collections.emptyList()
,我们看源码
@SuppressWarnings("rawtypes")public static final List EMPTY_LIST = new EmptyList<>();@SuppressWarnings("unchecked")public static final <T> List<T> emptyList() { return (List<T>) EMPTY_LIST;}
可知它一个不可变的列表。并且,每次调用不会创建一个空列表的新实例。如果您对设计模式熟悉的Singleton,您应该知道我的意思。因此,如果经常调用,这将为您提供更好的性能。
那我们要他有什么用呢?
比如说一个方法返回一个List,当没有任何结果的时候,返回null,有结果的时候,返回列表。那样的话,调用端就需要进行null判断,使用emptyList这样的方法,可以方便方法调用者。你可能说直接返回new ArrayList()
或者 new LinkedList()
,但是在创建他们的时候会有初始大小,多少会占用一内存。