Java 集合体系与List

一、集合体系

1)Collection接口

在Java类库中,Collection是集合最基本的接口。Collection定义了一系列集合常用操作(获取迭代器、添加、删除、包含、转化数组、判断是否为空、大小)以及default默认方法接口 ( 大部分与流相关( 除removeIf,其用来删除满足符合某个条件的元素 ) )。AbstractCollection实现了部分Collection方法。

boolean add(E e)
//确保此集合包含指定的元素(可选操作)。

boolean addAll(Collection<? extends E> c)
//将指定集合中的所有元素添加到此集合(可选操作)。

void clear()
//从此集合中删除所有元素(可选操作)。

boolean contains(Object o)
//如果此集合包含指定的元素,则返回 true 。

boolean containsAll(Collection<?> c)
//如果此集合包含指定 集合中的所有元素,则返回true。

boolean equals(Object o)
//将指定的对象与此集合进行比较以获得相等性。

int hashCode()
//返回此集合的哈希码值。

boolean isEmpty()
//如果此集合不包含元素,则返回 true。

Iterator<E> iterator()
//返回此集合中的元素的迭代器。

default Stream<E> parallelStream()
//返回可能并行的 Stream与此集合作为其来源。

boolean remove(Object o)
//从该集合中删除指定元素的单个实例(如果存在)(可选操作)。

boolean removeAll(Collection<?> c)
//删除指定集合中包含的所有此集合的元素(可选操作)。

default boolean removeIf(Predicate<? super E> filter)
//删除满足给定谓词的此集合的所有元素。例:
  ArrayList<String> list = new ArrayList<>();
  list.add("张三");
  list.add("李四");
  list.add("王二");
  list.add("李麻子");
  list.add("李三");
  list.removeIf(obj->obj.contains("李"));

boolean retainAll(Collection<?> c)
//仅保留此集合中包含在指定集合中的元素(可选操作)。

int size()
//返回此集合中的元素数。

default Spliterator<E> spliterator()
//创建一个Spliterator在这个集合中的元素。

default Stream<E> stream()
//返回以此集合作为源的顺序 Stream 。

Object[] toArray()
//返回一个包含此集合中所有元素的数组。

<T> T[] toArray(T[] a)
//返回包含此集合中所有元素的数组; 返回的数组的运行时类型是指定数组的运行时类型。

2)Iterator接口

boolean hasNext()
//如果迭代具有更多的元素,则返回true 。 (换句话说,如果next()返回一个元素而不是抛出一个异常,则返回true )
//结果 true如果迭代有更多的元素

E next()
//返回迭代中的下一个元素。
//结果 迭代中的下一个元素
//异常 NoSuchElementException - 如果迭代没有更多的元素

default void remove()
//从底层集合中删除此迭代器返回的最后一个元素(可选操作)。 此方法只能调用一次next() 。 如果底层集合在迭代过程中以任何方式进行修改而不是通过调用此方法,则迭代器的行为是未指定的。
//实现要求: 默认的实现抛出的一个实例UnsupportedOperationException并执行其他操作。
//异常 UnsupportedOperationException -如果 remove操作不会被这个迭代器支持
//     IllegalStateException - 如果 next方法尚未被调用,或者 remove方法在上次调用 next方法之后已经被调用

default void forEachRemaining(Consumer<? super E> action)
//对每个剩余元素执行给定的操作,直到所有元素都被处理或动作引发异常。 如果指定了该顺序,则按迭代的顺序执行操作。 动作抛出的异常被转发给呼叫者。
//实现要求: 默认实现的行为如下: while (hasNext()) action.accept(next());  
//参数 action - 要为每个元素执行的操作
//异常 NullPointerException - 如果指定的动作为空
//从以下版本开始: 1.8

重点看一下 forEachRemaining:

用法:forEachRemaining(element->对element的操作  element)

在没有引入lambda之前,集合支持两种遍历方式:1、for/while获取迭代器遍历。2、使用for-each遍历(Collection实现了Iterable,其规定必须有一个迭代器。所以对任何集合都可以使用for-each遍历)。这两种方法的共同特点都是要使用循环。到了Java8,其引入了forEachRemaining遍历方法。这个方法允许不使用循环遍历集合:

ArrayList<String> list = new ArrayList<>();
list.add("test1");
list.add("test2");
Iterator<String> iter = list.iterator();
iter.forEachRemaining(e-> System.out.println(e));

 

二、list体系及其迭代器

1)Java中的链式结构

Java中的链表都是双向循环链表,其可以从链表两头开始遍历。如果对LinkedList进行索引访问(不推荐,下面会讲到),若访问的坐标大于length/2,则从链表尾端向前遍历。

2)ArrayList与LinkedList(两者都不是同步的,有线程安全问题)

ArrayList:实现结构为循环数组。数组相比链表最大的特点就是可以按索引下标访问(随机访问)。但是数组如果要在中间加入/删除元素会导致前/后方元素集体移动,非常耗时间。

LinkedList:实现结构为双向链表。链式结构相比数组最大的特点就是在链表中间插入/删除元素只需要修改引用即可,不需要移动前/后方所有元素。缺点是按索引访问会非常慢,因为要从头/尾遍历挨个寻找元素。

综上描述,可以归纳出以下几点:

(1)当要按索引访问时,使用ArrayList。

(2)当要对表中添加/删除元素时,使用LinkedList。

(3)ArrayList一般用于查询,LinkedList用于修改。

3)lterator与listIterator

listIterator接口继承自lterator接口:

void add(E e)
//将指定的元素插入列表(可选操作)。

boolean hasNext()
//返回 true如果遍历正向列表,列表迭代器有多个元素。

boolean hasPrevious()
//返回 true如果遍历反向列表,列表迭代器有多个元素。

E next()
//返回列表中的下一个元素,并且前进光标位置。

int nextIndex()
//返回随后调用 next()返回的元素的索引。

E previous()
//返回列表中的上一个元素,并向后移动光标位置。

int previousIndex()
//返回由后续调用 previous()返回的元素的索引。

void remove()
//从列表中删除由 next()或 previous()返回的最后一个元素(可选操作)。

void set(E e)
//用指定的元素替换由 next()或 previous()返回的最后一个元素(可选操作)。

(1)listIterator(ArrayList与LinkedList通用)

上方说过,Java中的链表为双链表,因此可以进行向前/后遍历。listIterator与普通迭代器不同的是其提供了可以向前遍历、获取前方元素以及可以在元素中间插入元素的操作。

(2)迭代器的操作

我们使用 | 代表迭代器说明其工作原理

|ABC  ——> iter.next() ——> A|BC ——> 返回A(越过A)——>iter.next() ——> AB|C ——> iter.remove() ——> A|C(越过B) 

在使用next()方法后,迭代器越过了元素A,因此返回元素A;后边越过B,因此删除的是B。由此可见,迭代器只会对向前/后越过的元素进行操作。

(3)同步安全性(重点)

ArrayList与LinkedList是线程不安全的!

1、集合可以跟踪改写操作(添加、删除元素)的次数,迭代器也会维护一个自己进行改写操作次数的计数器。当两个计数数值不相等时便会抛出ConcurrentModificationException并发异常。例如在遍历list的时候使用list自己的删除方法删除了元素(list的计数器改变)但是没有使用迭代器删除元素(迭代器的计数器不改变),两者计数数值不一致便会抛出ConcurrentModificationException异常。但是如果使用了迭代器的remove()方法(迭代器计数数值加一)删除了list(list计数数值加一)的元素,两者相等,操作成功。

2、若同一个集合有两个迭代器,A迭代器发现B迭代器对集合进行了修改,则A就会抛出ConcurrentModificationException并发异常。

4)Vector

Vector的所有方法都是同步的,但是为了实现同步会浪费大量的时间。他可以使得两个线程安全的访问Vector。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值