LinkedHashMap字面上意思为有序集合,有两种排序方式,分别是按输入顺序与读取顺序,可通过以下构造方法来指定其排序方式:
public LinkedHashMap(int initialCapacity,
float loadFactor,
boolean accessOrder) {
super(initialCapacity, loadFactor);
this.accessOrder = accessOrder;
}
当accessOrder为false时按照输入顺序排序;accessOrder为true时按照读取顺序排序,但其中有一些细节需要注意,下文会说到。在LinkedHashMap其他的构造方法中,accessOrder均默认为false。
以下为代码演示
按输入顺序排序输出:
LinkedHashMap lhm = new LinkedHashMap(16,0.75f,false);
lhm.put("1","a");
lhm.put("2","b");
lhm.put("3","c");
lhm.put("4","d");
lhm.put("5","e");
输出结果为:
1-a
2-b
3-c
4-d
5-e
按读取顺序排序:
LinkedHashMap lhm = new LinkedHashMap(16,0.75f,true);
lhm.put("1","a");
lhm.put("2","b");
lhm.put("3","c");
lhm.put("4","d");
lhm.put("5","e");
//按顺序使用3、4、2元素
lhm.get("3");
lhm.get("4");
lhm.get("2");
for(Iterator iterator = lhm.entrySet().iterator();iterator.hasNext();){
Map.Entry<String,String> a = (Map.Entry<String,String>)iterator.next();
System.out.println(a.getKey() + '-' + a.getValue());
}
输出结果为:
1-a
5-e
3-c
4-d
2-b
可以看到该输出结果并不是完全按照读取顺序来输出的,根据结果来看其中3、4、2在被输出前是被使用过的,1、5没有被使用过,先输出的1、5在输出3、4、2。由此可见,LinkedHashMap指定了按元素读取顺序输出时会按照读取顺序将读取的元素添加到链表的末尾。在输出时先按照元素输入顺序输出未曾读取过的元素,也就是链表没有被读取过的前半部分,然后再按照读取的先后顺序输出后半部分读取过的元素。
所有集合在迭代器模式中遍历输出时是不允许修改集合结构的,也就是说LinkedHashMap在迭代遍历时同其他集合一样无法使用remove、put这种改变链表长度的方法,但不同的是LinkedHashMap在按照读取顺序来输出的模式下的话是连get方法也不能使用的,通过上面的代码可以发现LinkedHashMap在按读取顺序输出的模式下使用get方法时在内部将get的元素移动到了链表末尾,改变了链表的结构,会抛出ConcurrentModificationException异常。
代码如下:
for(Iterator iterator = lhm.keySet().iterator();iterator.hasNext();){ String name = (String)iterator.next(); lhm.get(name); }
异常信息: