5.使用线程安全可遍历映射
本范例用到的接口和实现类:ConcurrentNavigableMap接口及其实现类。实现这个接口的类以如下两部分存放元素
1.一个键值(key),它是元素的标示并且是唯一的。
2.元素其他部分数据。
ConcurrentSkipListMap类实现了ConcurrentNavigaleMap接口。从内部实现机制来讲,它使用了一个Skip List来存放数据。
Skip List是基于并发列表的数据结构,效率与二叉树相近。通过该类就可以得到一个数据结构,比有序列表在添加,搜索,或者删除元素耗费更少的
访问时间。
当你插入元素到映射中时,ConcurrentSkipListMap接口类使用键值阿里排序所有元素,除了提供返回一个具体元素的方法之外,这个类也提供获取子映射的方法 。
ConccurentNavigableMap<String,Contact> submap = map.submap(String from ,String to );
使用方法:
firstEntry():返回一个Map.Entry对象,含有映射中的第一个元素。这个方法不会从映射中移除元素。Map.Entry对象包含键值和元素。使用getValue()方法就能获取元素,
使用getKey()方法就能够获取元素的键值。
headMap(K toKey):K是在ConcurrentSkipListMap对象的泛型参数里用到的键。这个方法返回映射中所有键值小于参数值toKey的子映射。
tailMap(K fromKey):K是在ConcurrentSkipListMap对象的泛型参数里用到的键,返回映射中所有键值待遇参数值fromKey的子映射。
putIfAbsent(K key,V value): 如果映射中不存在键key,那么就将Key和value保存到映射中。
polllLastEntry():返回并移除映射中的最后一个Map.Entry()对象。
replace(K key , V value):如果映射中已经存在键Key,则用参数中的value替换现有的值。
实例代码:
public class Contact {
private String name;
private String phone;
public Contact(String name, String phone) {
super();
this.name = name;
this.phone = phone;
}
public String getName() {
return name;
}
public String getPhone() {
return phone;
}
}
/**
*
* @author fcs
* @date 2015-6-21
* 描述:使用线程安全可遍历映射
* 说明:
*/
public class Task implements Runnable{
private ConcurrentSkipListMap<String,Contact> map;
private String id;
public Task(ConcurrentSkipListMap<String, Contact> map, String id) {
this.map = map;
this.id = id;
}
@Override
public void run() {
for(int i = 0;i< 1000;i++){
Contact contact = new Contact(id,String.valueOf(i+1000));
//这里如果插入的键值已经存在,就用新插入的值覆盖已有的值
map.put(id+contact.getPhone(), contact);
}
}
}
public class Main {
public static void main(String[] args) {
ConcurrentSkipListMap<String,Contact> map = new ConcurrentSkipListMap<String, Contact>();
Thread threads []= new Thread[25];
int counter = 0;
for(char i = 'A';i<'Z';i++){
Task task = new Task(map,String.valueOf(i));
threads[counter] = new Thread(task);
threads[counter].start();
counter++;
}
//使用join()方法等待所有线程执行完成。
for(int i = 0;i< 25;i++){
try {
threads[i].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.printf("Main: Size of the map: %d\n",map.size());
Map.Entry<String, Contact> element; //map.entry是map接口的一个内部接口,它的作用就是包装一个map的节点,这个节点
//封装了key,value以及别的值(比如hashmap中的哈希码和next指针)
Contact contact;
//使用firstEntry()方法获取map中的第一个元素
element = map.firstEntry();
contact = element.getValue();
System.out.printf("Main: First Entry: %s: %s\n",contact.getName(),contact.getPhone());
//使用lastEntry()方法获取map中的最后一个元素
element = map.lastEntry();
contact = element.getValue();
System.out.printf("Main: Last Entry: %s %s\n",contact.getName(),contact.getPhone());
//使用subMap()取得map的一个子映射,将这些数据输出到控制台。
System.out.println("Main: Submap from A1996 to B1002 :");
//该方法返回含有映射部分元素的ConcurrentNavigableMap对象。
ConcurrentNavigableMap<String, Contact> submap = map.subMap("A1996", "B1002");
do{
element = submap.pollFirstEntry();
if(element!=null){
contact = element.getValue();
System.out.printf("%s: %s\n",contact.getName(),contact.getPhone());
}
}while(element != null);
}
}
运行结果: