Java集合框架
我们为什么要使用集合框架?
我们平常在存储多个数据的时候,通常会使用数组。但是数组的话则会有一些限制:
- 数组的长度是固定的。
- 数组只能存储同一个数据类型的内容,无法存储多个不同的数据类型。
所以集合框架就应运而生了。集合的话,简单理解:就是一个长度可以改变,可以保持任意数据类型的动态数据。
本身在数据结构中,就存在一个叫做集合的概念。但是我们这里所说的Java集合是Java语言对这种数据结构的具体实现。
Java中的集合并不是由一个类来完成的,而是由一组接口和类来构成了一个框架体系,大致分为三层:
- 最上层:一组接口
- 中间:接口的实现类
- 最下层:算法
Java集合框架中的接口
这里的框架中的接口是代表了集合的抽象数据类型。 我们比较常见的接口包括:
- Collection:集合框架中最基础的接口,最顶层的接口,我们一般不会去使用该接口。
- List:Collection接口的一个子接口。存储有序、不唯一的对象,最常用的接口。
- Set:Collection接口的一个子接口。存储无序、唯一的对象(和List刚好相反)
- Map:独立于Collection的一个接口,也是最顶层的接口,相当于和Collection是兄弟俩。存储了键值对象,提供了健到值得映射。
- Iterator:输出集合元素的接口,一般适用于无序集合,从前往后输出。
- ListIterator:Iterator子接口,可以双向输出集合中的元素。
- Enumeration:一个传统的输出接口,但是已经被Iterator取代了。
- SortedSet:Set的子接口,可以对集合中的元素进行排序。
- SortedMap:Map的子接口,可以对Map集合中的元素进行排序
- Queue: 队列接口,实现队列操作。
- Map.Entry:Map的内部接口,可以用来描述Map中存储的一组键值对元素。
Collection接口
Collection collection = new Collection() {
@Override
// 获取集合的长度
public int size() {
return 0;
}
@Override
// 判断集合是否为空
public boolean isEmpty() {
return false;
}
// 判断集合是否存在某个对象
@Override
public boolean contains(Object o) {
return false;
}
@Override
// 实例化Iterator接口,遍历集合。
public Iterator iterator() {
return null;
}
@Override
// 将集合转换为一个Object数组
public Object[] toArray() {
return new Object[0];
}
@Override
// 将集合转为一个指定数据类型的数组
public Object[] toArray(Object[] a) {
return new Object[0];
}
@Override
// 添加元素
public boolean add(Object o) {
return false;
}
@Override
// 删除元素
public boolean remove(Object o) {
return false;
}
@Override
// 判断集合中是否存在另一个集合的所有元素
public boolean containsAll(Collection c) {
return false;
}
@Override
// 从集合中添加某个集合的所有元素
public boolean addAll(Collection c) {
return false;
}
@Override
// 从集合中删除某个集合中的所有元素
public boolean removeAll(Collection c) {
return false;
}
@Override
// 剔除不在集合里面的元素
public boolean retainAll(Collection c) {
return false;
}
@Override
// 清除集合中的所有元素
public void clear() {
}
}
除此之外还有:
-
boolean equals(Collection c) // 判断两个集合是否相等
int hashCode() // 返回集合的哈希值
Collection的子接口
- List:存放有序、不唯一的元素
- Set:存放无序、唯一的元素
- Queue:队列接口。
List接口
Iist是Collection的子接口,继承了Collection的所有方法
同时List的常用扩展方法:
- T get(int index):通过下标返回集合中对应位置的元素。
- T set(int index, T element):在集合中指定位置存入对象
- int indexOf(Object o):从前向后查找某个对象在集合中的位置
- int lastIndexOf(Object o):从后向前查找某个对象在集合中的位置
- ListInterator
listIterator:实例化ListIterator接口,用来遍历List集合 - List
subList(int fromindex, intoIndex):通过下标截取List集合
List接口的实现类
- ArrayList:以数组的数据结构来进行存储集合,是开发中使用频率最高的List实现类,实现了长度可变的数组。由于是数组,所以在内存中分配连续的空间,所以读取快,增删慢
- LinkedList:以链表的数据结构来进行存储集合
- LinkedList和Stack都有pop方法,都是取出集合中的第一个元素,但是两者的顺序是相反的,Stack是栈,所以是后进先出,而LinkedList是先进先出。
- LinkedList底层实现了Deque接口,而Deque是Queue的子接口,Queue就是队列,实现了队列的数据结构,实际开发中不能直接实现。
通常情况下,我们使用ArrayList相对比较多。因为ArrayList是采用的数组的数据结构来进行的存储集合。而通过数据结构的学习我们了解到线性表(数组)的存储方式对查询操作是很快的,但是不利于增删等操作。而链表恰恰相反。
我们在日常使用的过程中,一般都是从数据库中查找出来相应的对象数据,然后返回给前端页面。因此使用查找的操作也非常多。这也是为何ArrayList的使用频率远大于LinkedList的原因。
-
Vector:线程安全,比ArrayList出现的都早。但是效率低。
- 实现线程安全的方式:直接通过synchronized修饰方法来完成
- 多线程环境下,实现线程安全可以保证程序不会出现异常。但是因为JMM的特性,同样会出现多线程的一系列问题。
- JMM内存模型在多线程环境下会创造多个多个工作内存,然后在工作内存写入主内存的时候就会出现错误。
-
ArrayList:基于数组的实现,非线程安全,效率高。
-
Stack:Vector的子类,实现了栈的子接口。
- push方法,入栈。和add方法相同。
- peek方法,取出栈顶元素
- pop方法:取出栈顶元素
- 两个方法的区别:pop方法是直接取出来。而peek方法是复制一份取出来,取出之后栈里面同样还有该元素。

浙公网安备 33010602011771号