Collection
1.概述
Java集合可分为Collection和Map两种体系
- Collection接口:单列数据,定义存取一组对象的方法集合
- List:元素有序、可重复的集合
- Set:元素无序、不可重复的集合
- Map接口:双列数据,保存具有映射关系"key-value对"的集合


2.Collection
Collection coll = new ArrayList();
coll.add(123); // 自动装箱
coll.add("AA");
coll.add("BB");
coll.add(new Date());
// size获取元素个数
System.out.println(coll.size());
Collection coll1 = new ArrayList();
coll.add(456);
coll.add("CC");
// addAll将coll1集合中的元素添加到当前的集合中,原集合会清空
coll.addAll(coll1);
System.out.println(coll.size());
System.out.println(coll);
// isEmpty判断当前集合是否为空
System.out.println(coll1.isEmpty());
// clear清空当前集合
coll1.clear();
System.out.println(coll1);
2.1.常用方法
向Collection中添加数据时,建议重写添加项的equals方法
(1)添加:
add(Object obj)
addAll(Collection coll)
(2)获取有效元素个数:
int size()
(3)清空集合:
void clear()
(4)是否是空集合:
boolean isEmpty()
(5)是否包含某个元素
boolean cotains(Object obj) // 通过元素的equals方法来判断是否是同一个对象
boolean containsAll(Collection c) // 也是调用元素的equals方法来比较,用两个集合的元素比较
(6)删除
boolean remove(Object obj) // 通过元素的equals方法判断是否是要删除的哪个元素,只会删除找到的第一个元素
boolean removeAll(Collection coll) // 取当前集合的差集
(7)取两个集合的交集
boolean retainAll(Collection c) // 将交集得到结果存在于当前集合中,不影响c
(8)集合是否相等
boolean equals(Object obj) // 如果是ArrayList,还需要考虑顺序
(9)转成对象数组
Object[] toArray()
调用Arrays.asList可以将数组转换为集合
注:
// 如果是基本类型的数组,则整个数组会被识别为一个元素
List list = Arrays.asList(new int[]{1, 2});
System.out.println(list.size()); // 1
(10)获取集合对象的hash值
hashCode()
(11)遍历
iterator() // 返回迭代器对象,用于集合遍历
Collection coll = new ArrayList();
coll.add(123);
coll.add(456);
coll.add("Tom");
coll.add(false);
coll.add(new Person(20, "Jerry"));
Iterator it = coll.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
(12)forEach遍历
coll.forEach(System.out::println);
Collection接口继承java.lang.Iterator接口,此接口有一个iterator()方法,name所有实现Collection接口的集合类都有一个iterator()方法,用以返回一个实现Iterator接口的对象
Iterator仅用于遍历集合,Iterator本身并不提供承装对象的能力,如果需要创建Iterator对象,则必须有一个被迭代的集合
集合对象每次调用iterator()方法都得到一个全新的迭代器对象,默认游标都在集合的第一个元素之前
iterator也有remove方法,可用于删除集合中数据
while (it.hasNext()) {
Object next = it.next();
if ("Tom".equals(next)) {
it.remove();
}
}
补充:
// 使用增强for时修改元素并不会对当前元素产生影响,因为增强for是将每次取出的值赋给下面的obj,改变obj的值并不会对集合(或数组)产生影响
for (Object obj : coll) {
obj=1;
System.out.println(obj);
}
3.List
List集合中元素有序、且可重复,集合中每个元素都有其对应的顺序索引
List容器中的元素都对应一个整数型的序号记载,可以根据序号存取容器中的元素
JDK API中List接口的实现类常用的有:ArrayList、LinkedList、Vector
3.1.ArrayList、LinkedList、Vector三者异同
同:均实现List接口,存储数据的特点相同
不同:
ArrayList作为List接口的主要实现类(1.2版本实现),线程不安全,效率高,底层使用Object[]存储
LinkedList底层使用双向链表存储,对于频繁插入和删除操作时使用此类效率高
Vector作为List接口的古老实现类(1.0版本出现),线程安全,效率低,底层使用Object[]数组
3.2.ArrayList的源码分析
(1)jdk7情况下
ArrayList list=new ArrayList(); // 默认长度为10
默认情况下,扩容为原容量的1.5倍,同时需要将原有数组中数据复制到新数组中
结论:建议开发中使用带参构造器:ArrayList(int initialCapacity)
(2)jdk8情况下
ArrayList list=new ArrayList(); // 底层Object[] elementData初始化为{},并没有创建长度
第一次调用add时,底层才创建长度为10的数组,并将数据添加到第一个位置上
后续的添加与扩容操作与JDK7相同
(3)小结
JDK7中ArrayList创建类似于单例模式的饿汉式,JDK8创建类似于单例模式的懒汉式,延迟数组的创建,节省内存
3.3.LinkedList的源码分析
LinkedList list=new LinkedList(); // 内部声明Node类型的first和last属性,默认值为null
list.add(123) // 将123封装到Node中,创建Node对象
其中,Node定义为:
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
3.4.Vector的源码分析
JDK7与JDK8中通过构造器创建对象时,底层默认创建长度为10的数组,在扩容方面,默认扩容为原来的数组2倍的长度
3.5.List接口方法
List除从Collection集合继承的方法外,其添加一些根据索引来操作集合元素的方法
void add(int index,Object ele) 在index位置插入ele元素
boolean addAll(int index,Collection eles) 从index位置开始将eles中的所有元素添加进来
Object get(int index) 获取指定index位置的元素
int indexOf(Object obj) 返回obj在集合中首次出现的位置,如果不存在则返回-1
int lastIndexOf(Object obj) 返回obj在当前集合中末次出现的位置
Object remove(int index) 移除指定index位置的元素,并返回此元素
Object set(int index,Object ele) 设置指定index位置的元素为ele
List subList(int fromIndex,int toIndex) 返回从fromIndex到toIndex位置左闭右开的子集合,不影响集合自身
总结:常用方法
增:add(Object obj)
删:remove(Object obj) / remove(int index)
改:set(int index,Object obj)
查:get(int index)
插:add(int index,Object obj)
长度:size()
遍历:增强for循环 / iterator迭代器方式 / 普通循环
4.Set接口
- Set接口用于存储无序的、不可重复的数据
- HashSet作为Set接口的主要实现类,线程不安全,可以存储null值
- LinkedHashSet作为HashSet的子类,在遍历时可以按照添加的顺序进行遍历
- TreeSet:底层使用红黑树,放入其中的数据需要是同一个类的对象,可以按照添加对象的指定属性进行排序
Set接口中没有额外定义新的方法,用的只是Collection中的方法
无序性:不等于随机性,存储的数组在底层数组中并非按照数组索引的顺序添加,根据hash值确定存储的位置
不可重复性:添加的数据不可重复,保证添加的元素按照equals判断时,不能返回true,即相同元素只能添加一个,也需要重写hashCode方法才能保证相同
- HashSet作为Set接口的主要实现类,线程不安全,可以存储null值
4.1.添加元素的过程:以HashSet为例
向HashSet中添加元素a,首先调用元素a所在类的hashCode方法,计算元素a的哈希值,此哈希值接着通过某种算法计算出在HashSet底层数组中的存放位置(即索引位置),判断数组此位置上是否已经有元素
如果此位置上没有其他元素,则元素a添加成功
如果此位置上有其他元素b(或以链表形式存在的多个元素),则比较元素a与元素b的hash值,如果hash不相同,则元素a添加成功,如果hash值相同,进而需要调用元素a所在类的equals方法,equals方法返回true,则元素a添加失败,equals返回false,则元素a添加成功
对于添加成功的情况而言:元素a与已经存在索引位置上的数据以链表的方式存储
JDK7:元素a放到数组中,指向原来的元素
JDK8:原来的元素在数组中,指向元素a
总结:“七上八下”
HashSet底层:数组加链表
要求:
- 向Set中添加的数据,其类一定要重写hashCode()和equals()
- 重写的hashCode()和equals()方法,尽可能保证一致性(相等的对象必须具有相同的散列吗)
- 用作eqauls()方法比较的Field,都应该用来计算hashCode值
HashSet底层使用HashMap:

4.2.LinkedHashSet
LinkedHashSet作为HashSet的子类,在添加数据的同时,每个数据还维护两个引用,用于记录此数据前一个与后一个数据
优点:对于比较频繁的遍历操作,使用LinkedHashSet要高于HashSet
4.3.TreeSet
向TreeSet中添加的数据,要求是相同类的对象
两种排序方式:自然排序(Comparable)、定制排序(Comparator)
自然排序中,TreeSet根据Comparable接口的compareTo方法比较是否相同,而不是根据equals判断是否相同
// 其中User实现Comparable接口
TreeSet<User> treeSet = new TreeSet<>();
treeSet.add(new User("Tom", 12));
treeSet.add(new User("Jerry", 32));
treeSet.add(new User("Jim", 2));
treeSet.add(new User("Mike", 65));
treeSet.add(new User("Jack", 33));
定制排序中,在TreeSet构造器中传入Comparator实现类参数,此时TreeSet会根据Comparator中的compare方法进行比较
Comparator com = new Comparator() {
@Override
public int compare(Object o1, Object o2) {
if (o1 instanceof User && o2 instanceof User) {
User user1 = (User) o1;
User user2 = (User) o2;
return user1.getName().compareTo(user2.getName());
}
throw new RuntimeException("输入的数据类型不匹配");
}
};
TreeSet<User> treeSet = new TreeSet<>(com);
5.Map接口

HashMap作为主要实现类,效率高,线程不安全,可以存储null的key和value
LinkedHashMap在HashMap的基础上添加双向引用,保证在遍历map元素时,可以按照添加的顺序实现遍历,原因:在原有的HashMap底层结构基础上,添加一对指针,指向前一个和后一个元素,对于频繁的遍历操作,此类执行效率高于HashMap
TreeMap可以按照添加的键值对进行排序,实现排序遍历(按照key进行自然排序或者定制排序),底层使用红黑树
Properties常用于处理配置文件,key和value都是String类型
HashMap在JDK1.7及之前,使用数组+链表的形式,在JDK1.8中使用数组+链表+红黑树的格式
Hashtable作为古老实现类,效率低,线程不安全,不能存储null的key和value
6.Collections工具类
reverse(List) 反转list中的元素顺序
shuffle(List) 对list集合元素进行随机排列

浙公网安备 33010602011771号