13

我有这段非常简单的代码,我只是想在地图中玩一些不同类型的对象。

//There's a bit of spanish, sorry about that
//just think 'persona1' as an object with
//a string and an int
Map mapa = new HashMap();
mapa.put('c', 12850);
mapa.put(38.6, 386540);
mapa.put("Andrés", 238761);
mapa.put(14, "Valor de 14");
mapa.put("p1", persona1);
mapa.put("Andrea", 34500);

System.out.println(mapa.toString());

然后我期望从控制台得到类似的东西:

{c=12850, 38.6=386540, Andrés=238761, 14=Valor de 14, p1={nombre: Andres Perea, edad: 10}, Andrea=34500}

但令我惊讶的是,我以不同的顺序获得了相同的数据:

{38.6=386540, Andrés=238761, c=12850, p1={nombre: Andres Perea, edad: 10}, Andrea=34500, 14=Valor de 14}

如果我尝试其他类型的对象(即使只是字符串或数字类型)也没关系,它总是做同样的事情,它会产生不同的没有任何意义的顺序。

有人可以告诉我为什么会这样吗?或者可能是我错过的太明显的东西?

我正在使用 Java 1.7 和 Eclipse Juno。

4

5 回答 5

21

根据 Oracle 的文档

HashMap 类与 Hashtable 大致等价,不同之处在于它是不同步的并且允许空值。此类不保证地图的顺序;特别是,它不保证订单会随着时间的推移保持不变。

请参阅HashMap JavaDocs。

于 2013-09-13T04:42:13.123 回答
16

在java中有3个实现map接口的类。1. hashMap:id不保证任何顺序。2. Linked HashMap:按插入顺序存储。3. TreeMap:按升序存储。(ASCII值)

因此,根据您的要求,您可以使用 Linked HashMap 而不是 HashMap.so 而不是编写

Map mapa = new HashMap();

创建 Linked HashMap 的对象

Map mapa = new LinkedHashMap();

按照下面的链接了解更多信息。

http://docs.oracle.com/javase/tutorial/collections/interfaces/map.html

于 2013-09-13T04:48:15.593 回答
5

HashMap不保证元素的顺序。如果您想保持秩序,请使用LinkedHashMap

见以下案例

    Map<Integer,String> unOrderedMap=new HashMap<>();
    unOrderedMap.put(1,"a");
    unOrderedMap.put(3,"a");
    unOrderedMap.put(2,"a");
    System.out.println("HashMap output: "+unOrderedMap.toString());

    Map<Integer,String> orderedMap=new LinkedHashMap<>();
    orderedMap.put(1,"a");
    orderedMap.put(3,"a");
    orderedMap.put(2,"a");
    System.out.println("LinkedHashMap output: "+orderedMap.toString());

输出:

   HashMap output: {1=a, 2=a, 3=a}
   LinkedHashMap output: {1=a, 3=a, 2=a}
于 2013-09-13T04:44:21.857 回答
1

Maps 不会维护添加元素的顺序,List 会维护元素的顺序

“地图的顺序被定义为地图集合视图上的迭代器返回其元素的顺序。一些地图实现,如 TreeMap 类,对它们的顺序做出具体保证;其他的,如 HashMap 类,不。”

于 2013-09-13T04:42:03.620 回答
0

这就是哈希图的工作方式:(引用自另一个来源)


它有许多“桶”,用于存储键值对。每个桶都有一个唯一的数字——这就是标识桶的原因。当你把一个key-value对放入map中时,hashmap会查看key的hash code,并将pair存放在标识符为key的hash code的bucket中。例如:key的hash code是235 -> 对存储在235号桶中。(注意一个桶可以存储多于一个键值对)。

当你在 hashmap 中查找一个值时,通过给它一个键,它会首先查看你给出的键的哈希码。然后 hashmap 将查看相应的存储桶,然后将您提供的键与存储桶中所有对的键进行比较,方法是将它们与 equals() 进行比较。

现在您可以看到这对于在映射中查找键值对非常有效:通过键的哈希码,哈希映射立即知道要在哪个存储桶中查找,因此它只需要针对该存储桶中的内容进行测试。

看上面的机制,也可以看出对keys的hashCode()和方法有什么要求:equals()

  • 如果两个键相同(比较它们时 equals() 返回 true),则它们的 hashCode() 方法必须返回相同的数字。如果键违反了这一点,那么相等的键可能存储在不同的桶中,并且哈希映射将无法找到键值对(因为它会在同一个桶中查找)。

  • 如果两个键不同,那么它们的哈希码是否相同都没有关系。如果它们的哈希码相同,它们将存储在同一个桶中,在这种情况下,hashmap 将使用 equals() 来区分它们。


现在,当您将所有“键值”对放入哈希图中并打印它们时,它会以键的某种随机顺序打印它们,这些键是通过散列为键提供的值生成的。

如果您的要求仍然是保持顺序,您可以使用LinkedHashMapJava 中的。

希望这可以帮助 :-)

编辑:原始帖子:Java HashMap 如何处理具有相同哈希码的不同对象?

于 2013-09-13T04:49:00.830 回答