文章目录
一、从数组引入到集合
1、集合与数组存储数据概述
集合、数组都是对多个数据进行存储操作的结构,简称Java容器。
说明:此时的存储,主要指的是内存层面的存储,不涉及到持久化的存储(.txt,.jpg,.avi,数据库中)
什么是集合
集合类存放于java.util包中,主要有list(列表), set(集), map(映射),集合存放的都是对象的引用而非对象本身,所以我们称集合中的对象就是集合中对象的引用。简而言之,集合就是存放数据对象引用的容器。
2、数组存储的特点
一旦初始化以后,其长度就确定了。
数组一旦定义好,其元素的类型也就确定了。我们也就只能操作指定类型的数据了。
比如:String[] arr;int[] arr1;Object[] arr2;
3、数组存储的弊端
一旦初始化以后,其长度就不可修改。
数组中提供的方法非常有限,对于添加、删除、插入数据等操作,非常不便,
且时效率不高,同时无法直接获取存储元素的个数。
获取数组中实际元素的个数的需求,数组没有现成的属性或方法可用
数组存储数据的特点:有序、可重复。对于无序、不可重复的需求,不能满足。
4、集合存储的优点
解决数组存储数据方面的弊端,Java集合类可以用于存储数量不等的多个对象,还可以用于保存具有映射关系的关联数组。
5、数组与集合的比较
(1).数组的特点
a. 数组长度固定,声明好的数组只能存储同类型的数据,并且内存空间固定不变
b. 数组本质上就是一段连续的内存空间,用于记录多个类型相同的数据
c. 插入和删除操作的时候不方便,可能会移动大量的元素导致效率太低
d. 支持下标访问,可以实现随机访问。
e. 数组中的元素可以是基本数据类型,也可以是引用数据类型。
但是数组一旦声明后,其存储的数据类型就固定不变了。
(2). 集合的特点
a. 集合内存空间可以不连续,数据类型可以相同(泛型集合),也可以不相同(非泛型集合)
b. 集合的长度是动态的,即集合的内容空间可以动态调整
c. 集合的插入删除操作可以不移动大量元素,比如LinkedList集合的插入与删除
d. 对于集合而言,部分集合支持下标访问,部分集合不支持
e. 集合中的元素必须是引用数据类型
二、集合
1. 单列集合架构图
单列集合继承树
2. Collection集合
Collection接口是最基本的集合接口,其中包含了单列集合中所有使用的方法,一个Collection代表一组Object,即Collection的元素(Elements)。它不提供直接的实现,Java SDK提供的类都是继承自Collection的“子接口”如List和Set
。Collection所代表的是一种规则
,它所包含的元素都必须遵循一条或者多条规则。如有些允许重复而有些则不能重复、有些必须要按照顺序插入而有些则是散列,有些支持排序但是有些则不支持。
在Java中所有实现了Collection接口的类都必须提供两套标准的构造函数
,一个是无参,用于创建一个空的Collection,一个是带有Collection参数的有参构造函数,用于创建一个新的Collection,这个新的Collection与传入进来的Collection具备相同的元素。
2.1 Collection集合的API
Colleaction代表着集合框架的这种数据形式,拥有方法如下
1、添加
add(Object obj) 添加一个元素obj到本集合中
addAll(Collection coll);将集合coll中的元素全部添加进本集合中
2、获取有效元素个数
int size()
3、清空集合
void clear()
4、判断是否为空集合
boolean isEmpty()
5、是否包含某个元素
boolean contains(Object obj): 是否包含某个对象,是通过元素的equals方法来判断是否是同一个对象
boolean containsAll(Collection c):是否包含某个集合,也是调用元素的equals方法来比较的。用两个两个集合的元素逐一比较
6、删除
boolean remove(Object obj):通过元素的equals方法判断是否是要删除的那个元素。只会删除找到的第一个元素
boolean removeAll(Collection coll):取当前集合的差集
取两个集合的交集
boolean retainAll(Collection c):把交集的结果存在当前的集合中,不影响c
7、集合是否相等
boolean equals(Object obj)
8、转换成对象数组
Object [] toArray() 将集合中的元素以数组形式然后返回
<T> T[] toArray(T[] a); //上一个方法的泛型形式
9、获取集合对象的哈希值
hashCode()
10、遍历
iterator():返回迭代器对象,用于集合遍历
注意事项:
ArrayList直接转化为一个String数组
如果要把一个List直接转化为Object数组,则可以直接使用Object[] o = list.toArray();
如果要转化为String数组,则有以下两种方式:
方法一、String[] arr = new String[list.size]; list.toArray(arr);//此时arr就有了list中的值了
方法二、String[] arr = (String[])list.toArray(new String[0]);
扩展;
*All方法参数的类型都为Collection ,大多数方法都是返回boolean类型值,Collection 接口用于表示任何对象或元素组。想要尽可能以常规方式处理一组元素时,就使用这一接口。(如,可以直接add(100),可以是普通数据类型)。
容器类对象在调用remove,contains等方法时需要比较对象是否相等地,这会涉及到对象类型的equals方法和hashcode方法。即,相等的对象应该有相等的hashcode.当然,如果是自定义的类型,需要重写这两个方法。
2.2 Collection的循环遍历
拓展:如何遍历Collection中的每一个元素?使用迭代器,迭代器详解见后续文章
不论Collection的实际类型如何,它都支持一个iterator()的方法,该方法返回一个迭代子,使用该迭代子即可逐一访问Collection中每一个元素。典型的用法如下:
Iterator iterator = col.iterator();//获取迭代器对象
hasNext(): 判断游标右边是否还有下一个元素,默认游标都在集合的第一个元素之前。
注意:此时只是判断是否有下一个元素,并不移动指针。
while(iterator.hasNext()){
//next():①指针下移 ②将下移以后集合位置上的元素返回
Object next = iterator.next();
System.out.println("next="+next);
}
2.3 Collection与两个子接口List与Set的特点
2.3.1 Collection特点
-
Collection 接口是List、Set和Queue接口的父接口,该接口里定义的方法既可用于操作Set集合,也可用于操作List和Queue集合。
-
JDK不提供此接口的任何直接实现,而是提供更具体的子接口(如:Set和List实现)。
-
在Java5之前,Java集合会
丢失
容器中所有对象的数据类型,把所有对象都当成Object类型处理;从JDK5.0增加了泛型之后,Java集合可以记住
容器中对象的数据类型。
2.3.2 List特点
- 元素
有序
(即添加顺序和取出顺序一致),且可重复
,即允许重复的对象。 - 是一个有序容器,保持了每个元素的插入顺序,输出的顺序就是插入的顺序。
- List集合中的每个元素都有其对应的顺序索引,即
支持索引
。List容器中的每个元素都对应一个整数型的序号记载其在容器中的位置
,可以根据序号存取容器中的元素。 可以插入多个null元素
。- 常用的实现类有 ArrayList、LinkedList 和 Vector。ArrayList 最为流行,它提供了使用索引的随意访问,而 LinkedList 则对于经常需要从 List 中添加或删除元素的场合更为合适。
- 向Collection接口的实现类的对象中添加数据obj时,要求obj所在类要
重写equals()
.
2.3.3 Set特点
- 不允许出现重复对象,利用这个特性可以对集合中的数据去重
- 是一个无序集合,存储元素和取出元素的顺序有可能不一致。你无法保证每个元素的存储顺序,TreeSet通过 Comparator 或者 Comparable 维护了一个排序顺序。
- 只允许一个 null 元素
- Set 接口最流行的几个实现类是 HashSet、LinkedHashSet 以及 TreeSet。最流行的是基于 HashMap 实现的 HashSet;TreeSet 还实现了 SortedSet 接口,因此 TreeSet 是一个根据其 compare() 和 compareTo() 的定义进行排序的有序容器。
set无序的理解
set中不包含重复的元素,也就是说set中不存在两个这样的元素a1.equals(a2)结果为true。又因为Set接口提供的数据结构是数学意义上的集合概念的抽象,因此他支持对象的添加和删除。
无序性:不等于随机性。存储的数据在底层数组中并非照数组索引的顺序添加,而是根据数据的哈希值决定的。
不可重复性:保证添加的元素照equals()判断时,不能返回true.即:相同的元素只能添加一个。
list有序的理解
List接口继承了Collection接口以定义一个允许重复项的有序集合。
一般有2种List,一种是基本的ArrayList,其优点在于随机访问元素,另一种是更强大的LinkedList,他并不是为了快速随机访问而设计的,而是具有一套更通用的方法。
3. List集合
3.0 List集合
List接口为Collection直接接口。List所代表的是有序的Collection,即它用某种特定的插入顺序来维护元素顺序。用户可以对列表中每个元素的插入位置进行精确地控制,同时可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。实现List接口的集合主要有:ArrayList、LinkedList、Vector、Stack。
3.0.1 List常用的API
List接口继承Collection接口,故可以使用Collection接口的所有方法,这里仅仅列举List集合相对Collection集合特有的方法
ListIterator listIterator(); 获取一个ListIterator迭代器,该迭代器是List集合独有的,功能较Iterator更加强大
boolean add(int index, Object element) :在指定位置插入指定数据,原来位置的数据会顺次往后移,没有返回值
boolean addAll(int index, Collection<? extends E> c) :在指定位置插入指定的集合,原来位置的数据会顺次往后移,没有返回值
Object get(int index):得到指定位置的元素,index从0开始
Object set(int i, Object element):替换指定位置的元素,返回值是更新的元素。
int indexOf(Object obj);在集合中顺序查找元素 ,obj如果在集合中存在 ,则返回所查找元素的下标,如果不存在则返回-1
int lastIndexOf(Object obj);在集合中倒序查找元素 ,obj如果在集合中存在 ,则返回所查找元素的下标,如果不存在则返回-1
void forEach(Consumer<? super T> action); 循环遍历集合中每一个元素
void sort(Comparator<? super E> c); 传入一个定制排序器,对集合中的元素进行排序
List subList(start,end);sublist函数是Java中List接口中的一个方法,用于截取原List中指定区间的元素,
返回一个新的List,其中包含原List中指定区间的所有元素。该函数的指定区间范围是左闭右开的区间。
Object remove(int index); 删除指定索引处的元素,返回的是被移除的元素;
boolean removeIf(Predicate<? super E> filter