实现自己的ArrayList和HashMap

本文通过自定义实现ArrayList和HashMap,深入浅出地讲解这两种数据结构的存储方式和内部运作机制。具体包括ArrayList的数组存储原理及扩容机制,以及HashMap的数组加链表存储结构、哈希碰撞解决策略、rehash过程等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ArrayList的存储就是一个数组,


HashMap的存储是一个数组加一个链表,下面这张图来自: http://beyond99.blog.51cto.com/1469451/429789


以下实现的MyArrayList及MyHashMap,在实际的工作中都是用不上的,最有可能用得到的地方就是面试找工作以及忽悠别人了。工作中虽然用不上,但是并不代表没有用,它可以帮助我们去理解他们的实现原理,等实现完后再去仔细查看JDK中的源码,就会发现别人实现当中那些可供学习的地方。

MyArrayList

[java]  view plain copy
  1. public class MyArrayList<E> {  
  2.     private int capacity = 10;  
  3.     private int size = 0;  
  4.     private E[] values = null;  
  5.   
  6.     @SuppressWarnings("unchecked")  
  7.     public MyArrayList() {  
  8.         values = (E[]) new Object[capacity];  
  9.     }  
  10.   
  11.     @SuppressWarnings("unchecked")  
  12.     public MyArrayList(int capacity) {  
  13.         this.capacity = capacity;  
  14.         values = (E[]) new Object[this.capacity];  
  15.     }  
  16.   
  17.     public void put(E e) {  
  18.         if (e == null) {  
  19.             throw new RuntimeException("The value should not be null.");  
  20.         }  
  21.         if (size >= capacity) {  
  22.             enlargeCapacity();  
  23.         }  
  24.         values[size] = e;  
  25.         size++;  
  26.     }  
  27.   
  28.     public E get(int index) {  
  29.         if (index >= size) {  
  30.             throw new RuntimeException("The index:" + index + " is out of band.");  
  31.         }  
  32.         return values[index];  
  33.     }  
  34.   
  35.     public void remove(int index) {  
  36.         if (index >= size) {  
  37.             throw new RuntimeException("The index:" + index + " is out of band.");  
  38.         }  
  39.         for (int i = index; i < size - 1; i++) {  
  40.             values[i] = values[i + 1];  
  41.         }  
  42.         values[size - 1] = null;  
  43.         size--;  
  44.     }  
  45.   
  46.     @SuppressWarnings("unchecked")  
  47.     private void enlargeCapacity() {  
  48.         capacity = capacity * 2;  
  49.         E[] tmpValues = (E[]) new Object[capacity];  
  50.         System.arraycopy(values, 0, tmpValues, 0, size);  
  51.         values = tmpValues;  
  52.     }  
  53.   
  54.     public String toString() {  
  55.         StringBuilder sb = new StringBuilder();  
  56.         sb.append("[");  
  57.         for (int i = 0; i < size; i++) {  
  58.             sb.append(values[i]).append(",");  
  59.         }  
  60.         if (size > 0) {  
  61.             sb.deleteCharAt(sb.length() - 1);  
  62.         }  
  63.         sb.append("]");  
  64.         return sb.toString();  
  65.     }  
  66.   
  67.     /** 
  68.      * @param args 
  69.      */  
  70.     public static void main(String[] args) {  
  71.         MyArrayList<String> myList = new MyArrayList<String>();  
  72.         myList.put("1");  
  73.         myList.put("2");  
  74.         myList.put("3");  
  75.         myList.put("4");  
  76.         myList.put("5");  
  77.         myList.put("6");  
  78.         myList.put("7");  
  79.         myList.put("8");  
  80.         myList.put("9");  
  81.         myList.remove(7);  
  82.         System.out.println(myList.toString());  
  83.     }  
  84.   
  85. }  

MyHashMap

[java]  view plain copy
  1. public class MyHashMap<K, V> {  
  2.     //initialization capacity  
  3.     private int capacity = 10;  
  4.     //total entities  
  5.     private int size = 0;  
  6.     private Entity<K, V>[] entities = null;  
  7.   
  8.     @SuppressWarnings("unchecked")  
  9.     public MyHashMap() {  
  10.         entities = new Entity[capacity];  
  11.     }  
  12.   
  13.     public void put(K key, V value) {  
  14.         if (key == null) {  
  15.             throw new RuntimeException("The key is null");  
  16.         }  
  17.         reHash();  
  18.         Entity<K, V> newEntity = new Entity<K, V>(key, value);  
  19.         put(newEntity, this.entities, this.capacity);  
  20.     }  
  21.   
  22.     private void put(Entity<K, V> newEntity, Entity<K, V>[] entities, int capacity) {  
  23.         int index = newEntity.getKey().hashCode() % capacity;  
  24.         Entity<K, V> entity = entities[index];  
  25.         Entity<K, V> firstEntity = entities[index];  
  26.         if (entity == null) {  
  27.             entities[index] = newEntity;  
  28.             size++;  
  29.         } else {  
  30.             if (newEntity.getKey().equals(entity.getKey())) {//Find the same key for the first entity, if find then replace the old value to new value  
  31.                 newEntity.setNext(entity.getNext());  
  32.                 newEntity.setPre(entity.getPre());  
  33.                 if (entity.getNext() != null) {  
  34.                     entity.getNext().setPre(newEntity);  
  35.                 }  
  36.                 entities[index] = newEntity;  
  37.             } else if (entity.getNext() != null) {  
  38.                 while (entity.getNext() != null) {//Find the same key for all the next entity, if find then replace the old value to new value  
  39.                     entity = entity.getNext();  
  40.                     if (newEntity.getKey().equals(entity.getKey())) {  
  41.                         newEntity.setPre(entity.getPre());  
  42.                         newEntity.setNext(entity.getNext());  
  43.                         if (entity.getNext() != null) {  
  44.                             entity.getNext().setPre(newEntity);  
  45.                         }  
  46.                         entities[index] = newEntity;  
  47.                         return;  
  48.                     }  
  49.                 }  
  50.                 //Cannot find the same key, then insert the new entity at the header  
  51.                 newEntity.setNext(firstEntity);  
  52.                 newEntity.setPre(firstEntity.getPre());  
  53.                 firstEntity.setPre(newEntity);  
  54.                 entities[index] = newEntity;  
  55.                 size++;  
  56.             } else {  
  57.                 //Cannot find the same key, then put the new entity in head  
  58.                 newEntity.setNext(firstEntity);  
  59.                 firstEntity.setPre(newEntity);  
  60.                 entities[index] = newEntity;  
  61.                 size++;  
  62.             }  
  63.         }  
  64.     }  
  65.   
  66.     public V get(K key) {  
  67.         if (key == null) {  
  68.             throw new RuntimeException("The key is null");  
  69.         }  
  70.         int index = key.hashCode() % capacity;  
  71.         Entity<K, V> entity = entities[index];  
  72.         if (entity != null) {  
  73.             if (entity.getKey().equals(key)) {  
  74.                 return entity.getValue();  
  75.             } else {  
  76.                 entity = entity.getNext();  
  77.                 while (entity != null) {  
  78.                     if (entity.getKey().equals(key)) {  
  79.                         return entity.getValue();  
  80.                     }  
  81.                     entity = entity.getNext();  
  82.                 }  
  83.             }  
  84.   
  85.         }  
  86.         return null;  
  87.     }  
  88.   
  89.     public void remove(K key) {  
  90.         if (key == null) {  
  91.             throw new RuntimeException("The key is null");  
  92.         }  
  93.         int index = key.hashCode() % capacity;  
  94.         Entity<K, V> entity = entities[index];  
  95.         if (entity != null) {  
  96.             if (entity.getKey().equals(key)) {  
  97.                 if (entity.getNext() != null) {//remove the first entity  
  98.                     entity.getNext().setPre(entity.getPre());  
  99.                     entities[index] = entity.getNext();  
  100.                     entity = null;  
  101.                 } else {//empty this index  
  102.                     entities[index] = null;  
  103.                 }  
  104.                 size--;  
  105.             } else {  
  106.                 entity = entity.getNext();  
  107.                 while (entity != null) {  
  108.                     if (entity.getKey().equals(key)) {  
  109.                         if (entity.getNext() != null) {  
  110.                             entity.getPre().setNext(entity.getNext());  
  111.                             entity.getNext().setPre(entity.getPre());  
  112.                             entity = null;  
  113.                         } else {  
  114.                             //release the found entity  
  115.                             entity.getPre().setNext(null);  
  116.                             entity = null;  
  117.                         }  
  118.                         size--;  
  119.                         return;  
  120.                     }  
  121.                     entity = entity.getNext();  
  122.                 }  
  123.             }  
  124.         }  
  125.     }  
  126.   
  127.     public String toString() {  
  128.         StringBuilder sb = new StringBuilder();  
  129.         for (int i = 0; i < capacity; i++) {  
  130.             sb.append("index=").append(i).append("[");  
  131.             boolean hasEntity = false;  
  132.             Entity<K, V> entity = entities[i];  
  133.             if (entity != null) {  
  134.                 hasEntity = true;  
  135.             }  
  136.             while (entity != null) {  
  137.                 sb.append("[").append(entity.getKey()).append("=").append(entity.getValue()).append("]").append(",");  
  138.                 entity = entity.getNext();  
  139.             }  
  140.             if (hasEntity) {  
  141.                 sb.deleteCharAt(sb.length() - 1);  
  142.             }  
  143.             sb.append("]\n");  
  144.         }  
  145.         return sb.toString();  
  146.     }  
  147.   
  148.     /** 
  149.      * Simple re-hash strategy, if the size is bigger than capacity, then do re-hash action 
  150.      */  
  151.     private void reHash() {  
  152.         if (size >= capacity) {  
  153.             int newCapacity = capacity * 2;  
  154.             @SuppressWarnings("unchecked")  
  155.             Entity<K, V>[] newEntities = new Entity[newCapacity];  
  156.             for (int i = 0; i < capacity; i++) {  
  157.                 Entity<K, V> entity = entities[i];  
  158.                 while (entity != null) {  
  159.                     put(entity, newEntities, newCapacity);  
  160.                     entity = entity.getNext();  
  161.                 }  
  162.             }  
  163.             this.capacity = newCapacity;  
  164.             this.entities = newEntities;  
  165.         }  
  166.     }  
  167.   
  168.     public static void main(String[] args) {  
  169.         MyHashMap<String, String> map = new MyHashMap<String, String>();  
  170.         map.put("one""1");  
  171.         map.put("two""2");  
  172.         map.put("three""3");  
  173.         map.put("four""4");  
  174.         map.put("five""5");  
  175.         map.put("six""6");  
  176.         map.put("seven""7");  
  177.         map.put("eight""8");  
  178.         map.put("nine""9");  
  179.         map.put("ten""10");  
  180.         System.out.println(map.get("one"));  
  181.         System.out.println(map.get("two"));  
  182.         System.out.println(map.get("three"));  
  183.         System.out.println(map.get("four"));  
  184.         System.out.println(map.get("five"));  
  185.         System.out.println(map.get("six"));  
  186.         System.out.println(map.get("seven"));  
  187.         System.out.println(map.get("eight"));  
  188.         System.out.println(map.get("nine"));  
  189.         System.out.println(map.get("ten"));  
  190.         System.out.println(map.toString());  
  191.   
  192.         map.remove("nine");  
  193.         map.remove("three");  
  194.         System.out.println(map.get("one"));  
  195.         System.out.println(map.get("two"));  
  196.         System.out.println(map.get("three"));  
  197.         System.out.println(map.get("four"));  
  198.         System.out.println(map.get("five"));  
  199.         System.out.println(map.get("six"));  
  200.         System.out.println(map.get("seven"));  
  201.         System.out.println(map.get("eight"));  
  202.         System.out.println(map.get("nine"));  
  203.         System.out.println(map.get("ten"));  
  204.         System.out.println(map.toString());  
  205.     }  
  206. }  
  207.   
  208. class Entity<K, V> {  
  209.     private K key;  
  210.     private V value;  
  211.     private Entity<K, V> pre;  
  212.     private Entity<K, V> next;  
  213.   
  214.     public Entity(K key, V value) {  
  215.         this.key = key;  
  216.         this.value = value;  
  217.     }  
  218.   
  219.     public K getKey() {  
  220.         return key;  
  221.     }  
  222.   
  223.     public void setKey(K key) {  
  224.         this.key = key;  
  225.     }  
  226.   
  227.     public V getValue() {  
  228.         return value;  
  229.     }  
  230.   
  231.     public void setValue(V value) {  
  232.         this.value = value;  
  233.     }  
  234.   
  235.     public Entity<K, V> getPre() {  
  236.         return pre;  
  237.     }  
  238.   
  239.     public void setPre(Entity<K, V> pre) {  
  240.         this.pre = pre;  
  241.     }  
  242.   
  243.     public Entity<K, V> getNext() {  
  244.         return next;  
  245.     }  
  246.   
  247.     public void setNext(Entity<K, V> next) {  
  248.         this.next = next;  
  249.     }  
  250.   
  251. }  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值