当一个重复的键被放入hashmap时会发生什么?

hjzp0vay  于 2021-06-30  发布在  Java
关注(0)|答案(12)|浏览(529)

如果我多次把同一把钥匙传给 HashMapput 方法,原值会发生什么变化?如果值重复呢?我没有找到任何关于这个的文件。
情况1:覆盖键的值

Map mymap = new HashMap();
mymap.put("1","one");
mymap.put("1","not one");
mymap.put("1","surely not one");
System.out.println(mymap.get("1"));

我们得到 surely not one .
案例2:重复值

Map mymap = new HashMap();
mymap.put("1","one");
mymap.put("1","not one");
mymap.put("1","surely not one");
// The following line was added:
mymap.put("1","one");
System.out.println(mymap.get("1"));

我们得到 one .
但是其他的价值观呢?我在教一个学生基础知识,有人问我这个问题。是 Map 就像引用最后一个值的bucket(但在内存中)?

wbgh16ku

wbgh16ku1#

你可以在map#put(k,v)的javadoc中找到答案(它实际上返回了一些东西):

public V put(K key,
             V value)

将指定值与此Map中的指定键相关联(可选操作)。如果Map以前包含此键的Map,则旧值将替换为指定值(Map m 据说包含一个键的Map k 当且仅当 m.containsKey(k) 会回来的 true .)
参数: key -与指定值关联的键。 value -要与指定键关联的值。
退货:
与指定键关联的上一个值,或 null 如果没有Map key . (一 null return还可以指示先前关联的Map null 使用指定的 key ,如果实现支持 null 值。)
如果调用时不赋值 mymap.put("1", "a string") ,它只是变得不可引用,因此符合垃圾收集的条件。

jrcvhitl

jrcvhitl2#

它将替换Map中相应键的现有值。如果不存在具有相同名称的键,那么它将使用提供的值创建一个键。如:

Map mymap = new HashMap();
mymap.put("1","one");
mymap.put("1","two");

输出键=“1”,值=“2”
因此,前面的值被覆盖。

5w9g7ksd

5w9g7ksd3#

将指定值与此Map中的指定键相关联。如果Map以前包含键的Map,则替换旧值。

nwlls2ji

nwlls2ji4#

顺便说一句,如果你想要一些语义,比如只有当这个键不存在时才放。你可以用 concurrentHashMapputIfAbsent() 功能。看看这个:
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/concurrenthashmap.html#put(千伏,%20v) concurrentHashMap 是线程安全的高性能,因为它使用“锁条带化”机制来提高吞吐量。

yws3nbqq

yws3nbqq5#

来自jdk的Map并不用于在重复的键下存储数据。
新值最多会覆盖以前的值。
更糟糕的情况是异常(例如,当您尝试将其收集为流时):
无重复项: Stream.of("one").collect(Collectors.toMap(x -> x, x -> x)) 好 啊。您将得到:$2==>{one=one}
复制流: Stream.of("one", "not one", "surely not one").collect(Collectors.toMap(x -> 1, x -> x)) exception java.lang.illegalstateexception:在collectors.duplicatekeyexception(collectors)处重复键1(尝试合并一个值而不是一个值)。java:133)|在收集器处。lambda$uniqkeysmapmapacculator$1(收集器。java:180)|在reduceops$3reducesink.accept(reduceops。java:169)|在拆分器$arrayspliterator.foreachremaining处(拆分器。java:948)|在abstractpipeline.copyinto(abstractpipeline。java:484)|在abstractpipeline.wrapandcopyinto(abstractpipeline。java:474)|在reduceops$reduceops.evaluatesequential(reduceops。java:913)|在abstractpipeline.evaluate(abstractpipeline。java:234)|在referencepipeline.collect(referencepipeline。java:578)|在(#4:1)
要处理重复的密钥-请使用其他软件包,例如:https://google.github.io/guava/releases/19.0/api/docs/com/google/common/collect/multimap.html
有许多其他的实现处理重复的密钥。这些是web所需要的(例如,重复的cookie密钥、http头可以有相同的字段,…)
祝你好运!:)

4sup72z8

4sup72z86#

HashMap<Emp, Emp> empHashMap = new HashMap<Emp, Emp>();

         empHashMap.put(new Emp(1), new Emp(1));
         empHashMap.put(new Emp(1), new Emp(1));
         empHashMap.put(new Emp(1), new Emp());
         empHashMap.put(new Emp(1), new Emp());
         System.out.println(empHashMap.size());
    }
}

class Emp{
    public Emp(){   
    }
    public Emp(int id){
        this.id = id;
    }
    public int id;
    @Override
    public boolean equals(Object obj) {
        return this.id == ((Emp)obj).id;
    }

    @Override
    public int hashCode() {
        return id;
    }
}

OUTPUT : is 1

意味着哈希Map不允许重复,如果您正确地重写了equals和hashcode()方法。
hashset在内部也使用hashmap,请参阅源文档

public class HashSet{
public HashSet() {
        map = new HashMap<>();
    }
}
watbbzwu

watbbzwu7#

是的,这意味着所有带值的1键都被最后添加的值覆盖,在这里您添加了“肯定不是一个”,因此它将只显示“肯定不是一个”。
即使您尝试使用循环显示,它也只会显示一个键和值,它们具有相同的键。

mbyulnm0

mbyulnm08#

对于你的问题Map是否像一个桶:不。
就像一张有 name=value 成对,鉴于 name 不需要是字符串(但是可以)。
要获取一个元素,需要将键传递给get()—方法,该方法将返回指定的对象。
hashmap意味着如果您试图使用get方法检索您的对象,它不会将实际对象与您提供的对象进行比较,因为它需要遍历它的list并比较()您提供给当前元素的键。
这将是低效的。相反,不管您的对象由什么组成,它都从这两个对象计算所谓的hashcode并比较它们。比较两者更容易 int 而不是两个完整(可能非常复杂)的对象。您可以将hashcode想象成一个具有预定义长度(int)的摘要,因此它不是唯一的并且有冲突。您可以在我插入链接的文档中找到hashcode的规则。
如果您想了解更多这方面的信息,您可能想看看javapractices.com和technofundo.com上的文章
当做

g6baxovj

g6baxovj9#

根据定义 put 命令替换与Map中给定键相关联的先前值(概念上类似于基元类型的数组索引操作)。
Map只是删除对值的引用。如果没有其他对象包含对该对象的引用,则该对象将有资格进行垃圾收集。此外,java返回与给定键(或 null 如果不存在),则可以确定存在什么,并在必要时保留引用。
更多信息:hashmap doc

w6lpcovy

w6lpcovy10#

键的先前值将被删除并替换为新值。
如果您想保留一个键给定的所有值,可以考虑实现如下内容:

import org.apache.commons.collections.MultiHashMap;
import java.util.Set;
import java.util.Map;
import java.util.Iterator;
import java.util.List;
public class MultiMapExample {

   public static void main(String[] args) {
      MultiHashMap mp=new MultiHashMap();
      mp.put("a", 10);
      mp.put("a", 11);
      mp.put("a", 12);
      mp.put("b", 13);
      mp.put("c", 14);
      mp.put("e", 15);
      List list = null;

      Set set = mp.entrySet();
      Iterator i = set.iterator();
      while(i.hasNext()) {
         Map.Entry me = (Map.Entry)i.next();
         list=(List)mp.get(me.getKey());

         for(int j=0;j<list.size();j++)
         {
          System.out.println(me.getKey()+": value :"+list.get(j));
         }
      }
   }
}
nhjlsmyf

nhjlsmyf11#

我总是用:

HashMap<String, ArrayList<String>> hashy = new HashMap<String, ArrayList<String>>();

如果我想对一个识别键应用多个东西。

public void MultiHash(){
    HashMap<String, ArrayList<String>> hashy = new HashMap<String, ArrayList<String>>();
    String key = "Your key";

    ArrayList<String> yourarraylist = hashy.get(key);

    for(String valuessaved2key : yourarraylist){
        System.out.println(valuessaved2key);
    }

}

你总是可以这样做,给自己制造一个迷宫!

public void LOOK_AT_ALL_THESE_HASHMAPS(){
    HashMap<String, HashMap<String, HashMap<String, HashMap<String, String>>>> theultimatehashmap = new HashMap <String, HashMap<String, HashMap<String, HashMap<String, String>>>>();
    String ballsdeep_into_the_hashmap = theultimatehashmap.get("firststring").get("secondstring").get("thirdstring").get("forthstring");
}
q9yhzks0

q9yhzks012#

它是键/值特性,您不能为多个值设置重复键,因为当您要获取实际值时,输入的键属于哪一个值
在你的例子中,当你想得到“1”的值时,它是哪一个?!
这就是每个值都有唯一键的原因,但您可以使用java标准库的技巧:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

public class DuplicateMap<K, V> {

    private Map<K, ArrayList<V>> m = new HashMap<>();

    public void put(K k, V v) {
        if (m.containsKey(k)) {
            m.get(k).add(v);
        } else {
            ArrayList<V> arr = new ArrayList<>();
            arr.add(v);
            m.put(k, arr);
        }
    }

     public ArrayList<V> get(K k) {
        return m.get(k);
    }

    public V get(K k, int index) {
        return m.get(k).size()-1 < index ? null : m.get(k).get(index);
    }
}

你可以这样使用它:

public static void main(String[] args) {
    DuplicateMap<String,String> dm=new DuplicateMap<>();
    dm.put("1", "one");
    dm.put("1", "not one");
    dm.put("1", "surely not one");
    System.out.println(dm.get("1"));
    System.out.println(dm.get("1",1));
    System.out.println(dm.get("1", 5));
}

打印结果如下:

[one, not one, surely not one]
not one
null

相关问题