- Set(集):集合中的元素不按特定方式排序,并且没有重复对象。他的有些实现类能对集合中的对象按特定方式排序。
- List(列表):集合中的元素按索引位置排序,可以有重复对象,允许按照对象在集合中的索引位置检索对象。
- Map(映射):集合中的每一个元素包含一对键对象和值对象,集合中没有重复的键对象,值对象可以重复。他的有些实现类能对集合中的键对象进行排序。
1、collection接口
Collection是整个类集中单值保存的最大父接口。
1 |
Public boolean add(E e) |
普通 |
向集合中添加 |
2 |
Public boolean addAll(Collection<? extends E> c) |
追加一个集合 |
|
3 |
Public void clear() |
||
4 |
Public boolean contains(Object o) |
||
5 |
Public boolean isEmpty |
||
6 |
Public boolean remove(Object o) |
||
7 |
Pulic int size() |
||
8 |
Public Object[] toArray() |
将集合变为字符数组 |
|
9 |
Public Iterator<E> iterator() |
|
|
只有add和Iterator会常常使用,但是要记住contains和remove方法需要Object的支持。
现在基本不使用collection接口,而是使用list和set这两个接口。
13.2.1 链表
从数组的中间位置删除一个元素要付出很大的代价,因为数组中处于被删除元素之后的元素都要向数组的前端移动,在数组中间的位置插入一个元素也是如此。
从链表中删除一个元素是一个非常轻松操作,急需要对被删除元素附近的节点更新一下即可。
List<String> staff = new LinkList<>(); staff.add("Amy"); staff.add("Bob"); staff.add("Carl"); Iterator iter = staff.iterator(); String first = iter.next(); String second = iter.next(); iter.remove();
链表是一个有序集合,每个对象的位置十分重要。LinkList.add方法将对象添加到链表的尾部,但是,常常需要将元素添加到链表的中间。由于迭代器是描述集合中位置的,所以这种依赖于位置的add方法将由迭代器负责。只有对自然有序的集合使用迭代器添加元素才有实际意义。例如,下一节中讨论的集(set)类型,其中的元素完全无序。因此,在Iterator接口中就没有add方法,相反的,集合类库提供了子接口ListIterator,其中包含add方法。
Collection接口中声明了很多对链表操作的有用方法,其中大部分方法都是在LinkList类的超类AbstractCollection中实现的。例如,toString方法调用了所有元素的toString,并产生了一个很长的格式为[A,B,C]的字符串。这为调试工作提供了便利。可以使用contaions方法检测某个元素是否出现在链表中。例如,如果链表中包含一个等于“Harry”的字符串,调用staff.contains("Harry")后将会返回true。
链表不支持快速地随机访问。
如果要查看链表的第n个元素,就必须从头开始,超过n-1个元素,没有捷径可走,所以在采用整数索引访问元素的时候,一般不选用链表。
尽管如此,LinkList中提供了一个用来访问某个特定元素的get方法:
LinkList<String> list = ... ; String obj = list.get(n);
get方法的效率不高,而且非常不建议使用get方法对链表进行遍历。
列表迭代器接口中有一种方法,可以告知当前位置的索引。实际上,Java迭代器指向两个元素之间的位置,所以可以 同时产生两个索引:nextIndex方法返回下一次调用next时返回元素的整数索引;previousIndex方法返回下一次调用previous方法时返回元素的整数索引。当然,这个索引只比nextIndex返回的索引值小1.这两个方法的效率非常高,因为迭代器保持着当前位置的计数值,
如果一个整数索引是n,则list。listIterator(n)将返回一个迭代器,这个迭代器指向索引为n的元素前面的位置,也就是说,调用next与调用list.get(n)会产生同一个元素,只是get方法效率比较低。
如果链表中只有很少的几个元素,就完全不必担心get方法和set方法的开销带来的烦恼。
为什么优先使用链表?唯一的理由是尽可能减少在列表中间插入或删除元素所付出的代价。如果列表中只有少数几个元素,就完全可以使用ArrayList。
如果需要对集合进行随机访问,就使用数组或者ArrayList,而不是使用链表。
import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; public class list_13_1 { public static void main(String args[]) { List<String> a = new LinkedList<>(); a.add("Amy"); a.add("Carl"); a.add("Erica"); List<String> b = new LinkedList<>(); b.add("Bob"); b.add("Doug"); b.add("Frances"); b.add("Gloria"); ListIterator<String> aIter = a.listIterator(); Iterator<String> bIter = b.listIterator(); //b非空 while(bIter.hasNext()) { //跳过一个 if(aIter.hasNext()) aIter.next(); //每隔一个,将b中的元素加入到a中 aIter.add(bIter.next()); } System.out.println(a); bIter = b.iterator(); while(bIter.hasNext()) { bIter.next(); if(bIter.hasNext()) { //每隔一个,删除一个b中的元素 bIter.next(); bIter.remove(); } } System.out.println(b); a.removeAll(b); System.out.println(a); } }
创建两个链表,将他们合并在一起,然后从第二个链表中每隔一个元素删除一个元素,最后测试removeAll方法。