Java中ArrayList相关的5道面试题
本文参考了 《关于ArrayList的5道面试题 》
1、ArrayList的大小是如何自动增加的?
这个问题我想曾经debug过并且查看过arraylist源码的人都有印象,它的过程是:当试图在一个arraylist中增加一个对象时,Java会去检查arraylist,确保已存在的数组中有足够的容量(默认是10),如果没有足够的容量,那么就会新建一个长度更长(是原来数组长度的1.5倍)的数组,旧的数组就会使用Arrays.copyOf()方法被复制到新的数组中。
来看源代码:
/**
* Appends the specified element to the end of this list.
*
* @param e element to be appended to this list
* @return <tt>true</tt> (as specified by {@link Collection#add})
*/
public boolean add(E e) {
ensureCapacity(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
} /**
* Increases the capacity of this <tt>ArrayList</tt> instance, if
* necessary, to ensure that it can hold at least the number of elements
* specified by the minimum capacity argument.
*
* @param minCapacity the desired minimum capacity
*/
public void ensureCapacity(int minCapacity) {
modCount++;
int oldCapacity = elementData.length;
if (minCapacity > oldCapacity) {
Object oldData[] = elementData;
int newCapacity = (oldCapacity * 3)/2 + 1;
if (newCapacity < minCapacity)
newCapacity = minCapacity;
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
}
2、什么情况下使用ArrayList,什么情况下使用LinkedList?
首先来看LinkedList是什么:
private transient Entry<E> header = new Entry<E>(null, null, null);
private transient int size = 0; /**
* Constructs an empty list.
*/
public LinkedList() {
header.next = header.previous = header;
}
没错,它就是一个链表,每一个节点都是Entry,而ArrayList是一个数组,初始化的大小是10:
public ArrayList(int initialCapacity) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
} /**
* Constructs an empty list with an initial capacity of ten.
*/
public ArrayList() {
this(10);
}
好,搞清楚这个之后,我们可以知道:①、对于数组的访问,即使是最糟糕的情况下,时间复杂度也是O(1),而对于链表来说,最糟糕的情况下,时间复杂度是O(N)。②、对于数组来说,当旧容量无法容下新增对象时,会将就的数组复制到一个新的数组里面,这里需要消耗时间,也就是说增加一个对象可能会耗时比较久,而对于链表来说,新增一个对象只是初始化一个entry,然后将其插入到链表表尾,耗时并不会太长。
看LinkedList的add方法:
public boolean add(E e) {
addBefore(e, header);
return true;
} private Entry<E> addBefore(E e, Entry<E> entry) {
Entry<E> newEntry = new Entry<E>(e, entry, entry.previous);
newEntry.previous.next = newEntry;
newEntry.next.previous = newEntry;
size++;
modCount++;
return newEntry;
}
所以,引用原文的话:多数情况下,当你遇到访问元素比插入或者是删除元素更加频繁的时候,你应该使用ArrayList。另外一方面,当你在某个特别的索引中,插入或者是删除元素更加频繁,或者你压根就不需要访问元素的时候,你会选择LinkedList。
3、当传递一个ArrayList到某个方法,或者某个方法返回ArrayList,什么时候要考虑安全隐患?如何修复这个安全违规问题?
当array被当做参数传递到某个方法中,如果array在没有被复制的情况下直接被分配给了成员变量,那么就可能发生这种情况,即当原始的数组被调用的方法改变的时候,传递到这个方法中的数组也会改变。
来看例子:
public class Array {
String []myArray = {};
public void SetMyArray(String []myArray){
this.myArray = myArray;//这里有安全隐患
} public String[] getMyArray(){
return this.myArray;//这里有安全隐患
} public static void main(String []args){
Array a = new Array();
String b[] = {"i "," am ","from ","china"};
a.SetMyArray(b);
System.out.println(a.getMyArray()[0]); b[0]="you";
System.out.println(a.getMyArray()[0]);
}
}
输出结果:
i
you
很明显,我们只修改了b[0],但是却影响到a[0](假设我们的目的是修改b并不会影响a),既然出现这个问题,那么我们对set方法做一次改进:
public void SetMyArray(String []myArray){//修改后的set方法
if(myArray == null){
this.myArray = new String[0];
}else{
this.myArray = Arrays.copyOf(myArray, myArray.length);
}
}
此时的运行结果:
i
i
所以此时的b和a都是分开的,互不影响的。
4、如何复制某个ArrayList到另一个Arraylist中去?用原文的话来说:
- 使用clone()方法,比如ArrayList newArray = oldArray.clone();
- 使用ArrayList构造方法,比如:ArrayList myObject = new ArrayList(myTempObject);
- 使用Collection的copy方法。
注意1和2是浅拷贝(shallow copy)。
关于浅拷贝,深拷贝,参考这篇文章。
5、在索引中ArrayList的增加或者删除某个对象的运行过程?效率很低吗?解释一下为什么?
在ArrayList中增加或者是删除元素,要调用System.arraycopy这种效率很低的操作,如果遇到了需要频繁插入或者是删除的时候,你可以选择其他的Java集合,比如LinkedList。看一下下面的代码:
在某个索引处增加一个元素:
public void add(int index, E element) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException(
"Index: "+index+", Size: "+size); ensureCapacity(size+1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
在某个索引处删除某个元素:
public E remove(int index) {
RangeCheck(index); modCount++;
E oldValue = (E) elementData[index]; int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // Let gc do its work return oldValue;
}
Java中ArrayList相关的5道面试题的更多相关文章
- Java中最常见的十道面试题
第一,谈谈final, finally, finalize的区别. final?修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承.因此一个类不能既被声明为 ...
- Java中创建String的两道面试题及详解
我们知道创建一个String类型的变量一般有以下两种方法: String str1 = "abcd"; String str2 = new String("abcd&qu ...
- java中ArrayList 、LinkList区别
转自:http://blog.csdn.net/wuchuanpingstone/article/details/6678653 个人建议:以下这篇文章,是从例子说明的方式,解释ArrayList.L ...
- JAVA中ArrayList用法
JAVA中ArrayList用法 2011-07-20 15:02:03| 分类: 计算机专业 | 标签:java arraylist用法 |举报|字号 订阅 Java学习过程中做题时 ...
- 【Socket编程】Java中网络相关API的应用
Java中网络相关API的应用 一.InetAddress类 InetAddress类用于标识网络上的硬件资源,表示互联网协议(IP)地址. InetAddress类没有构造方法,所以不能直接new出 ...
- Java中ArrayList与LinkedList的区别
Java中ArrayList与LinkedList的区别 一般大家都知道ArrayList和LinkedList的区别: 1. ArrayList的实现是基于数组,LinkedList的实现是基于双向 ...
- Java中arraylist和linkedlist源代码分析与性能比較
Java中arraylist和linkedlist源代码分析与性能比較 1,简单介绍 在java开发中比較经常使用的数据结构是arraylist和linkedlist,本文主要从源代码角度分析arra ...
- java中ArrayList 和 LinkedList 有什么区别
转: java中ArrayList 和 LinkedList 有什么区别 ArrayList和LinkedList都实现了List接口,有以下的不同点:1.ArrayList是基于索引的数据接口,它的 ...
- 《Java面试全解析》1000道面试题大全详解(转)
<Java面试全解析>1000道 面试题大全详解 本人是 2009 年参加编程工作的,一路上在技术公司摸爬滚打,前几年一直在上海,待过的公司有 360 和游久游戏,因为自己家庭的原因,放弃 ...
随机推荐
- HTTP 请求未经客户端身份验证方案“Anonymous”授权。从服务器收到的身份验证标头为“Negotiate,NTLM”
转自:http://www.cnblogs.com/geqinggao/p/3270499.html 近来项目需要Web Service验证授权,一般有两种解决方案: 1.通过通过SOAP Heade ...
- Hibernate,Session清理缓存时间点
当应用程序调用org.hibernate.Transaction的commit()的时候,commit()方法先清理缓存,然后再向数据库提交事务. 当应用程序显示调用Session.flush()方法 ...
- node-webkit教程<>Native UI API 之Menu(菜单)
node-webkit教程(6)Native UI API 之Menu(菜单)1 前言... 2 6.1 Menu 概述... 3 6.2 menu api6 6.2.1 new Menu([o ...
- 完整学习git四git对象
1查看git对象 git cat-file 实践 git head到底指向的是什么 ➜ gittest git:(master) find .git -name HEAD -o -name maste ...
- 使用percona xtradb cluster的IST方式添加新节点
使用percona xtradb cluster的IST(Incremental State Transfer)特性添加新节点,防止新节点加入时使用SST(State SnapShop Transfe ...
- java面试每日一题10
题目:利用递归方法求5! public class Recursion { public static void main(String args[]) throws NumberFormatExce ...
- android基础小结
(注:此小结文档在全屏模式下观看效果最佳) 2016年3月1日,正式开始了我的android学习之路. 最最开始的,当然是学习怎样搭载环境了,然而苦逼的我在win10各种坑爹的指引下还是安装了一个星期 ...
- 关于匿名类无法转换为object
缘由,不能在Razor中使用匿名类, 先事先封装了一个方法,用于Razor给cshtml模板返回页面. 在ashx一般处理程序中,是这样调用的 匿名类的格式如下:(只看格式,不看具体内容) 调用这样 ...
- D类 E类地址
D类地址不分网络地址和主机地址,它的第1个字节的前四位固定为1110.⑵ D类地址范围:224.0.0.0到239.255.255.255D类地址用于多点播送.D类IP地址第一个字节以“lll0”开始 ...
- EFsql笔记
like的语法 string[] cities = { "London", "Madrid" }; IQueryable<Customer> cus ...