集合框架图:
集合类的由来:对象用于封装特有数据,但是一旦对象变多,则需要被存储,对象的个数不确定时,需要使用集合容器来进行存储。
集合的特点:
1、集合的长度是可变的。
2、集合中存储的是(对象)引用类型数据,不可存储基本数据类型数据。
集合框架的形成:集合容器因为内部结构不同,并且有多种集合容器,所以被不断向上抽取形成了集合框架。
集合框架的顶级父类为Collection接口:
Collection接口中常见方法:
1、添加方法
boolean add(Object obj);
boolean addAll(Collection col);//添加指定集合(col)中所有元素到该集合中。
2、删除方法
boolean remove(Object obj);//移除该集合中的obj元素
boolean removeAll(Collection col);//移除该集合中所有与指定集合(col)中相同的元素。
void clear();//清空所有元素
3、判断:
boolean contains(Object obj);//判断给集合中是否存在obj元素
boolean containsAll(Collection col);//判断指定集合中元素是否全部存在于该集合中。
boolean isEmpty();//判断集合中是否有元素
4、获取:
int size();//获取集合大小。
5、迭代器:
Iterator iterator();//迭代器,用于取出集合中元素
Iterator接口就是所有的Collection容器进行元素取出的公共接口。
迭代器中提供了统一方法,用于遍历集合元素。
常用方法:
boolean hasNext();//判断是否还有下一个元素
E next();//取出集合中下一个元素
void remove();//在使用迭代器对集合进行遍历时,不能使用集合的移除方法移除集合的元素。必须使用迭代器自己提供的方法才可移除。
6、其他:
boolean retainAll(Collection col);//获取指定集合与该集合中的相同元素。也就是我们通常说的取交集。
Object[] toArray();//将集合转成数组
Collection接口有三个子接口:List、Set、Queue
一、List:List中常见方法,共性特点为都可以操作角标。
特点:有序(存入和取出顺序一致),元素都有索引,元素可以重复。
List中常用方法:
1、添加:
void add(int index,E element);//将指定元素添加到索引为index的位置上。
boolean addAll(int index,Collection col);//将指定集合中所有元素都添加到索引为index的位置上。
2、删除:
E remove(int index);//删除指定索引的元素,返回被删除的元素
boolean remove(Object o);//删除集合中第一个出现(如果存在)的指定元素
3、修改:
E set(int index,E element);//修改指定索引上的元素为element,此方法返回被修改的值。
4、获取:
E get(int index);//获取指定索引上的元素
int indexOf(object o);//获取指定元素第一次出现的索引,如果没有此元素则返回-1
int lastIndexOf(object o);//获取指定元素最后一次出现的索引,如果该元素不存在则返回-1
list<E> subList(int fromIndex,int toIndex);//返回此列表中指定的fromIndex和toIndex之间的视图。包前不包后。
ps:subList();方法在堆中产生了内部类Sublist新的集合对象。此集合对象引用的父集的一部分,修改子集会对父集产生影响。
List接口有三个实现类:
1、ArrayList:内部是动态数组结构,是不同步的。替代了Vector,查询很快。可存null值。(由于LinkedList每次查询都需要移动指针,效率低。)
2、LinkedList:内部是双链表结构,是不同步的。可存null值。删除和增加元素很快(由于ArrayList内部是数组结构,删除增加都需要扩容,移动元素)。
3、Vector:内部是动态数组结构,是同步的。可存null值,线程安全,但是增删、查询都很慢。
ps:Arrays中有一个方法,static List <E> Arrays.asList(T...a);-----将数组转换为集合。
eg:String[] arr1 = {"a","b","c"};
List<String> list = Arrays.asList(arr1);
二、Set:
特点:无序,元素不可重复。
Set接口有三个实现类:set接口中方法与Collection中方法一致。
1、HashSet:内部数据结构是哈希表,是不同步的。可存null值。
如何保证元素的唯一性?
是通过对象的hashCode和equals方法来完成对象的唯一性的。
如果对象的hashCode值不同,那么不需要判断equals方法,就直接存储到哈希表中。
如果对象的hashCode值相同,那么要再次判断对象的equals方法是否为true。
如果为true,视为相同元素,不存。如果为false,那么视为不同元素,就进行存储。
ps:如果元素要存储到HashSet集合中,必须覆盖hashCode方法和equals方法。
一般情况下,如果定义的类会产生很多对象,比如人,学生,书,通常都要覆盖equals、hashCode方法。
这是建立对象判断是否相同的依据。
2、LinkedHashSet:是HashSet的子类。可存null值,是不同步的。
内部数据结构是哈希表,同时使用链表来维护顺序,顺序与添加顺序一致。在查看检索时效率较高。
3、TreeSet:是SortedSet子接口的实现类,使用二叉树的数据结构维护元素的顺序。可以对Set集合中的元素进行排序。是不同步的。可存null值。
判断元素唯一性的方式:就是根据比较方法的返回值结果是否为0,是0就是相同元素,不存。
ThreeSet对元素进行排序的方式一:
让元素自身具备比较功能,就需要实现Comparable接口。覆盖comparaTo方法。
如果不要按照对象中具备的自然顺序进行排序。或者对象中不具备自然顺序。怎么办?
可以使用ThreeSet集合第二种排序方式二:
让集合自身具备比较功能,定义一个类实现Comparator接口,覆盖compare方法。
将该对象作为参数传递给ThreeSet集合的构造函数。
Set集合的遍历
因为Set集合是无序的,无下标可言,因此不能使用经典for
循环。我们可以使用迭代器原理。
(1) 调用集合的iterator()获取迭代器
(2) 使用foreach循环:for(要循环的元素类型 变量名:要遍历的集合或数组){
}
Set集合的元素:
不能轻易修改参与hash值算法的成员变量。
否则容易引起内存溢出。
原因:成员变量修改后,会出现新的hash值,但是存储位置还在
原hash值的位置上。因此操作时,找不
到具体的存储位置。
三、Queue:是队列。
队列通常都是一端进(offer),另一端出(poll)。Queue接口的实现类是LinkedList(由于队列经常进行增删操作,所以使用LinkedList实现了Queue接口)。
进出原则:先进先出(FIFO)
常用方法为:
boolean offer(E e);//元素从队尾进入队列。
E poll();//从队首移除元素,返回被移除的元素。当队列没有元素返回null。
E peek();//查看队首元素,不移除。队列中没有元素返回null。
ps:为了避免移除队列的队首元素时出现null,我们最好先查看队首元素是不是null。
Example:
输出结果为:
Deque:为Queue的子接口,实现的是双端队列的数据结构,两端都可进,都可出。
常用方法为:
boolean offerFirst(E e);//元素从队列的队首进入队列。
boolean offerLast(E e);//元素从队列的队尾进入队列。
E pollFirst();//从队首移除元素,返回被移除元素。
E pollLast();//从队尾移除元素,返回被移除元素。
E peekFirst();//查看队首元素,不移除。
E peekLast();//查看队尾元素,不移除。
Example:
输出结果为:
栈的数据结构:先进后出(FILO)
我们可以将双端队列的一端禁止操作。另一端进或出,即Stack。
常用方法:
void push(E e);//将指定元素e压进栈中。
E pop();//将栈中的最顶端元素移除。
Example:
运行结果为: