list接口的实现对象
- 有序(存入和取出的顺序一致),元素都有索引(角标),元素可以重复。
ArrayList:
内部是数组数据结构(有序),但是不同步的,替代了Vector,如果想要保证线程安全,则可以手动在数据修改处加锁。特点——查询的速度很快
扩容机制:
如果内部数组满了,那么数组列表就会自动创建一个更大的新数组,然后将所有对象拷贝过去
- 容器类对象在调用 remove、 contains等方法时需要比较对象是否相等时,会涉及到对象类型的equals方法和 hashCode方法(Map类型,如果是List接口,仅需判断equals)
- 对于自定义的类型,需要要重写 equals和 hashCode方法以实现自定义的对象相等规则。
注意:相等的对象应该具有相等的 hash codes。
LinkedList:
内部是链表数据结构,是不同步的。特点——增删元素的速度很快
set接口的实现对象
- 存储的数据特点:无序的(根据数组的hash值存储的,而不是索引)、存储元素是不可重复的
- Set判断两个对象是否相同不是使用==运算符,而是根据 equals()方法
HashSet
- hashSet的底层就是HashMap
- HashSet是线程不安全的。
- HashSet通过对象的hashCode和equals方法来完成对象唯一性的。
- 扩容机制:当数组的使用率超过0.75时,扩容容量2倍
判断条件是这样的:
- 如果对象的hashCode值不同,那么不用判断equals方法,就直接存储到哈希表中。
- 如果对象的hashCode值相同,那么要再次判断对象的equals方法是否为true。
- 如果为true,视为相同元素,不存。如果为false,那么视为不同元素,就进行存储。
记住:如果将一个数据存储到HashSet集合中,必须覆盖hashCode方法和equals方法。
LinkHashSet
- 作为HashSet的子类;遍历其内部数据时,可以按照添加的顺序遍历,但是并不是代表LinkedHashSet是有序的
- 其内部还维护了两个引用(链表),因此添加删除数据会更快
TreeSet
- 底层用红黑树存储,所以TreeSet判断对象是否相同是用ComparaTo的返回值来确定的,如果返回0,则认为两个比较对象是相同的
- 向TreeSet中添加的数据,要求是相同类的对象。
- 可以对Set集合中的元素进行排序。是线程不安全的。
TreeSet的两种排序
TreeSet对元素进行排序的方式一(自然排序):
- 让元素自身具备比较功能:需要实现Comparable接口,覆盖compareTo方法。
TreeSet集合第二种排序方式(定制排序):
- 让集合自身具备比较功能,定义一个类实现Comparator接口,覆盖compare方法。
将该类对象作为参数传递给TreeSet集合的构造函数。
public void test2(){
Comparator com = new Comparator() {
//照年龄从小到大排列
@Override
public int compare(Object o1, Object o2) {
if(o1 instanceof User && o2 instanceof User){
User u1 = (User)o1;
User u2 = (User)o2;
return Integer.compare(u1.getAge(),u2.getAge());
}else{
throw new RuntimeException("输入的数据类型不匹配");
}
}
};
TreeSet set = new TreeSet(com);//有参数就按照定制排序
}
Map接口的实现对象
- Map(K,V):Map一次添加一对元素(键值对),key-value构成了一个entry对象。
- map集合中必须保证键的唯一性
- Key所在的类需要重新equals方法和hashCode方法
底层实现:
- 扩容向题:护容为原来容量2倍,并将原有的数据复制过来。
- jdk8时,首次put才创建数组(长度为16),类似懒汉式,而jdk7是饿汉式
- 在jdk7时HashMap是数组+链表的结构,HashMap是数组+链表+红黑树
- 当数组的某一个索引位置上的元素以链表形式存在的数据个数 > 8 且当前数组的长度 > 64时,此时此索引位置上的所数据改为使用红黑树存储。
Hashtable
- 开发中已经不怎么用了
- Hashtable :内部结构是哈希表,线程安全的。
- 不允许null作为键、null作为值。
有个子类 Properties: 常用来处理配置文件。key和value都是String类型
HashMap:
- 线程不安全的,效率快;
- 可以存储null的key和value
有个子类LinkedHashMap:效率更快
TreeMap:
- 保证照添加的key-value对进行排序,实现排序遍历。此时考虑key的自然排序或定制排序
- 底层使用红黑树
- 是线程不安全的
迭代Map
由于Map没有直接实现Iterator方法所以无法直接遍历Map。
但是有三个方法可以间接进行迭代取出Map集合中元素。
方法一:keySet()
我们可以通过keySet()方法获取map中所有的键组成的Set集合,再通过Set集合的迭代器方法取到键,最后根据键去取值就可以了。
方法二:entrySet()
该方法将键值对映射关系作为对象存储到了Set集合中,而这个映射关系的类型就是Map.Entry( )类型。(是一个整体)
Map中的entry:无序的、不可重复的,使用Set存储所的entry
Map.Entry有getKey( )和getValue( )供调用。
方法三:values()
利用多态,向上抽取父类,调用父类collection的values方法
Collections工具类
操作List、Set和Map集合的工具类
- Collections中提供了一系列静态的方法对集合元素进行排序、查询和修改等操作
- 还提供了对集合对象设置不可变、对集合对象实现同步控制等方法