13、集合2
一、HashMap和Hashtable排序
将HashMap转换成List之后才能排序,排序之后的循环输出使用list的迭代器,不能使用map的迭代器。
public class G { public static void main(String[] args) { Map<String,Integer> map=new HashMap<>(); map.put("a",1); map.put("b",2); map.put("c",3); map.put("d",4); Set<String> ss=map.keySet(); Iterator<String> it=ss.iterator(); while(it.hasNext()){ String key=it.next(); System.out.println(key+":"+map.get(key)); } List<Map.Entry<String,Integer>> list=new ArrayList<>(map.entrySet()); Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() { @Override public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) { return -(o1.getKey().compareTo(o2.getKey())); } }); Iterator<Map.Entry<String,Integer>> it1=list.iterator(); while(it1.hasNext()){ System.out.println(it1.next()); } } }
二、ConcurrentHushMap 当前HashMap
HashMap在并发编程过程中使用非同步可能导致死循环,因为插入过程不是原子操作,每个HashEntry是一个链表节点,很可能在插入的过程中,已经设置了后节点,实际还未插入,最终反而插入在后节点之后,造成链中出现环。只有一把锁,有获取意向的线程数目增加,导致大量线程处于轮询或阻塞状态。导致同一个时间段有效执行的线程的增量远不及线程总体增量。
HashTable因为内部是采用synchronized来保证线程安全的,但在线程竞争激烈的情况下HashTable的效率下降的很快,因为synchronized关键字会造成代码块或方法成为临界区(对同一个对象加互斥锁),当一个线程访问临界区的代码时,其他线程也访问同一临界区时,会进入阻塞或轮询状态。
在查询时,尤其能够体现出CocurrentHashMap在效率上的优势,HashTable使用Sychronized关键字,会导致同时只能有一个查询在执行,而Cocurrent则不采取加锁的方式,而是采用volatile关键字,虽然会牺牲效率,但是性能稍好。
CocurrentHashMap利用锁分段技术增加了锁的数目,从而使争夺同一把锁的线程得到了控制。
锁分段技术就是对数据集进行分段,每段竞争一把锁,不同数据段的数据不存在锁竞争,从而有效提高并发访问效率。
Synchronized和volatile的区别
cocurrenthashmap结构(segment看成hashmap数组形式的锁,一个segment单元对应一个链表结构hashentry数组,每个hashentry是一个链表结构。segment守护者一个Hashentry数组你的元素)
concurrentHashMap使用场景:
用法:
public class H { public static void main(String[] args) { Map<Integer,String> map=new ConcurrentHashMap<>(); map.put(1,"A"); map.put(2,"B"); map.put(3,"C"); map.put(4,"D"); Set<Integer> s=map.keySet(); Iterator<Integer> it=s.iterator(); while(it.hasNext()){ Integer key=it.next(); System.out.println(key); } } }
三、Properties
用文件流读取文件内容,是HashTable的儿子,安全
public class I { public static void main(String[] args) { Properties pro=new Properties(); try { pro.load(new FileInputStream(new File("src/com/zxc/M/obj"))); Set<Map.Entry<Object,Object>> ss=pro.entrySet(); Iterator<Map.Entry<Object,Object>> it=ss.iterator(); while(it.hasNext()){ Map.Entry e=it.next(); System.out.println(e.getKey()+"="+e.getValue()); } } catch (IOException e) { e.printStackTrace(); } }
四、Set接口
不允许包含相同元素(如果有重复会被覆盖),Set判断两个对象是否相同需要采用equals方法进行判断。
HashSet是其实现类,有以下特点
HashSet当存入一个元素时,会调用该元素的hashCode()方法来得到该元素的hashCode值,之后以该值的顺序进行存储。