1.概述
Collection{list(Vector、Arraylist、Linkedlist),Set(HashSet、TreeSet、LinkedHashSet)}
Map{(HashMap、Hashable、TreeMap)}
2.List接口及其实现类(各种集合框架的实现都重写了toString方法,可以快速输出),设计下标操作时选用。
List:中的数据对象有顺序且可以重复(即互相equals),适合维护线性结构的数据。List接口下特有方法具备的特点,操作的方法都存在索引值,只有list接口下的方法可以操作索引值,其他接口不具备操作索引值的特性。
1) Arraylist:底层是数组结构,所以查询快,修改、删除、插入慢。对于随机访问的get和set,Arraylist优于LinkedList,因为后者涉及到移动指针。
2) LinkedList:底层是链表结构,所以查询慢,修改、删除、插入快。
3) ArrayList:线程不安全,不同步。
Vector:线程安全,效率低。
3.Set接口及其实现类
set:中的数据对象没有顺序且不可重复,适合数据的查找。
1) TreeSet:不仅实现了Set接口,还实现了java.util.SortedSet接口,内部使用排序树进行存储,所有加入TreeSet的元素都保证是有序的,因为TreeSet的有序性,在进行查找时可以使用二分法进行高效查找,所以TreeSet集合的查找效率最高,但是维护所有元素都是有序的是比较困难的,在数据添加方面,TreeSet集合的效率相对较低。注意:如果使用TreeSet存放自定义类型,则要求该类型实现用于比较大小的Comparable接口,否则会出现异常。
2) HashSet:底层是用HashMap实现的,取了HashMap里面的key值,所以HashSet集合里面的元素不可重复,HashSet类按照哈希算法来存取对象,当向集合中加入一个新对象的时候,会调用对象的HashCode方法得到对象的哈希码,然后根据这个码计算出对象在集合中存储的位置。
3) LinkedHashSet:底层是链表结构,插入效率较高。需要注意的是,LinkedHashSet支持两种排序:插入顺序和访问顺序。前者是按照插入时的顺序排序,后者是按照最旧使用到最新使用的顺序,访问使用后,元素将会移至链表尾部。
补充:HashSet在向集合中添加元素的顺序
1) 在向集合中添加元素的时候,先调用该对象的hashCode()方法获取int型的数据,称为散列码。
2) 根据散列码计算元素在集合中的分类(比如集合分10类,用散列码除以10取余数获得类别)。
3) 如果该分类为空,直接添加。否则循环该分类下的所有元素,逐一调用equals方法进行比较,如果返回true,说明存在重复,添加失败。如果没有重复,将元素追加至该分类。注意:两个元素的hashcode如果相同,它们两个不一定相同,但是两个元素如果相同,那么它们的hashcode一定相同。
4.Map接口
Map提供key到value的映射,可以通过key查找value,一个key只能映射一个value。Map接口的实现类有:HashMap、TreeMap和HashTable等。Map的底层结构就是数组+链表。
1) HashTable:继承Map接口,实现一个key-value映射的Hash表,任何非空的对象都可以作为key或value,所以它的键和值都不能为空,HashTable是同步的(多个对象或者方法访问时,不会出现多线程的问题,比如死锁,即多线程时不用专门的操作就安全地可以使用了),线程安全。
2) HashMap:也是基于hash散列表的实现,键和值都可以为空,是不同步的,线程不安全。LinkedHashMap类似于HashMap,但是迭代遍历的时候,取得“键值对”的顺序是其插入的次序,或者是最近最少使用的次序。
3) TreeMap:基于红黑树数据结构的实现,查看键或“键值对”时,它们会被排序,得到的结果都是经过排序的。
5.集合注意事项
1) Collection类对象在调用remove、contains等方法时需要比较对象是否相等,这会涉及到对象类型的equals方法和hashCode方法;对于自定义类型,需要重写equals和hashCode方法以实现自定义的对象相等规则。
2) Collection没有get()方法来取得某个元素,只能通过iterator()遍历元素。添加元素用的是add()方法。
3) Set和Collection拥有一模一样的接口。
4) List可以通过get()方法来一次取出一个元素,使用下标取出相应的元素。
5) Map用的是put(),get()方法来添加或者取出某一个值,还可以使用containsKey()和containsValue()来检查其中是否含有某个键或者值。
6) Map中的元素,可以将Key序列、value序列单独抽取出来。使用keySet()抽取key,使用values()抽取value。
6.Iterator接口
所有实现了Collection接口的容器类都有一个iterator方法用以返回一个实现了Iterator接口的对象。Iterator对象称作迭代器,用以方便的实现对容器内元素的遍历操作。
1) boolean hasNext(); 判断游标右边是否有元素。
2) Object next(); 返回游标右边的元素并将游标移动到下一个位置。
3) void remove(); 删除游标左面的元素,在执行完next之后该操作只能执行一次。
使用迭代器的异常:NoSuchElementException:没有元素可以迭代。
ListIterator:系列表迭代器,允许程序员按任一方向遍历列表、迭代期间修改列表,并获得迭代器在列表中的当前位置。ListIterator 没有当前元素;它的光标位置始终位于调用previous() 所返回的元素和调用next() 所返回的元素之间,长度为n 的列表的迭代器有n+1 个可能的指针位置。特有的方法有:
1) hasPrevious(),判断是否存在上一个元素。
2) previous(),当前指针先向上移动一个单位,然后再取出当前指针所指元素。
3) next(),先取出当前指针指向的元素,然后指针向下移动一个单位。
4) add(),把当前元素插入到指针位置上。
5) set(),替换迭代器最后一次返回的元素。remove()和set()方法不是根据光标位置定义的,它们是根据对调用privious()和next()方法所返回的最后一个元素操作定义的。
迭代器在遍历元素时需要注意的事项:
在迭代器迭代元素的过程中,不允许使用集合对象改变集合中的元素个数,如果需要添加或者删除只能使用迭代器的方法进行操作(在添加元素时,迭代器指针会跳过该元素,要不然会出现死循环)。如果使用了集合对象改变了集合中的元素个数那么就会出现ConcurrentModificationException异常。
7.用容器存储数据
1.思路一
1) 一张表对应一个类。
2) 一个列对应一个属性。
3) 一个对象代表一行记录。做成构造器,封装起来,存储数据时更加方便。
4) 将这个类对象存贮在一个容器当中
2.思路二
1) 一行数据用一个Map对象来表示,键为表头属性,值为数据内容。
2) 将多个Map对象再放入容器当中进行存储。