集合类以及集合框架

集合是一组复合元素的容器,用来存储,检索,控制聚合数据并提供它们之间的通信方法。

java的集合框架提供了表示和操控集合的统一架构。所有的集合框架都包含下面三个方面:


接口:即集合的抽象数据结构。接口允许我们独立地操纵集合而不用考虑集合的具体实现

实现:即接口的具体实现类。从本质上来讲,它们是可重用的数据结构

算法:即在实现了集合接口的对象上执行有用的计算,比如排序和搜索,的方法。算法是多态的:同名的方法可以被任何合适的接口实现类调用,从本质上来讲,算法是可重用的功能

 

核心集合接口封装了不同类型的集合,它们是java集合框架的基础,形成了下图所示的层级结构



从上图中可以看到,Set是一种特殊的Collection,而SortedSet是一种特殊的Set……诸如此类。

需要注意,上图中有两个不同的树,Map并不是Collection的子接口,而是一个独立的接口

所有的集合接口都是泛化的。比如下面是Collection接口的声明:

public interface Collection<E>...

“<E>”表示该接口是通用的。当我们声明一个Collection接口时,最好指定该接口包含的对象类型,以便让编译器在编译时检验输入的对象是否正确,从而减少运行时抛出的错误。

对于接口中的方法,有很多是可选择实现的,就是说,它的实现类可以实现该方法,也可以不实现,根据具体需要来决定

 

我们先来看一下核心的集合接口,对它们有一个整体的感性认识:

Collection接口:集合框架的根接口。它是集合类框架中最具一般性的顶层接口。Java平台没有提供任何该接口的直接具体实现类,但是提供了具有各种不同特性的子接口

Set接口:不允许包含重复值的集合

List接口:可索引的集合,可以包含重复值。使用该接口时我们通过索引对元素进行精准的插入和查找

Queue接口:该集合适用于组织一个队列,队列中的元素按照优先级进行处理。除了继承自Collection接口的方法,该接口还提供了另外的插入、提取和检验方法。典型的队列是符合“先进先出”(FIFO:First In,First Out)原则的,优先级队列是一种例外,它按照元素的优先级顺序排列元素。无论按照什么原则排序,队头元素总是首先被检出。每个Queue接口的实现类必须指定它的排序原则

Deque接口:与Queue的不同之处在于它是一个双端队列,在两端都能插入和移除元素,它继承并扩展了Queue接口

Map接口:提供了键值对(key/value)的映射关系的集合。关键字不能有重复值,每个关键字至多可映射一个值

SortedSet接口:以升序的原则维持着集合中的元素顺序。

SortedMap接口:以关键字升序的原则维持着集合中的元素顺序

 

以上接口的通用实现类(这里的通用实现类一般是指适用于单线程环境下的实现类,在JDK中有针对多线程并发环境下的特殊实现类)总结如下


接口

哈希表实现

可变数组实现

树实现

链表实现

哈希表+链表实现

堆实现

Set

HashSet

 

TreeSet

 

LinkedHashSet

 

List

 

ArrayList

 

LinkedList

 

 

Queue

 

 

 

LinkedList

 

PriorityQueue

Deque

 

 

 

LinkedList

 

 

Map

HashMap

 

TreeMap

 

LinkedHashMap

 

可以发现,LinkedList同时实现了List、Queue、Deque三个接口。


SortedSet接口和SortedMap接口没有在上表中列出,在上面的层次结构图中可以看到,它们分别是Set和Map的子接口,TreeSet和TreeMap就是它们的实现类

以上提到的所有通用实现类都支持为null的元素(或者键/值),不过有的只能包含一个null,有的可以包含多个null;所有通用实现类都实现了Serializable,是可序列化的对象;所有通用实现类都提供了一个clone方法用于复制对象;所有通用实现类都是线程不安全的(即是不同步的);所有通用实现类都提供了”fail-fast”机制的迭代器

关于“fail-fast”机制,来看一个实例:

Map<String,String> map = new HashMap<String,String>();  
map.put("first", "Jay");  
map.put("second","Jack");  
map.put("third", "Jim");  
  
Iterator<String> it= map.keySet().iterator();  
while(it.hasNext()){  
       System.out.println(map.get(it.next()));  
       if(map.containsKey("second")){  
              map.remove("second");  
       }  
}  

以上代码试图使用Iterator迭代Map里的键值,如果键值为“second”则删除Map中的该元素。运行一下可以发现,执行删除操作时会报java.util.ConcurrentModificationException异常,即便这是单线程。

Iterator 是工作在一个独立的线程中,并且拥有一个 mutex 锁。 Iterator 被创建之后会建立一个指向原来对象的单链索引表,当原来的对象数量发生变化时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭代的对象,所以按照 fail-fast 原则 Iterator 会马上抛出 java.util.ConcurrentModificationException 异常。


如果想要成功的执行删除操作,就需要先对Iterator进行对应的删除操作


Map<String,String> map = new HashMap<String,String>();  
map.put("first","Jay");  
map.put("second","Jack");  
map.put("third","Jim");  
  
Iterator<String> it= map.keySet().iterator();  
while(it.hasNext()){  
       System.out.println(map.get(it.next()));  
       if(map.containsKey("second")){  
              it.remove();  //先对Iterator进行删除  
              map.remove("second");  
       }  
}  


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值