ArrayList 本是 java中的代码,放到android这边显得不太合适,但由于它在android开发中又大量应用,所以就放到这里,供大家学习。
相信大家对ArrayList不陌生,但要说到细节的方面,可能就有点含糊其辞了。下面就来说几个日常使用中的几个例子:
1、判断ArrayList是否有值:
if (mList.size() != 0){
// do something
}
上面这个写法,是最常见的。但你知道吗,ArrayList中其实是有个isEmpty()方法的,源码如下:
public boolean isEmpty() {
return size == 0;
}
所以,判断ArrayList是否有值的写法应改为:
if (!mList.isEmpty()){
// do something
}
补充一点:最好再增加一个mList是否为空的判断,让代码的严谨性更好。
2、ArrayList 的add(E e)方法,可以传入null的值吗?
看了下面它的源码,就有答案了:
public boolean add(E e) {
ensureCapacity(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
所以,答案是肯定的,可以传入null。
补充一点:虽然ArrayList 是可以传入null的,但在实际应用中,这么做没有什么意义。所以,在调用add方法前,最好还是判断一下传入的值是否为空。
3、ArrayList的get(int index)方法,会返回null吗?
看一下它的源码:
public E get(int index) {
RangeCheck(index);
return (E) elementData[index];
}
这个的回答,还要看代码是如何写的。如果之前add的时候添加了null进去,那么这里就会有可能返回null。
很多人会这样写代码:
for (int i = 0; i < mList.size(); i++) {
mList.get(i).xxx();
}
如果能确定ArrayList中确实没有null值的话,这么写没问题。但如果确定不了的话,还是增加一个是否为空的判断吧,避免空指针异常。
4、ArrayList的remove(Object o)方法,出入null时,会空指针异常吗?
实际应用当中,我相信没人会直接传个null进去。多数应用场景是,获取了一个对象,在不知道其是否为null的情况下,想要移除掉它。
看一下它的源码:
public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
所以,传入为null的值的话,如果我们之前调用add方法时,传入过null值,那么这里就会移除掉它。
5、ArrayList的remove(Object o)方法传入未添加的值,会报异常吗?
如果我们传入的值,之前没有add过,也只是返回false,并不会报什么异常。原因就在上面那段代码里。
而在实际代码中,有些人在调用remove方法时,会这么写:
if(mList.contain(object)){
mList.remove(object);
}
所以,这么看来,remove方法前再调用contain,就没什么意义了。我们可以通过判断其返回值,来获得其是否有这个值,也就是是否删除成功。
6、ArrayList可以重复添加相同的值吗?
这个问题其实比较基础了,但实际写代码中,还会有很多人在这块犯错误,认为相同对象只能添加一次。
这里直接给出答案:相同的对象是可以重复添加进去的。原因可以从上面add方法了解到。
补充一点:可以添加多个相同对象,但remove的时候,可不会一次全部都删掉,而是按添加顺序删除。调一次,删除一个!这一点,初学java的同学要特别注意了!
7、ArrayList中的Object[ ] toArray() 与 <T> T[ ] toArray(T[ ] a) 方法
在实际应用场景中,会需要将ArrayList转换成数组的形式。我见过有些人会用for循环的方法,一个个将ArrayList取出来,再赋值给数组的。没那么麻烦,用toArray这个方法即可。但ArrayList会有两个同名方法,该用哪一个呢?还是先看源码吧:
public Object[] toArray() {
return Arrays.copyOf(elementData, size);
}
public <T> T[] toArray(T[] a) {
if (a.length < size)
// Make a new array of a's runtime type, but my contents:
return (T[]) Arrays.copyOf(elementData, size, a.getClass());
System.arraycopy(elementData, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}
直接调用toArray()这个方法,会直接返回一个数组,源码是返回Object类型的。所以,你需要自己手动泛型一下。
说起这个泛型,还真得唠叨一句,不知道有多少人会这么写:
ArrayList<String> mList = new ArrayList<String>();
......
String[] s = (String[]) mList.toArray();
如果有哪位同学这么写运行不报错的话,给我留个言。
继续。下面那个toArray(T[] a),就显得稍微复杂了一些。如果T[]的大小比ArrayList要小的话,则只会返回与T[]大小相等的数组。
注意,如果传入的数组与ArrayList的大小不相等,则会将ArrayList的size那位赋值为null。
这里给个最简单的测试例子:
ArrayList<String> mList = new ArrayList<String>();
mList.add("a");
mList.add("b");
String[] s = new String[4];
s[2] = "c";
s[3] = "d";
for (String string: s) {
System.out.println(string);
}
s = mList.toArray(s);
for (String string : s) {
System.out.println(string);
}
第一个for循环输出内容为:
null
null
c
d
因为我没有对String数组第一个和第二个赋值,所以自然为输出内容为null。
第二个for循环输出内容为:
a
b
null
d
可以看到,String数组的第三个值被赋值为null。
所以,在使用toArray(T[] a)要特别留心这个问题。当然,如果对第一个toArray()使用觉得麻烦的话,可以创建一个与ArrayList大小一样的数组,调用toArray(T[] a)传参进去,就可以直接得到了:
ArrayList<String> mList = new ArrayList<String>();
......
String[] s = new String[mList.size()];
s = mList.toArray(s);
以上,就是总结了ArrayList在实际使用中的一些细节知识点,希望对大家能有所帮助。