(1)、为什么要有集合?
面向对象语言对事物的体现都是以对象的形式,为了方便对多个对象进行操作我们就需要把这多个对象进行存储,要存储多个对象,不能是一个基本的变量。需要的是一个容器变量。我们前面所学,只有数组和StringBuffer是容器,但是StringBuffer的结果是一个字符串,不一定能满足我们的要求,所以只能选择数组,但是数组的长度不能变化,又满足不了变化的需求,所以,java就提供了集合类来供我们使用。
(2)、集合和数组的区别
长度区别:数组长度是固定的,集合长度是可变的
内容不同:数组存储的是同一种类型的元素,集合可以存储不同类型的元素
元素的数据类型不同:数组可以是基本类型,也可以是引用类型,集合只能存引用类型
(3)、集合继承关系图
Collection跟Map没什么关系,图中想表达的意思是可以通过Map生成Collection。比如:Map可以返回其所有键组成的Set和其所有值组成的Collection,或其键值对组成的Set。
(4)、Collection
是集合的顶层接口,它的子体系中有可重复的,有唯一的,有序的,有无序的。
添加功能
boolean add(Object o);添加一个元素
boolean addAll(Collection c)添加一个集合的元素
删除功能
void clear()删除集合中所有元素
boolean remove(Object o)删除指定元素
boolean removeAll(Collection c)删除一个集合的元素,删除一个
判断功能
boolean contains(Object o)判断集合中是否含有指定元素
boolean containsAll(Collection c)判断集合中是否包含指定集合的元素,包含所有
boolean isEmpty()判断集合是否为空
获取功能
Iterator<E> iterator(),迭代器
[boolean hasNext()判断是否有下一个元素,有则返回true,否则false,Object next()获取下一个元素,并移动到下一个位置]
int size()获取元素的个数
交集功能
boolean retainAll(Collection c)两个集合都有的元素,调用方法的集合是否改变
转换功能
Object[] toArray() 把集合转成数组
(5)、Iterator接口
对Collection进行迭代的迭代器,依赖于集合存在的。
接口中的成员方法
boolean hasNext()
E next()
为什么不定义成一个类,而是一个接口?
假设迭代器是一个类,那么我们就可以创建该类对象,调用该类方法来实现集合的遍历。但是,java中提供了很多集合类。这些集合类的数据结构是不同的,所以存储数据的方式和遍历的方式应该也是不同的。所以迭代器不是一个类。
无论是哪种集合,都应该具备获取元素的操作,并且,最好有判断功能来做辅助,这样,再获取前先判断,就不容易出错。也就是说判断和获取功能应该是一个集合遍历所具备的功能。然而每种集合的方式又不一样,所以我们把这两个功能提取出来,不给出具体的实现,这中方式就是接口。
真正的实现再具体的子类中,以内部类的方式体现的。
(6)、List接口
有序集合(也称为序列 )。 使用此接口的用户可以精确控制列表中每个元素的插入位置。 用户可以通过整数索引(列表中的位置)访问元素,并搜索列表中的元素,和set不同,列表通常允许重复的元素
方法
void add(int index,E element)再指定位置添加元素
E get(int index)获取指定位置的元素
ListIterator<E> listIterator()List集合特有的迭代器
E remove(int index)根据指定索引删除元素,返回被删除的元素
E set(int index,E element)根据索引修改元素,返回被替代的元素
(7)、ArrayList类
底层数据结构是数组,查询快,增删慢。线程不安全,效率高
(8)、Vector类
底层数据结构是数组,查询快,增删慢。线程安全,效率低
特有内容
public void addElement(E obj),添加一个元素add()
public E elementAt(int index),获取指定位置元素get()
public Enumeration<E> elements(),iterator()
Public E nextElement(),next()
public E firstElement(),hasNext(),get(0)
public void setElementAt(E obj,int index),设置指定位置的元素set()
JDK升级原因:安全升级、提高效率、简化书写、添加新特性
(9)、LinkedList类
底层数据结构是链表,查询慢,增删快。线程不安全,效率高
特有内容
public void addFirst(E e)
public void addLast(E e)
public E getFirst()
public E getLast()
public E element()
public E removeFirst()
public E removeLast()
(10)、增强for
简化数组和集合的遍历
jdk5之后的新特性:自动拆装箱、泛型、增强for、静态导入、可变参数、枚举
(11)、静态导入
可以直接导入到方法的级别,方法必须是静态的,如果有多个方法同名,容易搞混,不知道用谁,这个时候要使用,就必须加前缀。
import static 包名...类名.方法名;
(12)、Arrays数组工具类中的方法
public static <T> List<T> asList(T... a)//把数组转成集合
注意:虽然可以把数组变成集合,但是集合的长度不能发生改变
(13)、set接口
set接口:无序不包含重复元素的集合
(14)、HashSet类
不保证set的迭代顺序,不能保证订单在一段时间内保持不变。
HashSet是如何保证元素的唯一的?
底层数据结构是哈希表(元素是链表的数组)
哈希表依赖哈希值存储
添加功能底层依赖2个方法:hashCode()、equals()
(15)、LinkedHashSet类
元素有序并唯一
底层数据结构是由哈希表和链表组成
由链表保证有序
由哈希表保证唯一
(16)、TreeSet类
使用元素的自然顺序对元素进行排序或者根据创建set时提供的Comparator 进行排序,具体取决于使用的构造方法。
TreeSet:能够按照2种顺序对元素进行排序
自然排序:
需要被排序的类实现Comparable<T>接口,重写其中的 comparaTo
比较器排序:
这种方法需要一个新的类实现Comparator<T>接口,重写其中的compare方法
前者-后者是升序排列,小值放在前面(返回负数在前面,返回正数在后面)
public class Demo {
public static class MySet implements Comparable<MySet> {
int num;
public MySet(int num) {
this.num = num;
}
@Override
public int compareTo(MySet o) {
return this.num - o.num;
}
}
public static void main(String[] args) {
Set<MySet> set = new TreeSet();
set.add(new MySet(10));
set.add(new MySet(15));
set.add(new MySet(9));
for (MySet mySet : set) {
System.out.println(mySet.num);
}
}
public static class Demo{
public static class MySet{
int num;
public MySet(int num) {
this.num = num;
}
}
public static void main(String[]args){
Set<MySet> set = new TreeSet<MySet>(new Comparator<MySet>() {
@Override
public int compare(MySet o1, MySet o2) {
return o2.num-o1.num;
}
});
set.add(new MySet(10));
set.add(new MySet(15));
set.add(new MySet(9));
for (MySet mySet : set) {
System.out.println(mySet.num);
}
}
}
}
TreeSet集合的特点:
排序和唯一
创建集合对象使用无参,采用自然顺序排序
TreeSet是如何保证元素的排序和唯一的:
底层数据结构是红黑树(红黑树是一种自平衡的二叉树)
基于TreeMap实现
如果一个类的元素要想能够进行自然排序,就必须实现自然排序接口
TreeSet存储自定义对象并遍历
比较依赖的是元素的compareTo()方法,这个方法是定义在Comparable接口中的是抽象方法,自定义类没有实现此接口,所以用TreeSet集合存储自定义类的时候无法比较所以程序就报错了
我们要用TreeSet存储自定义对象,那么自定义类就必须重写compareTo()方法,所以自定义类就必须实现Comparable接口,这个接口表示的就是自然排序
TreeSet集合保证元素唯一和排序的原理:被排序的类必须实现Comparable接口
(17)、Map(接口)集合
Map集合遍历
方式1,根据键找值,获取所有键的集合,遍历键的集合,获取每一个值
方式2,获取所有映射关系,从映射关系中拿出键值
(18)、HashMap类
键是哈希表结构,可以保证键的唯一性
不能保证map的顺序; 特别是,它不能保证订单在一段时间内保持不变。
(19)、LinkedHashMap类
哈希表和链表实现的Map接口,具有可预测的迭代次序。
这种实现不同于HashMap,它维持于所有条目的运行双向链表
由哈希表保证键的唯一
由链表保证键的有序(存和取的顺序一致)
(20)、TreeMap类
键是红黑树结构,可以保证键的排序和唯一
Map map = new HashMap<Integer, Student>();
map.put(1, new Student("AAA", 10));
map.put(2, new Student("BBB", 20));
map.put(3, new Student("CCC", 30));
map.put(1, new Student("DDD", 40));
Set keySet = map.keySet();
Iterator iterator = keySet.iterator();
while (iterator.hasNext()) {
Object key = iterator.next();
Object value = map.get(key);
System.out.println(key + ":" + value);
}
Set set = map.entrySet();
Iterator it = set.iterator();
while (it.hasNext()){
Map.Entry entry = (Map.Entry) it.next();
Object key = entry.getKey();
Object value = entry.getValue();
System.out.println(key + ":" + value);
}