2017-08-24 27 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,它可以保持键的顺序。您通常不需要提供比较器,如果没有提供比较器,则使用它们的键类型的自然顺序。