引言:
今天主要分析一下Java 8版本中java.util.ArrayList集合类有何变化。
变化:
1.上层collection接口变化
//1.8新增方法:提供了接口默认实现,返回分片迭代器
@Override
default Spliterator<E> spliterator() {
return Spliterators.spliterator(this, 0);
}
//1.8新增方法:提供了接口默认实现,返回串行流对象
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
//1.8新增方法:提供了接口默认实现,返回并行流对象
default Stream<E> parallelStream() {
return StreamSupport.stream(spliterator(), true);
}
/**
* Removes all of the elements of this collection that satisfy the given
* predicate. Errors or runtime exceptions thrown during iteration or by
* the predicate are relayed to the caller.
* 1.8新增方法:提供了接口默认实现,移除集合内所有匹配规则的元素,支持Lambda表达式
*/
default boolean removeIf(Predicate<? super E> filter) {
//空指针校验
Objects.requireNonNull(filter);
//注意:JDK官方推荐的遍历方式还是Iterator,虽然forEach是直接用for循环
boolean removed = false;
final Iterator<E> each = iterator();
while (each.hasNext()) {
if (filter.test(each.next())) {
each.remove();//移除元素必须选用Iterator.remove()方法
removed = true;//一旦有一个移除成功,就返回true
}
}
//这里补充一下:由于一旦出现移除失败将抛出异常,因此返回false指的仅仅是没有匹配到任何元素而不是运行异常
return removed;
}
}
public interface Iterable<T>{
.....
//1.8新增方法:提供了接口默认实现,用于遍历集合
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
//1.8新增方法:提供了接口默认实现,返回分片迭代器
default Spliterator<T> spliterator() {
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
}
public interface List<E> extends Collection<E> {
//1.8新增方法:提供了接口默认实现,用于对集合进行排序,主要是方便Lambda表达式
default void sort(Comparator<? super E> c) {
Object[] a = this.toArray();
Arrays.sort(a, (Comparator) c);
ListIterator<E> i = this.listIterator();
for (Object e : a) {
i.next();
i.set((E) e);
}
}
//1.8新增方法:提供了接口默认实现,支持批量删除,主要是方便Lambda表达式
default void replaceAll(UnaryOperator<E> operator) {
Objects.requireNonNull(operator);
final ListIterator<E> li = this.listIterator();
while (li.hasNext()) {
li.set(operator.apply(li.next()));
}
}
/**
* 1.8新增方法:返回ListIterator实例对象
* 1.8专门为List提供了专门的ListIterator,相比于Iterator主要有以下增强:
* 1.ListIterator新增hasPrevious()和previous()方法,从而可以实现逆向遍历
* 2.ListIterator新增nextIndex()和previousIndex()方法,增强了其索引定位的能力
* 3.ListIterator新增set()方法,可以实现对象的修改
* 4.ListIterator新增add()方法,可以向List中添加对象
*/
ListIterator<E> listIterator();
}
2.构造方法变化
/**
* Constructs an empty list with an initial capacity of ten.
* 1.8版的默认构造器,只会初始化一个空数组
*/
public ArrayList() {
super();
this.elementData = EMPTY_ELEMENTDATA;//初始化一个空数组
}
/**
* Constructs an empty list with an initial capacity of ten.
* 1.7版的默认构造器,会直接初始化一个10容量的数组
*/
public ArrayList() {
this(10);
}
构造方法最大的改变就是变成懒加载了,当你调用add方法的时候才会真正分配数组的内存。
3.增加foreach
/**
* Performs the given action for each element of the {@code Iterable}
* until all elements have been processed or the action throws an
* exception. Unless otherwise specified by the implementing class,
* actions are performed in the order of iteration (if an iteration order
* is specified). Exceptions thrown by the action are relayed to the
* caller.
* 1.8新增方法,重写Iterable接口的forEach方法
* 提供对数组的遍历操作,由于支持Consumer因此在遍历时将执行传入的方法
*/
@Override
public void forEach(Consumer<? super E> action) {
Objects.requireNonNull(action);
final int expectedModCount = modCount;
@SuppressWarnings("unchecked")
final E[] elementData = (E[]) this.elementData;
final int size = this.size;
for (int i=0; modCount == expectedModCount && i < size; i++) {
action.accept(elementData[i]);//执行传入的自定义方法
}
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}
4.增加removeIf
/**
* Removes all of the elements of this collection that satisfy the given
* predicate. Errors or runtime exceptions thrown during iteration or by
* the predicate are relayed to the caller.
* 1.8新增方法,重写Collection接口的removeIf方法
* 移除集合内所有复合匹配条件的元素,迭代时报错会抛出异常 或 把断言传递给调用者(即断言中断)
* 该方法主要干了两件事情:
* 1.根据匹配规则找到所有符合要求的元素
* 2.移除元素并转移剩余元素位置
* 补充:为了安全和快速,removeIf分成两步走,而不是直接找到就执行删除和转移操作,写法值得借鉴
*/
@Override
public boolean removeIf(Predicate<? super E> filter) {
Objects.requireNonNull(filter);
// figure out which elements are to be removed any exception thrown from
// the filter predicate at this stage will leave the collection unmodified
int removeCount = 0;
//BitSet用于按位存储,这里用作存储待移除元素(即符合匹配规则的元素)
//BitSet能够通过位图算法大幅减少数据占用存储空间和内存,尤其适合在海量数据方面,这里是个很明显的优化
//有机会会在基础番中解析一下BitSet的奇妙之处
final BitSet removeSet = new BitSet(size);
final int expectedModCount = modCount;
final int size = this.size;
//每次循环都要判断modCount == expectedModCount!
for (int i=0; modCount == expectedModCount && i < size; i++) {
@SuppressWarnings("unchecked")
final E element = (E) elementData[i];
if (filter.test(element)) {
removeSet.set(i);
removeCount++;
}
}
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
// shift surviving elements left over the spaces left by removed elements
// 当有元素被移除,需要对剩余元素进行位移
final boolean anyToRemove = removeCount > 0;
if (anyToRemove) {
final int newSize = size - removeCount;
for (int i=0, j=0; (i < size) && (j < newSize); i++, j++) {
i = removeSet.nextClearBit(i);
elementData[j] = elementData[i];
}
for (int k=newSize; k < size; k++) {
elementData[k] = null; // Let gc do its work
}
this.size = newSize;
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
modCount++;
}
//正常情况下,一旦匹配到元素,应该删除成功,否则将抛出异常,当没有匹配到任何元素时,返回false
return anyToRemove;
}
5.增加removeAll
/**
* Replaces each element of this list with the result of applying the operator to that element.
* Errors or runtime exceptions thrown by the operator are relayed to the caller.
* 1.8新增方法,重写List接口的replaceAll方法
* 提供支持一元操作的批量替换功能
*/
@Override
@SuppressWarnings("unchecked")
public void replaceAll(UnaryOperator<E> operator) {
Objects.requireNonNull(operator);
final int expectedModCount = modCount;
final int size = this.size;
for (int i=0; modCount == expectedModCount && i < size; i++) {
elementData[i] = operator.apply((E) elementData[i]);
}
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
modCount++;
}
6.增加sort
/**
* Sorts this list according to the order induced by the specified
* 1.8新增方法,重写List接口的sort方法
* 支持对数组进行排序,主要方便于Lambda表达式
*/
@Override
@SuppressWarnings("unchecked")
public void sort(Comparator<? super E> c) {
final int expectedModCount = modCount;
//Arrays.sort底层是结合归并排序和插入排序的混合排序算法,有不错的性能
//有机会在基础番对Timsort(1.8版)和ComparableTimSort(1.7版)进行解析
Arrays.sort((E[]) elementData, 0, size, c);
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
modCount++;
}
网友评论