Java:HashMap操作练习

HashMap是HashTable的兄弟,继承AbstractMap,实现Cloneable/Serializable接口。AbstractMap又是Map的实现。

HashMap是通过计算存储对象的哈希值,以键值Entry数组来散列存储对象。
如果存储遇到哈希碰撞,新建一个Node类,以旧键值对为头部,从尾部插入新键值对。
如果链表的长度大于8,则该链表转换成红黑树存储碰撞键值对。(JDK 1.8)

HashMap的容量总是2的次幂,在能估算需要容量的情况下,赋予接近并大于(容量*1.333)的2次幂大小为优

本练习实现:
创建HashMap插入数据,检查长度,清除数据
遍历HashMap的4种方法
1.for each entry:entrySet
2.while iterator of entrySet hasNext
3.for each key:keySet
4.for each value:values
浅拷贝
1.HashMap.clone()
2.HashMap.putAll(Map<K,T>)
深拷贝
1.HashMapPrac.cloneDeep()
2.for each new entry put(map.entry.getKey(),new List(listOrigin))

结论:

  1. HashMap的浅拷贝里Copied EntrySet()地址与Original EntrySet()不同
    所以直接修改EntrySet里的key或者value指向是没问题的。
  2. 如果Map存的是基本类型的包装类或者String,浅拷贝和深拷贝没区别
  3. 浅拷贝的真正的问题在于修改value或者key指向的,对象(比如一个List)的指向地址,会改变前者指向的地址从而产生意想不到的结果。
import java.util.*;
import java.io.*;

/*
 * This class is meant to practise implementing the API of HashMap
 */
public class HashMapPrac{

  public static void main(String[] args){

    //1. instantiate a hashmap with default constructor
    // then put some data
    print("==========1==========");
    var hashMap = new HashMap<String,String>();
    print(hashMap.isEmpty());//true
    hashMap.put("No.1","Oliver");//add data
    hashMap.put("No.2","Kimiko");
    hashMap.put("No.3","Matthew");
    hashMap.put("No.4","Andrew");
    print(hashMap.isEmpty());//false
    print(hashMap.size()); //4
    print(hashMap); //@override AbstractMap.toString()

    //2. get a shallow copy of this hashmap
    // then remove all of the mappings
    print("==========2==========");
    var hashMapCopyS = (HashMap)hashMap.clone();
    print(hashMapCopyS.size());//4
    print(hashMapCopyS);
    hashMapCopyS.clear();
    print(hashMapCopyS.size());//0



    //3. is there a mapping value for No.1? Is there a key mapping to Oliver?
    print("==========3==========");
    print(hashMap.containsKey("No.1"));//true
    print(hashMap.containsValue("Oliver"));//true

    //4. create a new hashMap, add 10 Integer pair to it
    //make sure value = 10*key
    //print the pairs where values < 50
    print("==========4==========");
    var map = new HashMap<Integer,Integer>();
    for(int i=1;i<=10;i++){
      map.put(i,i*10);
    }
    //for each entry of entrySet()
    for(Map.Entry<Integer,Integer> entry:map.entrySet()){
      if (entry.getValue()<50){
        print("Key: "+entry.getKey()+" Value: "+entry.getValue());
      }
    }

    print("");

    //while iterator of entrySet hasNext()
    Iterator iterator = map.entrySet().iterator();
    while(iterator.hasNext()){
      var entry = (Map.Entry<Integer,Integer>)iterator.next();
      if (entry.getValue()<50){
        print("Key: "+entry.getKey()+" Value: "+entry.getValue());
      }
    }

    print("");

    //for each key of keySet()
    for(Integer key:map.keySet()){
      if(map.get(key)<50){
        print("Key: "+key+" Value "+map.get(key));
      }
    }

    //5.print only the value of map where value <50
    print("==========5==========");

    for (Integer value:map.values()){
      if(value<50){
        print("Value: "+value);
      }
    }

    //6.get a deep copy of hashmap(Integer,ArrayList<T>)
    print("==========6==========");

    //create the original hashmap
    var list = new ArrayList<Integer>();
    list.add(1);
    list.add(2);
    list.add(3);
    var mapOrigin = new HashMap<Integer,ArrayList<Integer>>();
    mapOrigin.put(1,list);
    //copy the original hashmap
    var mapCopyDeep = new HashMap<Integer,ArrayList<Integer>>();
    for (Map.Entry<Integer,ArrayList<Integer>> entry:mapOrigin.entrySet()){
      mapCopyDeep.put(entry.getKey(),new ArrayList<Integer>(entry.getValue()));
    }

    //check if the values are pointing to the same list?
    print(mapOrigin.get(1)==mapCopyDeep.get(1)); //false

    // try copy using HashMap.putAll(Map<? extends K,? extends V>)
    var mapCopy = new HashMap<Integer,ArrayList<Integer>>();
    mapCopy.putAll(mapOrigin);
    print(mapOrigin.get(1)==mapCopy.get(1)); //true, another shallow copy

    //7. get a deep copy of mapOrigin, assumed that you dont know the 
    //   classes of which entry key and value have
    print("==========7==========");
    mapCopy = cloneDeep(mapOrigin);
    print(mapCopy + "\n" + mapOrigin);
    print(mapOrigin.get(1)==mapCopy.get(1)); //false



  }

  /*
   *Dizzy Lazy Fussy Busy
   */
  public static void print(Object obj){
    System.out.println(obj);
  }

  /*
   * Deep copy T of which extends Serializable
   */
   public static <T extends Serializable> T cloneDeep(T obj){

     T clonedObj = null;
     try{
       ByteArrayOutputStream baos = new ByteArrayOutputStream();
       ObjectOutputStream oos = new ObjectOutputStream(baos);
       oos.writeObject(obj);
       oos.close();

       ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
       ObjectInputStream ois = new ObjectInputStream(bais);
       clonedObj = (T)ois.readObject();
       ois.close();
     }catch(Exception e){
       e.printStackTrace();
     }
     return clonedObj;
   }
}

输出:

==========1==========
true
false
4
{No.2=Kimiko, No.1=Oliver, No.4=Andrew, No.3=Matthew}
==========2==========
4
{No.2=Kimiko, No.1=Oliver, No.4=Andrew, No.3=Matthew}
0
==========3==========
true
true
==========4==========
Key: 1 Value: 10
Key: 2 Value: 20
Key: 3 Value: 30
Key: 4 Value: 40

Key: 1 Value: 10
Key: 2 Value: 20
Key: 3 Value: 30
Key: 4 Value: 40

Key: 1 Value 10
Key: 2 Value 20
Key: 3 Value 30
Key: 4 Value 40
==========5==========
Value: 10
Value: 20
Value: 30
Value: 40
==========6==========
false
true
==========7==========
{1=[1, 2, 3]}
{1=[1, 2, 3]}
false
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值