手写HashMap

    一、链表的基本实现
    定义节点类

    1. package LinkList;
    2. /**
    3. * 定义Node类(节点)
    4. * @author DaluxC
    5. *
    6. */
    7. public class Node {
    8. //上一节点
    9. private Node previous;
    10. //当前结点的内容
    11. private Object sth;
    12. //下一节点
    13. private Node next;
    14. public Node getPrevious() {
    15. return previous;
    16. }
    17. public void setPrevious(Node previous) {
    18. this.previous = previous;
    19. }
    20. public Object getSth() {
    21. return sth;
    22. }
    23. public void setSth(Object sth) {
    24. this.sth = sth;
    25. }
    26. public Node getNext() {
    27. return next;
    28. }
    29. public void setNext(Node next) {
    30. this.next = next;
    31. }
    32. }

    实现链表容器

    1. package LinkList;
    2. /**
    3. * 实现链表容器
    4. * @author DaluxC
    5. *
    6. */
    7. public class TestLinklist {
    8. private Node first; //定义首节点
    9. private Node last; //定义末节点
    10. private int size; //记量链表的长度
    11. //遍历链表的方法,输入你要遍历到第几个节点
    12. public Node Ergodic(int index) {
    13. aragecheck(index);
    14. Node temp = null;
    15. if(first != null) {
    16. temp = first;
    17. for(int i=0;i<index;i++) { //temp节点依次等于各个节点,到第index个节点时循环停止,temp节点就等于第index个节点了
    18. temp = temp.getNext();
    19. }
    20. }
    21. return temp;
    22. }
    23. public Object get(int index) {
    24. Node temp = Ergodic(index);
    25. return temp.getSth();
    26. }
    27. //依然是检查越界的方法
    28. public void aragecheck(int index) {
    29. if(index<0||index>size-1) {
    30. try {
    31. throw new Exception();
    32. }catch(Exception e) {
    33. e.printStackTrace();
    34. }
    35. }
    36. }
    37. //向链表中顺序添加新节点的方法
    38. public void SeqAdd(Object sth) {
    39. Node n = new Node(); //定义一个新节点n
    40. if(first==null) { //如果首节点为空,n将成为首节点
    41. n.setPrevious(null); //首节点没有上一个节点
    42. n.setSth(sth);
    43. n.setNext(null); //暂且没有下一个节点
    44. first = n; //将节点n定义为第一个节点
    45. last = n; //由于n是第一个添加的节点,所以它目前也是最后一个节点
    46. }else { //如果首节点不为空
    47. n.setPrevious(last); //n的上一个节点为曾经的末节点
    48. n.setSth(sth);
    49. n.setNext(null); //暂且没有下一个节点
    50. last.setNext(n); //将曾经为空的末节点的next域指向n
    51. last = n; //n成为末节点
    52. }
    53. size++;
    54. }
    55. //移除链表元素的方法
    56. public void remove(int index) {
    57. if(first != last) { //如果链表中不止一个节点
    58. Node pre;
    59. Node nxt;
    60. Node temp = Ergodic(index); //遍历链表,找到要删的那一个节点temp
    61. pre = temp.getPrevious(); //将temp节点的上一个节点命名为pre
    62. nxt = temp.getNext(); //将temp节点的下一个节点命名为nxt
    63. pre.setNext(nxt); //pre节点的next节点本来是temp节点,现在换为nxt节点
    64. nxt.setPrevious(pre); //nxt节点的previous节点本来是temp节点,现在换为pre节点
    65. //上面两步执行完后,temp的上一个节点和下一个节点连接在了一起,而隔过了temp节点,
    66. //实现了删除temp节点
    67. }else {
    68. first = null; //如果链表中只有一个节点,就直接给它整空
    69. }
    70. size--;
    71. }
    72. //获得链表大小的方法
    73. public int getSize() {
    74. return size;
    75. }
    76. }

    二、HashMap的基本实现
    定义键值对

    1. package Map;
    2. /**
    3. * 定义Entry类(键值对)
    4. * @author DaluxC
    5. *
    6. */
    7. public class Entry {
    8. private Object key;
    9. private Object value;
    10. public Entry(Object key,Object value) {
    11. this.key = key;
    12. this.value = value;
    13. }
    14. public Object getKey() {
    15. return key;
    16. }
    17. public void setKey(Object key) {
    18. this.key = key;
    19. }
    20. public Object getValue() {
    21. return value;
    22. }
    23. public void setValue(Object value) {
    24. this.value = value;
    25. }
    26. }

    实现HashMap

    1. package Map;
    2. import LinkList.TestLinklist;
    3. /**
    4. * @author DaluxC
    5. * 同时利用数组和链表来实现map容器
    6. * map容器储存键值对(key-value),一个key值对应一个value值
    7. */
    8. public class TestMap {
    9. TestLinklist[] arr = new TestLinklist[999]; //定义一个每个元素都是一个链表的数组
    10. int size;
    11. //定义向容器中添加数据的方法
    12. public void put(Object key,Object value) {
    13. Entry e = new Entry(key,value);
    14. int m = key.hashCode()%arr.length; //设置一个int值m,其值为输入的key值的哈希码值与数组arr的长度的模,通过这个模值来找某一个数据的位置
    15. if(arr[m] == null) { //如果数组中第m个链表为空
    16. TestLinklist l = new TestLinklist(); //新建一个链表
    17. l.SeqAdd(e); //向这个链表中添加第一个节点
    18. arr[m]=l; //将新建的这个链表赋给数组中的第m个元素
    19. }else { //如果第m个链表不为空
    20. for(int i=0;i<arr[m].getSize();i++) { //遍历链表
    21. Entry g = (Entry)arr[m].get(i);
    22. if(g.getKey().equals(key)) { //如果发现要添加的这个key值已经第m个链表中存在
    23. g.setValue(value); //用新输入的value值覆盖掉这个key值曾经对应的value值
    24. }
    25. }
    26. arr[m].SeqAdd(e); //如果要添加的这个key值在第m个链表中不存在,则直接在这个链表后直接添加新节点
    27. }
    28. size++;
    29. }
    30. //定义从容器中读数据的方法
    31. public Object get(Object key) {
    32. int m = key.hashCode()%arr.length;
    33. if(arr[m] != null) {
    34. for(int i=0;i<arr[m].getSize();i++) { //遍历相应的链表
    35. Entry g = (Entry)arr[m].get(i);
    36. if(g.getKey().equals(key)) { //如果找到了与输入的key值相等的key值
    37. return g.getValue(); //返回这个key值对应的value值
    38. }
    39. }
    40. }else
    41. System.out.println("没有找到值");
    42. return null; //如果相应的链表为空,则输出null
    43. }
    44. //定义从容器中移除数据的方法
    45. public void remove(Object key) {
    46. int m = key.hashCode()%arr.length;
    47. if(arr[m] != null) {
    48. for(int i=0;i<arr[m].getSize();i++) { //依然是遍历相应链表
    49. Entry g = (Entry)arr[m].get(i);
    50. if(g.getKey().equals(key)) { //如果找到了与输入的key值相等的key值
    51. arr[m].remove(i); //直接调TestLinklist类的remove方法给它删了
    52. }
    53. }
    54. }
    55. }
    56. }