2017-08-24 35 views
1

改變鍵的順序似乎的NetBeans趨於將它們放置時成HashMap相比,通過直接調用javac.exejava.exe創建的HashMap對象修改的鍵值雙的順序。的NetBeans在HashMap中

考慮下面的類定義(packageimport聲明忽略):

class Coder { 

    enum Gender { FEMALE, MALE } 
    String name; 
    Gender gender; 

    Coder(String name, Gender gender) { 
     this.name = name; 
     this.gender = gender; 
    } 

    String getName() { return name; } 
    Gender getGender() { return gender; } 
} 

class Test{ 
    public static void main(String[] args) { 
     List<Coder> list = Arrays.asList(
       new Coder("Alice", Coder.Gender.FEMALE), 
       new Coder("Chuck", Coder.Gender.MALE), 
       new Coder("Bob", Coder.Gender.MALE)); 
     Map<Coder.Gender, List<String>> classification = list.stream() 
         .collect(Collectors.groupingBy(Coder::getGender, 
           Collectors.mapping(Coder::getName, Collectors.toList()))); 
     System.out.println(classification); 

     // Getting metainfo: 
     System.out.println("Actual map's type at runtime is " + 
          classification.getClass().getSimpleName()); 
     System.out.println("OS: " + System.getProperty("os.name") + 
          ", ver." + System.getProperty("os.version")); 
     System.out.println("Java ver.: " + System.getProperty("java.version")); 

     // Serializing: 
     String filename = "classification_cmd.ser"; 
     // String filename = "classification_NetBeans.ser"; // toggle commenting-out as needed 
     File file = new File(filename); 
     try (
      FileOutputStream fos = new FileOutputStream(file); 
      ObjectOutputStream outs = new ObjectOutputStream(fos) 
     ) 
     { outs.writeObject(classification); 
     } catch (IOException ioe) { ioe.printStackTrace(); }; 
    } 
} 

編譯和在Windows(爪哇ver.1.8.0_066)直接從命令行運行上述代碼生成此:

{MALE=[Chuck, Bob], {FEMALE=[Alice]} 

在我的Raspberry Pi(Java ver.1.80_065)上的CLI和通過ideone.com(Java ver.1.8.0_112)的Linux下,結果基本相同:首先是MALE組,然後是FEMALE組。然而,在NetBeans 8.1在Windows下(Java的ver.1.8.0_066)輸出發生了逆轉:

{FEMALE=[Alice], MALE=[Chuck, Bob]} 

在所有情況下有問題的地圖的實際類型是HashMap。序列化映射到磁盤和偷看裏面證實物體在鍵值對秩序方面確實不同:

- 命令行: enter image description here

- 從內部的NetBeans : enter image description here

因此我的問題:

  • 它爲什麼會發生,以及
  • 應該做些什麼(我的意思是,除了強制排序,如僱用約定製Comparator等建立了一個TreeMap)以確保結果將是完全一樣的,不管我們如何編譯並運行我們的程序,從命令行或從NetBeans中運行?
+1

我知道你仍然想知道它爲什麼會發生,但這很重要:「這個類不能保證地圖的順序;特別是,它不能保證順序會隨着時間的推移保持不變「。 - [HashMap Doc](https://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html) – mumpitz

+0

是的,我確實意識到這一點,並沒有解決閒置問題好奇心。想象一下,當我編寫OCP考試時(1Z0-809),其中一個測驗的構建與我的問題類似,因此包含兩個同樣可能的,相互顛倒的選項,儘管我本應只勾選其中一個。是什麼讓問題變得更加令人困惑,「對返回的Map或List對象的類型,可變性,可串行性或線程安全性沒有保證(按照Collectors.groupingBy()中的javadoc)。我只是希望有更多的東西... –

回答

0

無法保證通用Map實現保留添加元素的任何順序。

如果你關心這個順序,你確實需要使用像TreeMap一樣的NavigableMap,它可以保持鍵的順序。您通常不需要提供比較器,如果沒有提供比較器,則使用它們的鍵類型的自然順序。