1. 程式人生 > >LinkedHashMap在不同排序方式下的遍歷

LinkedHashMap在不同排序方式下的遍歷

        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);
        }

異常資訊: