List: 是一个接口,定义了一组元素是有序的、可重复的集合。
List的实现类:ArrayList
1.特点:
a.动态的增加和减少元素
b.实现了Collection和List接口
c.灵活的设置数组的大小
d.多用于查询
2.构造方法
a.ArrayList()
构造容量为10的空列表
b.ArrayList(Collection<? extends E> c)
构造一个包含指定集合的元素的列表,按照它们由集合的迭代器返回的顺序
c.ArrayList(int initialCapacity)
构造具有指定初始容量的空列表
3.常用方法
boolean add(E e) 将指定的元素追加到此列表末尾
void add(int index,E e) 将指定的元素插入到指定位置
boolean addAll(Collection<? extends E> c) 按指定集合的Iterator返回的顺序将指定集合中的所有元素追加到此列表的末尾
void clear() 从列表中删除所有元素
Object clone() 返回此ArrayList实例的拷贝
boolean contains(Object o) 如果此表含有此元素则返回true
E get(int index) 返回此列表中指定位置的元素
int indexof(Object o) 返回此列表中指定元素的第一次出现的索引,如果此列表不包含元素,则返回-1
int size() 返回此列表中的元素数
E set(int index,E element) 用指定的元素替换此列表中指定位置的元素。
3.遍历方式
a.for循环
for(int i=0;i<size;i++)
需要知道集合或数组的大小,而且需要是有序的,不然无法遍历
b.foreach循环
for(Integer integer:list)
可用于遍历任何集合或数组,而且操作简单易懂,他唯一的不好就是需要了解集合内部类型
c.Iterator迭代器
for(Iterator iterator = list.iterator(); iterator.hasNext; )
{
value = Iterator.next();
}
当我们需要遍历不同的集合时,我们只需要传递集合的iterator(如arr.iterator())看懂了吧,这就是iterator的好处,
他不包含任何有关他所遍历的序列的类型信息,能够将遍历序列的操作与序列底层的结构分离。
迭代器统一了对容器的访问方式。这也是接口的解耦的最好体现。
它可以随时修改或者删除集合内部的元素,并且是在不需要知道元素和集合的类型的情况下进行的(原因可参考第三点:多态差别),
当你需要对不同的容器实现同样的遍历方式时,迭代器是最好的选择!
分享一下在网上看到的一些关于ArrayList的几道面试题
1、ArrayList的大小是如何自动增加的?你能分享一下你的代码吗?
如果没看过源码的,应该是不知道怎么回答,果断去把源码再熟悉了一遍。当要新增一个
元素的时候,java每次都会去检查容量够不够,如果不够的话,就会新建一个容量更大的数组,
旧的数组就会使用Arrays.copyOf方法被复制到新的数组中去,现有的数组引用指向了新的数组,
看段源码
//ArrayList Add方法:
public boolean add(E e){
ensureCapacity(size+1); //确保对象数组elementData有足够的容量,可以将新加入的元素e加进去
elementData[size++] = e; //加入新元素e,size加1
return true;
}
//ensureCapacity方法:处理ArrayList的大小
public void ensureCapacity(int minCapacity) {
modCount++;
int oldCapacity = elementData.length;//获取数组大小(即数组的容量)
//当数组满了,又有新元素加入的时候,执行扩容逻辑
if (minCapacity > oldCapacity) {
Object oldData[] = elementData;
int newCapacity = (oldCapacity * 3)/2 + 1; //新容量为旧容量的1.5倍+1
if (newCapacity < minCapacity) //如果扩容后的新容量还是没有传入的所需的最小容量大或等于(主要发生在addAll(Collection<? extends E> c)中)
newCapacity = minCapacity; //新容量设为最小容量
elementData = Arrays.copyOf(elementData, newCapacity); //复制新容量
}
}
2、当传递ArrayList到某个方法中,或者某个方法返回ArrayList,什么时候要考虑安全隐患?
如何修复安全违规这个问题呢?
当array被当做参数传递到某个方法中,如果array在没有被复制的情况下直接被分配给了成员变量,那么就可能发生这种情况,即当原始的数组被调用的方法改变的时候,
传递到这个方法中的数组也会改变。下面的这段代码展示的就是安全违规以及如何修复这个问题。
ArrayList被直接赋给成员变量——安全隐患:
public void setMyArray(String[] myArray)
{
this.myArray = myArray;
}
修复这个安全隐患:
public void setMyArray(String[] myArray)
{
if(newMyArray == null)
{
this.myArray = new String[0];
}
else
{
this.myArray = Arrays.copyof(myArray,myArray.length):
}
}
3、如何复制某个ArrayList到另一个ArrayList中去?写出你的代码?
下面就是把某个ArrayList复制到另一个ArrayList中去的几种技术:
1.使用clone()方法,比如ArrayList newArray = oldArray.clone(); 经过测试这种方法最快
2.使用ArrayList构造方法,比如:ArrayList myObject = new ArrayList(myTempObject); 这个其次
3.使用Collection的copy方法。 这个最慢