很多时候我们截取字符串用的是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方法之后,就不要对原来的列表进行任何操作了, //否则在对新列表操作时就会出现并发修改异常,这也和这个性质有关 } }