【问题标题】:Combining remove and put method in LinkedHashMap在 LinkedHashMap 中结合 remove 和 put 方法
【发布时间】:2019-06-21 05:21:26
【问题描述】:

使用LinkedHashMap,当我尝试重新插入具有不同值的相同键时,它会替换值并保持键的顺序,即如果我这样做

Map<String,String> map = new LinkedHashMap<>();
map.put("a", "a");
map.put("b", "b");
map.put("c", "c");
map.put("d", "d");
map.values().stream().forEach(System.out::print);    

输出:abcd

现在,如果我在地图中添加具有相同键的不同值,则顺序保持不变,即

map.put("b", "j");
map.values().stream().forEach(System.out::print); 

输出:ajcd

还有其他方法吗?一种是删除并重新插入具有新值的键,将acdj 打印为输出。就我而言,我想根据用作值的对象的某些属性对多个键执行此操作?

使用流的解决方案会更好。

【问题讨论】:

  • 取出钥匙再重新插入有什么问题?我认为这两个操作都应该是O(1)
  • 删除和插入是唯一的方法,实际上也不是一个坏方法。
  • @TimBiegeleisen 根据答案和 cmets 没有其他办法,我需要删除密钥并重新插入它。但是我需要新的地图来存储删除的条目然后把它回到地图中作为删除和放置在迭代时不能做同样的事情。?或者我可以在没有额外空间的情况下这样做吗?
  • 您可以使用this constructor 创建一个地图,在每次访问时都会更改顺序,当然,您必须接受即使get 也可能更改顺序的事实。跨度>

标签: java java-8 java-stream linkedhashmap


【解决方案1】:

这个链表定义了迭代顺序,通常是键插入映射的顺序(插入顺序)。请注意,如果将键重新插入到地图中,插入顺序不会受到影响

LinkedHashMap javadoc

它会跟踪 keys 插入,如果我们添加 Map.put javadoc :

如果映射先前包含键的映射,则旧值将替换为指定值。

Map javadoc

Entry 没有被替换,只是修改了值,所以key 保持不变。

您需要删除然后插入值来更新键的顺序。

【讨论】:

    【解决方案2】:

    HashMap 不按键或值排序。您正在寻找的是 TreeMap。 对于 HashMap,唯一的保证是,键会根据它们的哈希值进行哈希处理并放入一个数组中。

    根据 Javadoc,LinkedHashMap 创建一个内部 LinkedList,并跟踪条目的原始插入顺序。换句话说,如果您使用 LinkedHashMap,您根本不会收到“排序”列表。

    您有两个选项可以解决此问题:要么使用 TreeMap(或其派生图),要么在每次想要输出值时进行排序。 TreeMaps 有一个内部排序,基于它们的键。如果以您期望的方式(通过比较字符串)将键相互比较,那么您将根据键得到正确的升序排序。但是,这并不能解决您想要对值进行排序的问题。

    要解决您最初的问题,请使用双向 TreeMap。 Apache Commons4 实现了这样一个映射 (https://commons.apache.org/proper/commons-collections/javadocs/api-4.3/org/apache/commons/collections4/bidimap/AbstractDualBidiMap.html#values--) 它允许您访问键和值集。但请注意,如果您的价值观不是唯一的,则此地图将不适合您。与键一样,双向映射中的所有值都必须是唯一的,因为它们本身需要充当键。

    来自 Javadoc:

    此映射强制限制键和值之间存在 1:1 关系,这意味着多个键不能映射到同一个值。这是必需的,以便“反转”映射导致映射没有重复键。有关详细信息,请参阅 put(K, V) 方法说明。

    【讨论】:

    • 我认为您将哈希图与链接哈希图混淆了。这些与订购确实不同。 linkedhashmap 实际上具有可预测的顺序,即实际上基于第一次插入或每次访问。
    • 你是对的,部分是对的。我错过了,会更正。但是,LinkedHashMap 的排序不是基于键。来自 LinkedHashList 的 Javadoc:这个链表定义了迭代顺序,通常是键插入映射的顺序(插入顺序)
    【解决方案3】:

    Hashmap 插入仅基于哈希码。例如,“b”键的哈希码为 98。

    for map.put("b", "b");

    您插入作为具有代码 98 的键“b”。 所以它看起来像。 98 ---> 保持值'b'。

    再次,如果您尝试使用仅具有哈希码 98 的相同键“b”。 所以 hashmap 尝试仅链接相同的哈希码,即 98 ---> 将“j”作为一个值。

    要了解 hashmap 哈希码的工作原理,请查看下面的链接 https://www.geeksforgeeks.org/internal-working-of-hashmap-java/

    【讨论】:

    • 他使用的是LinkedHashMap,而不是HashMap
    • 即使在 LinkedHashMap 中,也仅将哈希码用于密钥插入并保持顺序。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-21
    相关资源
    最近更新 更多