Java中的数组创建时就需要给定空间,故是不可修改的。但是在实际生活中的很多情况都是无法确定数量,所以这些数据不能有数组来保存,这个时候就需要使用集合。
Java在编程的时候,可以使用对象数组来存储多个对象,但数组长度是不可变化,而且一旦在初始化数组时就指定了数组长度,那么这个数组长度就是不可变的。如果需要保存数量变化的数据,数组就有点无能为力了。
目录
假如有一个成绩单(姓名,成绩),用一个数组存储姓名,一个数组存储成绩,a[0]存姓名、b[0]存成绩。看似没有问题,但是这两者没有保存映射关系。数组无法保存具有映射关系的数据,如成绩表为语文——79,数学——80,这种数据看上去像两个数组,但这两个数组的元素之间有一定的关联关系。为了保存数量不确定的数据,以及保存具有映射关系的数据(也被称为关联数组),Java提供了集合类。集合类主要负责保存、盛装其他数据,因此集合类也被称为容器类。
java中的集合就是一个容器,来存储Java类中的对象。
以装水的容器水瓶来说,可以对水进行倒出和倒入,很难在容器内进行操作;
以装衣服的容器衣柜来说,可以在衣柜里对衣服进行操作(查找、排序等),也可以将衣服取出和塞入。
Java集合类的功能比这个容器的功能还要多,其中有些是方便进行查找,有些是方便进行排序,有些是方便进行取出取入。(集合的安全是利用泛型来使集合更加安全)
Java 所有的集合类都位于 java.util 包下,提供了一个表示和操作对象集合的统一构架,包含大量集合接口,以及这些接口的实现类和操作它们的算法。
集合类和数组不一样,数组元素既可以是基本类型的值,也可以是对象(实际上保存的是对象的引用变量),而集合里只能保存对象(实际上只是保存对象的引用变量,但通常习惯上认为集合里保存的是对象)。
Collection接口和Map的介绍
集合的类型分为:Collection 和 Map 。它们是 Java 集合的根接口,这两个接口又包含了一些子接口或实现类。
Iterator 接口 | 集合的输出接口,主要用于遍历输出(即迭代访问)Collection 集合中的元素,Iterator 对象被称之为迭代器。迭代器接口是集 合接口的父接口,实现类实现 Collection 时就必须实现 Iterator 接口。 |
Collection 接口 | 是 List、Set 和 Queue 的父接口,是存放一组单值的最大接口。 所谓的单值是指集合中的每个元素都是一个对象。一般很少直接 使用此接口直接操作。 |
Queue 接 口 | Queue 是 Java 提供的队列实现,有点类似于 List。 |
Dueue 接 口 | 口 是 Queue 的一个子接口,为双向队列。 |
List 接口 | 是最常用的接口。是有序集合,允许有相同的元素。使用 List 能 够精确地控制每个元素插入的位置,用户能够使用索引(元素在 List 中的位置,类似于数组下标)来访问 List 中的元素,与数组 类似。 |
Set 接口 | 不能包含重复的元素。 |
Map 接口 | 是存放一对值的最大接口,即接口中的每个元素都是一对,以 key→value 的形式保存。 |
HashSet | 为优化査询速度而设计的 Set。它是基于 HashMap 实现的, HashSet 底层使用 HashMap 来保存所有元素,实现比较简单 |
TreeSet | 实现了 Set 接口,是一个有序的 Set,这样就能从 Set 里面提 取一个有序序列 |
ArrayList | 一个用数组实现的 List,能进行快速的随机访问,效率高而且 实现了可变大小的数组 |
ArrayDueue | 是一个基于数组实现的双端队列,按“先进先出”的方式操作集 合元素 |
LinkedList | 对顺序访问进行了优化,但随机访问的速度相对较慢。 |
HsahMap | 按哈希算法来存取键对象 |
TreeMap | 可以对键对象进行排序 |
除此之外还有很多的方法,可自行参考 API 文档来查阅这些方法的详细信息。无需硬性记忆这些方法,可以和实际生活结合记忆。
集合类就像容器,现实生活中容器的功能,就是添加对象、删除对象、清空容器和判断容器是否为空等,集合类为这些功能都提供了对应的方法。
Java集合主要由2大类型构成,分别是Collection和Map,其中Collection和Map分别是对应接口分支中的顶层接口。
Collection主要有三个子接口:List(列表)、Set(集)、Queue(队列)。
List、Queue中的元素有序可重复,而Set中的元素无序不可重复。
本章我们主要学习List;List中又主要有ArrayList、LinkedList两个实现类;所以,我们来理解ArrayLists和LinkedList
ArrayList
public static void main(String[] args)
{
//不能直接实例化List,因为List是接口,如果实例化就会重写包含的方法
ArrayList List1 = new ArrayList();//创建集合List1
ArrayList List2 = new ArrayList();//创建集合List2
List1.add(1);//集合中添加int类型数据
List1.add("1");//集合中添加char类型数据
List1.add("12345");//集合中添加String类型数据
System.out.println("List1中的内容:"+List1.toString());//输出集合的内容(toString)
List2.addAll(List1);//将List1中的全部元素添加到List2
List2.add("Lungcen");//集合中添加String数据
// Iterator iterator = new Iterator() 这是接口,不能new(实例化)
Iterator iterator = List2.iterator();//输出集合的内容(迭代器)
System.out.print("List2中的内容:");
while(iterator.hasNext())//判断是否又下一个
{
System.out.print(iterator.next()+" ");//输出内容
}
List2.remove(1);//传入的是逻辑位置,对应的存储位置是2
System.out.println("\nList2删除第二个位置的数后:"+List2.toString());//输出集合内容
List2.removeAll(List1);
System.out.println("List2删除与List1相同的内容后:"+List2.toString());//输出集合内容
}
LinkedList
public static void main(String[] args)
{
ArrayList list = new ArrayList();
LinkedList list1 = new LinkedList();
list.add("123456");
list1.add(1);
//list.get(0)获得list表逻辑位置为0的数据
list1.add(list.get(0));
System.out.println("list1中的全部元素:"+list1.toString());
list1.addFirst("一");//将元素添加到第一个位置
list1.addLast("Lungcen");//将元素添加到最后一个位置
System.out.println("list1中的第一个元素:"+list1.element());
System.out.println("list1修改后的全部元素:"+list1.toString());
Object object = list1.clone();//List的克隆功能
System.out.println("object克隆list1后的元素:"+object.toString());
list1.pop();//弹栈,将第一个元素弹出去
System.out.println("弹栈后List1的元素:"+list1.toString());
}
两者的区别
ArrayList 与 LinkedList 都是 List 接口的实现类,因此都实现 了 List 的所有未实现的方法,只是实现的方式有所不同。
ArrayList 是基于动态数组数据结构的实现,访问元素速度优 于 LinkedList。
LinkedList 是基于链表数据结构的实现,占用 的内存空间比较大,但在批量插入或删除数据时优于 ArrayList。
对于快速访问对象的需求,使用 ArrayList 实现执行效率上会 比较好。需要频繁向集合中插入和删除元素时,使用 LinkedList 类比 ArrayList 类效果高。
不同的结构对应于不同的算法,有的考虑节省占用空间,有的 考虑提高运行效率,对于程序员而言,它们就像是“熊掌”和“鱼 肉” ,不可兼得。
高运行速度往往是以牺牲空间为代价的,而 节省占用空间往往是以牺牲运行速度为代价的。 ArrayList 查找快,修改慢 LinkedList 修改快,查找慢