`
444878909
  • 浏览: 638113 次
文章分类
社区版块
存档分类
最新评论

Android编程之ArrayList源码详解及使用

 
阅读更多

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在实际使用中的一些细节知识点,希望对大家能有所帮助。




分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics