集合与数组详解
一、数组与集合的基础介绍:
1.数组
(1)同一组数据类型的集合,其实数组就是一个容器。
(2)数组的好处在于可以对内部元素从0开始进行索引编号,方便对内部元素进行操作。
(3)数组的声明:
int[ ] name=new int[ X ];
int为声明数组所存储的元素类型,name为声明数组的名称,x为数组所包含具体几个元素;
另外还可以用以下方式声明数组:
int[ ] name=new int[ ]{元素1,元素2 };
int[ ] name={ 元素1,元素2 };
这样声明数组还将数组内具体元素都进行了表示。
(4)数组的具体操作
数组最常用的操作就是通过索引取元素
name[ index ],name为数组名称,index为索引,要牢记数组是固定长度固定类型的容器。
2.集合
(1)集合存放于java.util包中,集合类中存放的都是对象的引用并没有存放具体的对象内容,我们称集合中的对象就是指对象的引用, 集合中主要包含三类接口,Set(集)、List(列表)、Map(映射)。
Collection接口是集合类的根接口,Java中没有提供这个接口的直接的实现类。但是却让其被继承产生了两个接口,就是Set和List。Set中不能包含重复的元素。List是一个有序的集合,可以包含重复的元素,提供了按索引访问的方式。
Map是Java.util包中的另一个接口,它和Collection接口没有关系,是相互独立的,但是都属于集合类的一部分。Map包含了key-value对。Map不能包含重复的key,但是可以包含相同的value。
Iterator,所有的集合类,都实现了Iterator接口,这是一个用于遍历集合中元素的接口,主要包含以下三种方法:
<1>hasNext()是否还有下一个元素。
<2>next()返回下一个元素。
<3>remove()删除当前元素。
Iterator遍历数组举例:
ArrayList al = new ArrayList();
Iterator iter= al.iterator();
while(iter.hasNext()){
System.out.println(iter.next());
}
(2)下图详细介绍了集合类的接口,及接口实现类集合的特点:

<1>List(有序、可重复):List里存放的对象是有序的,同时也是可以重复的,List关注的是索引,拥有一系列和索引相关的方法,查询速度快。因为往list集合里插入或删除数据时,会伴随着后面数据的移动,所以插入删除数据速度慢。
实现List接口的类主要有ArrayList,Vector,LinkedList,其存储性能和特性如下:
ArrayList和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector由于使用了 synchronized方法(线程安全),通常性能上较ArrayList差,因此现在vector基本被ArrayList取代,而LinkedList使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。
需要注意的是:
1.对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
2.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。
3.查找操作indexOf,lastIndexOf,contains等,两者差不多。
List集合中常用的操作:
增 add(Object) 添加一个Object元素;
删 remove(index) 删除给定索引的元素;
查 get(index) 获取给定索引的元素;
改 set(index, Object) 修改给定索引的元素为Object;
<2>Set(无序、不能重复):Set集合的基本特征是不记录添加顺序,不允许元素重复,只是简单地把对象加入集合中,最常用的实现类是HashSet。
1.HashSet类直接实现了Set接口, 其底层其实是包装了一个HashMap去实现的。HashSet采用HashCode算法来存取集合中的元素,因此具有比较好的读取和查找性能。
主要特征:
不仅不能保证元素插入的顺序,而且在元素在以后的顺序中也可能变化(这是由HashSet按HashCode存储对象(元素)决定的,对象变化则可能导致HashCode变化);
HashSet是线程非安全的;
HashSet元素值可以为NULL;
2.TreeSet底层数据结构为二叉树,是一个有序的set集合,是线程不安全的;
3.LinkedHashSet是HashSet的一个子类,LinkedHashSet也根据HashCode的值来决定元素的存储位置,但同时它还用一个链表来维护元素的插入顺序,插入的时候即要计算hashCode又要维护链表,而遍历的时候只需要按链表来访问元素。
需要注意的是:
HashSet和TreeSet是Set集合中用得最多的集合。HashSet总是比TreeSet集合性能好,因为HashSet不需要额外维护元素的顺序。
LinkedHashSet需要用额外的链表维护元素的插入顺序,因此在插入时性能比HashSet低,但在迭代访问(遍历)时性能更高。因为插入的时候即要计算hashCode又要维护链表,而遍历的时候只需要按链表来访问元素。
Set集合中常用的操作:
增 add(Object) 往set中添加元素使用的是add()方法,但是在set中没有add(index , element)方法;
删 remove(Object) 删除具体的Object元素;
查(无此方法)
改(需要自己写工具类) 如下:
public Set<Object> updateSetValue(Set<Object> oldSet) {
Set<Object> newSet = new HashSet<Object>();
for (Object s : oldSet) {
if (s != "你要修改前的值") {
newSet.add(s);
} else {
newSet.add("你要修改后的值");
}
}
return newSet;
}
<3>Map(键值对、键唯一、值不唯一):Map集合中存储的是键值对,键不能重复,值可以重复。根据键得到值,对map集合遍历时先得到键的set集合,对set集合进行遍历,得到相应的值。HashMap为常用的实现类。
实现类:HashMap、Hashtable、LinkedHashMap和TreeMap
1.HashMap (底层数据结构哈希表)
HashMap是最常用的Map,它根据键的HashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度,遍历时,取得数据的顺序是完全随机的。因为键对象不可以重复,所以HashMap最多只允许一条记录的键为Null,允许多条记录
的值为Null,是非同步的(非同步就是线程不安全)
2.Hashtable (底层数据结构哈希表)
Hashtable与HashMap类似,是HashMap的线程安全版,它支持线程的同步,即任一时刻只有一个线程能写Hashtable,因此也导致了Hashtale在写入时会比较慢,它继承自Dictionary类,不同的是它不允许记录的键或者值为null,同时效率较低。
3.ConcurrentHashMap(不常使用)
线程安全,并且锁分离。ConcurrentHashMap内部使用段(Segment)来表示这些不同的部分,每个段其实就是一个小的hash table,它们有自己的锁。只要多个修改操作发生在不同的段上,它们就可以并发进行。
4.LinkedHashMap(不常使用)
LinkedHashMap保存了记录的插入顺序,在用Iteraor遍历LinkedHashMap时,先得到的记录肯定是先插入的,在遍历的时候会比HashMap慢,有HashMap的全部特性。
5.TreeMap(底层数据结构二叉树)
TreeMap实现SortMap接口,能够把它保存的记录根据键排序,默认是按键值的升序排序(自然顺序),也可以指定排序的比较器,当用Iterator遍历TreeMap时,得到的记录是排过序的。不允许key值为空,非同步的;
Map集合中常用的操作:
添加 put(key,value):当存储的键相同时,新的值会替换老的值,并将老值返回。如果键没有重复,返回null。
删除 clear():清空
remove(key) :删除指定键。
判断 boolean isEmpty():
boolean containsKey(key):是否包含key
boolean containsValue(value) :是否包含value
取出 int size():返回长度
get(key) :通过指定键获取对应的值。如果返回null,可以判断该键不存在。当然有特殊情况,就是在hashmap集合中,是可以存储null键null值的。
Collection values():获取map集合中的所有的值。
map元素的遍历:
HashMap map = new HashMap();
map.put("ZH", "中国");
map.put("EN", "英国");
map.put("ZH1", "中华人名共和国");
Set<Map.Entry<String,String>> set = map.entrySet();
for (Entry<String, String> entry : set) {
System.out.print(entry.getKey()+"----");
System.out.println(entry.getValue());
}
输出结果:
EN----英国
ZH----中国
ZH1----中华人名共和国
二、数组与集合的区别:
1、数组声明了它容纳的元素的类型,而集合不声明。
2、数组是静态的,一个数组实例具有固定的大小,一旦创建了就无法改变容量了。而集合是可以动态扩展容量,可以根据需要动态改变大小,集合提供更多的成员方法,能满足更多的需求。
3、数组不论是效率还是类型检查都是最好的。
4、数组的存放的类型只能是一种,集合存放的类型可以不是一种(不加泛型时添加的类型是Object);
5、数组是java语言中内置的数据类型,是线性排列的,执行效率或者类型检查,都是最快的,ArrayList就是基于数组创建的容器类。
6、数组最大的弱点就是功能太弱小,所有才会有其他容器的出现。

浙公网安备 33010602011771号