Fork me on GitHub

需要注意的subList方法!和substring是不一样的!从源码解释他们的不同。

很多时候我们截取字符串用的是substring方法,很自然用着,但是对于列表的截取时很多时候就用得很少,但是其实他们是很不一样的,具体哪里不一样呢?

package main;

import java.util.ArrayList;
import java.util.List;

/**
 * @author XX
 *
 */
public class Test {

    public static void main(String[] args) {
        //先来一个字符串
        String abcd = "abcd";
        //删除字符串前面两个字符
        String cd = abcd.substring(2);
        //true
        System.out.println(cd.equals(cd));
        //false
        System.out.println(abcd.equals(cd));
        
        //下面的源码很容易解释这个问题,造成这个结果的原因是,生成了一个新的字符串,所以不一样,很正常也容易理解
        
        /*public String substring(int beginIndex) {
            if (beginIndex < 0) {
              throw new StringIndexOutOfBoundsException(beginIndex);
            }
            int subLen = value.length - beginIndex;
            if (subLen < 0) {
               throw new StringIndexOutOfBoundsException(subLen);
            }
                return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
        }*/
        
        
        List<Integer> list = new ArrayList<Integer>();
        list.add(3);
        list.add(2);
        list.add(2);
        list.add(4);
        list.add(1);
        list.add(5);
        
        List<Integer> list2  = list.subList(0, list.size());
        list2.add(2);
        //true?为什么list截取之后再加元素还是true呢?
        System.out.println(list.equals(list2));
        //如果不明白的话,打印个原来列表的size就明白了,结果是7,原来只有6个元素哦
        System.out.println(list.size());
        
        
        
        //然后我们再看看源码是怎么样的
        /*
         * public List<E> subList(int fromIndex, int toIndex) 
         * {
         *     subListRangeCheck(fromIndex, toIndex, size);
         *    return new SubList(this, 0, fromIndex, toIndex);
         * }
         * 
         * 首先是进入这个方法,是List中的subList中ArrayList实现的那个方法
         * subListRangeCheck这个我们不管,看命名就知道是判断能不能sub
         * 直接进下一个方法,别看到new就着急,往里面看看
         * private class SubList extends AbstractList<E> implements RandomAccess {
                private final AbstractList<E> parent;
                private final int parentOffset;
                private final int offset;
                int size;
        
                SubList(AbstractList<E> parent,
                        int offset, int fromIndex, int toIndex) {
                    this.parent = parent;
                    this.parentOffset = fromIndex;
                    this.offset = offset + fromIndex;
                    this.size = toIndex - fromIndex;
                    this.modCount = ArrayList.this.modCount;
                }
        
                public E set(int index, E e) {
                    rangeCheck(index);
                    checkForComodification();
                    E oldValue = ArrayList.this.elementData(offset + index);
                    ArrayList.this.elementData[offset + index] = e;
                    return oldValue;
                }
        
                public E get(int index) {
                    rangeCheck(index);
                    checkForComodification();
                    return ArrayList.this.elementData(offset + index);
                }
        
                public int size() {
                    checkForComodification();
                    return this.size;
                }
                
                
                。。。。。
                后面的方法省略了
                
                这里我们就可以看到,其实在这里的操作,都是this. = 
                这就表示所有的操作都是在原来的列表上面操作的。
                
                简单的说,subList方法只是返回了一个原来列表的视图而已
         * 
         * */
        
        
        //利用这个性质可以实现删除列表中任何位置的连续的一段值,代码如下
        list.subList(0, 2).clear();
        //执行上面这句之后,列表就变成了[2, 4, 1, 5, 2],删除了前面两个数,列表的大小也变成了5
        System.out.println(list.size());
        
        //需要提醒的是,一旦用过subList方法之后,就不要对原来的列表进行任何操作了,
        //否则在对新列表操作时就会出现并发修改异常,这也和这个性质有关
        
    }
}
posted @ 2016-07-27 10:33  LinkinStar  阅读(1396)  评论(0编辑  收藏  举报