一、集合概述:
1、集合特点:
集合只用于存储对象,集合的长度是可变的,可以存储不同类型的对象。
2、集合和数组的区别?
1、集合的长度是可变的,数组的长度是固定的。
2、数组可以存储对象和基本数据类型,集合只能存储对象。
3、集合框架的由来:
因为集合有很多,而且各个集合的数据结构都有不同,但都具备共性,这些共性通过向上抽取就形成了集合框架。
数据结构:就是容器中对象的存储方式。
4、迭代器Iterator:
迭代器是集合中元素的取出方式,而每个集合怎么取出元素集合自己清楚,所以迭代器定义在内部类中。只要是Collection集合中的容器,迭代器是通用的取出方式。
publicclass InteratorDemo {
publicstaticvoid main(String[] args) {
Collection coll =newArrayList();
coll.add("java1");
coll.add("java2");
coll.add("java3");
coll.add("java4");
//获取迭代器,并用迭代器迭代元素。
for(Iterator it = coll.iterator();it.hasNext();){
System.out.println(it.next());
}
}
}
列表迭代器ListIteator:ListIterator继承了Iterator。
使用Iterator在对集合进行迭代时,在迭代的过程中是不能对集合进行修改的,因为如果对集合进行操作,那么迭代器是不知道的,所以就会产生不确定性。
如果想要在迭代的过程中想要对元素进行更多的操作,可以使用ListIterator列表迭代器中提供了更多对元素操作的方法。
ListIterator提供了对元素增,删,改,查的方法:
5、注意事项:
1、集合中真正存储的是对象的引用。
2、jdk1.5后可以直接存储基本数据类型数据,因为有自动装箱机制。
3、在开发中一般存储的都是自定义对象。
6、集合使用注意:
1、用add方法存储时,都被提升为了Objcet。取出时如果要使用自定义对象的特有方法,一定要进行向下转型。
2、一般集合都结合泛型使用,如果定义泛型就可以不用强转了。
System.out.println((Person)it.next().getName());// 强转过程,点的优先级别很高,所以要用小括号括起来。
3、在迭代过程,循环中只需要有一个it.next()即可。
二、集合文档。
Collection集合框架图:
Collection中的方法:
1、添加:
boolean add(E e):一次添加一个元素。
boolean addAll(Collection):将一个容器中的元素添加到当前容器中。
2、删除:
boolean remove(Object o):删除一个指定对象。
boolean removeAll(Collection c):删除参数容器和本容器中相同的元素。
void clear():直接将容器中的元素清空。
3、判断:
boolean contains(Object o):是否包含指定元素。
boolean containsAll(Collection c):是否包含指定容器中的元素。容器中元素发生变化为ture
boolean inEmpty():是否有元素,是否为空。
LinkedList中特有操作方法:
addFirst();将指定元素插入此列表的开头。
addLast();将指定元素添加到此列表的结尾。
jdk1.6以后,变成。
offerFirst();
offerLast();
getFirst();返回此列表的第一个元素。如果列表为空,抛出异常。
getLast();返回此列表的最后一个元素。如果列表为空,抛出异常。
jdk1.6以后。
peekFirst();返回此列表的第一个元素。如果列表为空,返回null。
peekLast();返回此列表的最后一个元素。如果列表为空,返回null。
removeFirst();移除并返回此列表的第一个元素。如果列表为空,抛出异常。
removeLast(); 移除并返回此列表的最后一个元素。如果列表为空,抛出异常。
jdk1.6以后。
pollFirst();移除并返回此列表的第一个元素。如果列表为空,返回null
pollLast();移除并返回此列表的最后一个元素。如果列表为空,返回null
List集合中的方法:基本上和Collection一致,只是多了角标的操作。
1、添加
void add(int index,E element):将元素插入指定角标位置。
boolean addAll(int index,collection c):将参数容器中的元素插入指定位置角标。
2、删除
E remove(index);
3、获取
获取元素:
E get(index):根据角标获取元素。
获取索引:
int indexOf(object):根据元素获取元素第一次的角标。如果没有元素,返回-1.
int lastIndexOf(object):根据元素获取元素最后出现的角标。
获取子列表:
List subList(fromIndex,toIndex):获取列表中的一部分,包含fromIndex,不包含toIndex。
4、修改
object set(index,element):替换指定位置的元素,并返回被替换掉的元素。
我们发现List接口可以对元素进行增,删,改,查的操作(只有这个具备)。
|--List:列表。
特点:
1、有序(存储元素的顺序和取出元素的顺序相同)。
2、该集合中的元素都有索引,可以通过索引来访问元素。
3、该集合可以存储相同元素。
|--Set:集:这个集合中的方法和Collection一致。
特点:
1、不能存储重复元素。
2、存入的元素顺序和取出元素的顺序不一定不同(具体的容器对象数据结构不同,顺序也有不同)。
List的常见子类对象:我们重点学的是这些子类对象的特有数据结构,以及相关特点。
|--vector:jdk1.0就存在了,底层是数组结构的,是可变长度数组 ,vector是同步的。
可变数组原理:一旦原数组长度不够,会创建新数组,将原数组的元素复制到新数组中,并将新元素添加到新数组中。
vector有两种取出元素的方式:
方式一:迭代器。
方式二:枚举。跟迭代器的取出方式是一样,就是写法不一样,后期枚举被迭代器取代了。
|--ArrayList:1.2后出现的,底层是数组结构,也是支持长度可变数组的。好处:查询元素效率很高。
是不同步的。替代了vector,因为效率高。
|--LinkedList:底层是链接列表结构。这种结构的特点是每个元素都会记住后面跟着的元素的位置。
这种结构好处:对元素的增删效率非常高。但是查询效率很低。
两种常见的数据结构:
1、队列:先进先出。
2、堆栈:先进后出。
面试题:用LinkedList集合模拟队列和堆栈结构。
定义一个功能,去除ArrayList中重复的元素。使用contains方法判断交集。contains方法依赖equals。
定义一个功能,去除重复ArrayList集合中重复元素,用ArrayList存储自定义Person对象,如果姓名和年龄相同就不存储。
Set集合中常见的子类对象:
HashSet:
|--HashSet:底层数据结构是哈希表,不保证顺序,是不同步的。
1、HashSet的特点:
1、不关心顺序。
2、提高了查询效率。
3、不能存储相同元素。
2、HashSet容器中元素存储位置?
将要存储的元素先通过哈希算法算出一个哈希值,来标识存储的位置,代表着元素。想要查找元素,通过元素的哈希算法算出哈希值,再通过哈希值到哈希表中查找。
3、判断元素唯一性的依据是?
判断哈希值,通过hashCode方法来完成。
判断元素相同,通过equals方法来完成。ture视为元素相同。
所以使用HashSet集合来存储元素需要覆盖元素的hashCode和equals方法。
覆盖方法代码演示:
覆盖Object类中的hashCode方法,建立Person对象自己特点的哈希算法。HashSet集合。
publicint hashCode(){
returnname.hashCode() +age;
}
覆盖equals方法,建立Person对象自身的比较方法。HashSet集合。
publicboolean equals(Object obj){
if(!(objinstanceof Person)){
returnfalse;
}
Person p = (Person)obj;
returnthis.name.equals(p.name) && this.age == p.age;
}
TreeSet:
|--TreeSet:底层是二叉树结构。可以给set集合中的元素进行指定顺序排序,默认情况下是通过元素自然顺序排序的。
1、保证元素唯一:保证元素元素唯一性的依据是看compareTo方法返回结果是否为0,是0就视为相同,不存。
注意:TreeSet集合存储的对象必须要具备比较功能,不然会出现异常。
如何写conpareTo的对象比较:
(重点)覆盖conpareTo方法进行比较的时候,通常,先比较主要条件,如果主要条件相同,再比较次要条件。
2、TreeSet排序方式:
TreeSet排序方式一:让元素自身具备比较性,需要实现Comparable接口,覆盖compareTo方法。
需求:按照姓名进行排序。姓名主要,年龄次要。
通常,比较的时候,先比较主要条件,如果主要条件相同,再比较次要条件。如果想要按照一个人的年龄排序,如果年龄相同,再比较姓名。
//覆盖compareTo()方法,建立person类的比较方法。
publicint compareTo(Object o) {
Person p = (Person)o;
if(this.age>p.age)
return 1;
if(this.age<p.age)
returnthis.name.compareTo(p.name);//这是String对象中的比较方法。
//为什么这么调用??? this.name相当于一个字符串对象,所以可以调用方法。
return -1;
/*
* 技巧性写法。
*/
// Person p = (Person)o;
// int temp = this.age - p.age;
// return temp==0?this.name.compareTo(p.name):temp;
}
TreeSet排序方式二:比较器排序方式,让容器自身具备比较性。
如果元素自身具备的比较性(自然顺序)不是所需要的,那就用这种排序方式。容器中有一个构造方法,TreeSet(comparator).可以再容器初始化时,指定一个比较器。
自定义比较器:需要实现Comparator接口,覆盖Compare方法即可。
需求:对字符串的长度进行排序,使用TreeSet集合。
定义了一个根据Person的Name进行比较的比较器。
publicclass ComparatorByNameimplementsComparator {
publicint compare(Object o1,Object o2){
Person p1 = (Person)o1;
Person p2 = (Person)o2; int temp = p1.getName().compareTo(p2.getName());
return temp==0?p1.getAge()-p2.getAge():temp;
}
}
其他容器:
LinkedHashSet:集合中的一个有序集合。
hashSet查询速度比较快,但不能保证顺序。
是hashSet的子类:1.4版本后出现LinkedHashSet
存储元素:还是按照哈希表存,但是会按照链表的方式记录住每个元素。