集合框架 之 List 集合 - 深度解析
集合框架简介
集合框架是为表示和操作多个对象而规定的一种统一的标准体系结构。
任何集合框架都包含三大块内容:
对外的接口、接口的实现和对集合运算的算法。
接口:即表示集合的抽象数据类型,接口提供了让我们对集合中所表示的内容进行单独操作的可能。
实现: 也就是集合框架中接口的具体实现。实际它们就是那些可复用的数据结构。
算法:在一个实现了某个集合框架中的接口的对象身上完成某种有用的计算方法,如查找、排序等。
┻╰(o‵▽′o)╯ ,各位看官是不是感觉有点子迷迷糊糊呢,没关系,我们接着往下看。
ennn,我的理解是,集合就是 Java API 所提供的一系列类,可以用于动态存放多个对象——集合只能存对象。
例如:存一个 int 型数据 1放入集合中,其实它是自动转换成 Integer 类后存入的,Java中每一种基本类型都有对应的引用类型。
jdk 1.5开始,集合全部用泛型进行的重写,是一种数据安全的用法。
数据过多可以用对象进行存储,对象过多可以用集合来进行存储。
然而,存储数据的方式(数据结构)各有不同,所以存储的容器也就分为多种,从而,形成了集合框架这一体系。
Java的集合框架从整体上可以分为两种:
- 1、Collection接口:该接口下的所有子孙均存储的是单一对象
- 2、Map接口 :该接口下的所有子孙均存储的是key-value(键值对)形式的数据
另外还有三个分支,均是为上述服务的。
- Iterator(迭代器):主要用于遍历Colleciton接口的及其子类而设计。
- Comparator(比较器): 在集合中存储对象时候,用于对象之间的比较
- Collecitons 是工具类:(注意:该类名带个s,一般就表示工具类。)里面提供了N多静态方法,来对Colleciton集合进行操作。
Collection 方法
Collection 表示一组对象,这些对象称为 collection 的元素。一些 collection 允许有重复的元素,而另一些则不允许。一些 collection 是有序的,而另一些则是无序的。
迭代器
集合框架中提供了一个内部类专门操作集合中的元素,这个内部类就是迭代器。
有兴趣的看官,可以去看一下迭代器的原理 !
集合框架 List
集合框架 ArrayList
List集合相对于collection集合所特有的方法:
凡是可以操作下标的方法,都是该特有的方法。(ArrayList 集合中的元素有序,且有下标)
如下:(index-下表)
增
Add(index,element)
Add(index,Collection)
删
Remove(index)
改
Set(index,element)
查
Get(index)
subList(from,to)
listIterator()
index(element)
ArrayList 特有迭代器
list 集合所特有的迭代器:ListIterator是Iterator的子接口
在迭代时,不可以通过集合对象的方法操作集合中的元素;
因为会发生并发修改异常(ConcurrentModificationException)。
所以,在迭代时,只能通过迭代器来操作元素,Iterator的方法是有限的,Iterator只提供了判断、取出、删除的操作。如果想要有其他的操作,如添加、修改等,就需要使用其子接口ListIterator,该接口只能通过list集合的listIterator方法来获取。
运行结果:
因为它有指针,通过指针往下移!!!
List 集合调优,增长因子1.5倍,认证如下:
运行效果:
那么,怎么能进行集合调优呢?
我们可以改变集合的初始容量,来减少改变容器长度的次数
判断list 集合中元素是否相同:依据的是元素的equals方法。
Contains调用了equals
Remove调用了equals
字符串去重:
list 中存储的是字符串,而string的equals方法就是比的字符串的值
引用数据类型去重:(以人为对象,有姓名、年龄属性)
思路:
-
将原有的集合遍历
-
遍历后的元素需要存放到新的集合中
-
存放前做一个字符串的判断
步骤:
-
1.实例化一个新集合
-
2.遍历出之前集合里面的所有元素
-
3.边遍历边判断,如果新集合里面的元素与旧集合里面的元素不相等, 就将该元素加入新集合。
底层源码:
集合list中remove方法调用时,调用了equals方法验证
ArrayList 线程不同步,查看源码:
集合框架 Vector
Vector底层实际上就是实现了一个Object类型的数组
1、表面上把数据存储到Vector对象中,实际上底层还是把数据存储到Object数组中的
2、数组的元素类型是Object,意味着集合中只能存储任意类型的对象
3、集合中存储的对象,都存储的是对象的引用,而不是对象(数据)本身
Vector 线程同步,查看源码:
注意:以后用 ArrayList 代替 Vector,两者方法大同小异。
集合框架 LinkedList
链表的数据结构
特有方法 :
addFirst();
addLast();
获取元素但是不删除元素,如果集合中没有元素,会出现NoSuchElementException :
getFirst();
getLast();
获取元素的同时会删除元素,如果集合中没有元素,会出现NoSuchElementException:
removeFirst();
removeLast();
在jdk1.6出现了替代方法:
offerFirst()
offerLast()
peekFirst();
peekLast();
获取元素的同时会删除元素,如果集合中没有元素,会返回null
pollFirst();
pollLast();
由于是链表结构,当前节点能够记住上一个节点、以及下一个节点,所有有带First、last的方法存在。
面试常遇到的题目:用 LinkedList 模拟队列以及堆栈:
堆栈:先进后出 子弹夹
队列:先进先出 水管
模拟堆栈,代码如下:
//利用LinkedList完成具有堆栈存储结构特点的一个容器:先进后出
class Duizhan{
private LinkedList ll = new LinkedList<>();
public void push(Object obj){
ll.addFirst(obj);
}
public Object pop(Object obj){
ll.getLast();
}
public void mys{
Iterator it = ll.iterator();
while(it.hasNext()){
System.out.printIn(it.next());
}
}
}
public class LinkedListDemo{
public static void main(String[] args){
Duizhan dz = new Duizhan();
dz.push("a");
dz.push("b");
dz.push("c");
dz.push("d");
dz.push("e");
dz.mys();
}
}
运行效果如下:
模拟队列,代码如下:
//利用LinkedList完成具有队列存储结构特点的一个容器:先进先出
class Duilie{
private LinkedList ll = new LinkedList<>();
public void push(Object obj){
ll.addLast(obj);
}
public Object pop(Object obj){
ll.getLast();
}
public void mys{
Iterator it = ll.iterator();
while(it.hasNext()){
System.out.printIn(it.next());
}
}
}
public class LinkedListDemo{
public static void main(String[] args){
Duilie d = new Duilie();
d.push("a");
d.push("b");
d.push("c");
d.push("d");
d.push("e");
d.mys();
}
}
运行效果如下:
面试常见问题:
1、迭代器的remove方法与集合的remove的区别?
只需要了解迭代器在内存的运行(指针),迭代器与集合是两个对象,
如果说在迭代器中调用集合中的remove方法,会报currentModifyException错误。
2、array与ArrayList的有何区别?
array长度固定,ArrayList反之;
array一旦声明,只能放该类型的对象。
3、ArrayList与Linkedlist有何区别?
数据结构明显不同。
ArrayList的数据结构是数组存储,造成了查询速度快,增删慢,线程不同步
Linkedlist的数据结构是链表存储,造成了增删快,查询慢
vector:线程同步