当前位置:   article > 正文

Java语言中HashMap集合面试常问问题_java map面试题

java map面试题

Java中HashMap集合在JDK1.8版本时基于 数组+链表+红黑树实现的,查询效率为O(1)

使用内部类Entry来描述键值对对象

目录

1.HashMap的key是否可以为自定义对象?

2.HashMap集合存储数据时是有序还是无序?

 3.HashMap key是否可以为null值?

4.什么是hash冲突问题?如何解决hash冲突问题?


创建了StudentEntity类并重写了toString方法,创建demo进行测试:

1.HashMap的key是否可以为自定义对象?

答案:可以

  1. public class demo {
  2. public static void main(String[] args) {
  3. HashMap<StudentEntity, String> hashMap = new HashMap<>();
  4. StudentEntity s1 = new StudentEntity("Mercedes", "22");
  5. StudentEntity s2 = new StudentEntity("Mercedes", "22");
  6. hashMap.put(s1,"OK");
  7. hashMap.put(s2,"OK");
  8. for (Map.Entry<StudentEntity,String> studentEntityStringEntry:
  9. hashMap.entrySet()) {
  10. System.out.println("key:"+studentEntityStringEntry.getKey().toString()+
  11. " value:"+studentEntityStringEntry.getValue());
  12. }
  13. }
  14. }

程序运行结果:

2.HashMap集合存储数据时是有序还是无序?

答案:无序,其底层采用散列机制存放数据

测试时我发现一个问题,当HashMap的key值被设置为Integer类型时,HashMap的存储就时有序的。

  1. public class demo {
  2. public static void main(String[] args) {
  3. HashMap<String, String> hashMap = new HashMap<>();
  4. for (int i = 0; i < 100; i++) {
  5. hashMap.put("k"+i,"v"+i);
  6. }
  7. hashMap.forEach((k,v)->{
  8. System.out.println(k+","+v);
  9. });
  10. }
  11. }

以上代码采用了一种比较新颖的Java集合基于范围的for循环遍历:

  1. hashMap.forEach((k,v)->{
  2. System.out.println(k+","+v);
  3. });

可替换为lambda表达式的方式:

hashMap.forEach((k,v)-> System.out.println(k+","+v));

程序运行结果:

 3.HashMap key是否可以为null值?

答案:可以  null键值存放在HashMap底层数组的index为0的位置(HashTable的key不允许存放null值)

  1. hashMap.put(null,"Mercedes");
  2. hashMap.forEach((k,v)-> System.out.println(k+","+v));

 可以为null值。

4.什么是hash冲突问题?如何解决hash冲突问题?

答:hash冲突问题是指:当要通过调用put方法存入两个对象时,这两个Entry对象的键的hashCode值相同,通过hashCode计算出的index值相同,所以会产生存入覆盖问题

  1. public class demo {
  2. public static void main(String[] args) {
  3. HashMap<Object, Object> hashMap = new HashMap<>();
  4. hashMap.put("a","a");
  5. hashMap.put(97,"97");
  6. System.out.println(hashMap.get("a"));
  7. }
  8. }

程序运行结果:

 可以看到Java提供的集合已经解决了hash冲突问题(本人想到一种解决冲突办法:将HashMap泛化出来再使用)

JDK1.7是这样解决的:

将hashCode值相同的key存放在同一张链表中

以下是自定义的HashMap

  1. package lzx4;
  2. public class MyHashMap<K,V> {
  3. private Entry<K,V>[] entries = new Entry[10000]; //存放键值对的数组
  4. class Entry<K, V> {
  5. K k;
  6. V v;
  7. int hash; //当前对象的hashCode
  8. Entry<K,V> next; //当前对象的next指针
  9. public Entry(K k, V v,int hash) {
  10. this.k = k;
  11. this.v = v;
  12. this.hash = hash;
  13. }
  14. }
  15. public void put(K k,V v){
  16. int hash = k.hashCode();
  17. int index = hash%entries.length;
  18. Entry oldEntry = entries[index]; //拿到该对象后判断是否为空,为空则证明该位置是第一次存对象
  19. if(oldEntry == null){ //否则就将上一次存放的对象的next指针指向当前对象
  20. entries[index] = new Entry<>(k,v,hash);
  21. }else{
  22. oldEntry.next = new Entry<>(k,v,hash);
  23. }
  24. }
  25. public V get(K k){
  26. int hash = k.hashCode();
  27. int index = hash%entries.length;
  28. for(Entry<K,V> entry = entries[index];entry!=null;entry = entry.next){
  29. if(entry.hash == hash && (entry.k == k || entry.k.equals(k))){
  30. return entry.v;
  31. }
  32. }
  33. return null;
  34. }
  35. public static void main(String[] args) {
  36. MyHashMap<Object, Object> myHashMap = new MyHashMap<>();
  37. myHashMap.put("a","a");
  38. myHashMap.put(97,"97");
  39. System.out.println(myHashMap.get("a"));
  40. }
  41. }

get()方法思路:先得到传入的key的hashCode,得到index后找到该条链表所在的位置,然后通过next指针向后循环,先比较当前对象的k的hashCode和传入的key的hashCode是否相等,if中这个语句

entry.k == k || entry.k.equals(k))

前面entry.k == k方便自定义类型比较,后面的equals方法在本案例中配合hash值来比较判断该对象位于链表中的哪个位置,在这里,equals方法单纯就是比较值一不一样。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/425206
推荐阅读
相关标签
  

闽ICP备14008679号