Java类集出现在JDK1.2,主要是为了解决数组的定长问题,说得简单点,类集其实就是一个动态数组。
在类集的总体结构中,最重要的两个接口是Collection接口与Map接口。
1.Collection接口:单个元素存储的最顶层父接口
- Collection接口的结构:
Collection接口只定义了一个存储数据的标准,但是无法区分存储类型。
因此我们往往使用Collection的两个子接口,List允许数据重复,Set不允许数据重复。 - Collection接口中提供的一些核心方法:
- add(E e):添加元素
- iterator():取得迭代器(主要是为了遍历集合)
2.List接口:
List接口允许数据重复,且拓展了自己独有的两个重要方法:
- E get(int index):取得对应索引的元素
- E set(int index,E element):为对应索引的元素赋值
List接口下有三个子接口:ArrayList、Vector、LinkedList,我们来看一下这三者的区别与联系:
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable{
//初始化容量为10
private static final int DEFAULT_CAPACITY = 10;
private static final Object[] EMPTY_ELEMENTDATA = {};
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//用来存储数据的数组
transient Object[] elementData;
private int size;
//此时并不初始化
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
}
可以看出,ArrayList在调用构造方法时并不会对数组进行初始化,而是在第一次添加元素时初始化数组,默认大小为10。
public class Vector<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{ //存储元素的数组
protected Object[] elementData;
protected int capacityIncrement;
public Vector(int initialCapacity, int capacityIncrement) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
//此时进行了初始化
this.elementData = new Object[initialCapacity];
this.capacityIncrement = capacityIncrement;
}
public Vector(int initialCapacity) {
this(initialCapacity, 0);
}
public Vector() {
this(10);
}
}
而Vector在调用构造方法时就已经为数组进行了初始化。
!!!总结:ArrayList、Vector、LinkedList的区别与联系:
- 首先,ArrayList、Vector、LinkedList都是List接口下的常用子类;但ArrayList与Vector基于数组实现,LinkedList基于双向链表实现。
- ArrayList出现在JDK1.2,采用懒加载机制,在调用构造方法时并不会初始化内部数组,而在第一次添加元素时才初始化;扩容机制为1.5倍;采用异步处理,线程不安全;效率较高。
- Vector出现在JDK1.0,在调用构造方法时就初始化内部数组,默认大小为10;扩容机制为原来的2倍;采用synchronized方法上加锁,线程安全;效率较低。
- LinkedList出现在JDK1.2,线程不安全,适合频繁的在指定位置的插入与删除操作。
- Vector支持较老的迭代器Enumeration
3.Set接口:
Set接口常用子类:
- HashSet(无序存储):
a. 底层使用哈希表+红黑树
b. 允许存放null,无序存储 - TreeSet(有序存储):Comparable、Comparator接口
a. 底层使用红黑树
b. 不允许出现空值,有序存储
c. 自定义类要想保存到TreeSet中,要么实现Comparable接口,要么向TreeSet传入比较器(Compartor接口)
4.Java中实现一个类的两个对象大小比较的方式:
-
java.lang.Comparable接口(内部比较器) --> 排序接口:
1) 若一个类实现了Comparable接口,就意味着该类支持排序。
存放该类的Collection或数组,可以直接通过Collections.sort()或Arrays.sort()进行排序。
2) 实现了Comparable接口的类可以直接存放在TreeSet或TreeMap中。
3) public int compareTo(T o)
返回值三种情况:
a. 返回正数:表示当前对象大于目标对象
b. 返回0:表示当前对象等于目标对象
c. 返回负数:表示当前对象小于目标对象 -
java.util.Comparator接口(外部排序接口) --> 函数式编程接口:比较灵活
1) 若要控制某个自定义类的顺序,而该类本身不支持排序(类本身没有实现Comparable接口)。
我们可以建立一个该类的“比较器”来进行排序,比较器实现Comparator接口即可。
比较器:实现了Comparator接口的类作为比较器,通过该比较器来进行类的排序。
2) int compare(T o1,T o2)
返回值与compareTo()返回值完全一样:
a. 返回正数:表示 o1 > o2
b. 返回0:表示 o1 = o2
c. 返回负数:表示 o1 < o2