集合基础-Map

Map是一个接口,其包含了多个实现类。Map是利用键值对的方式,来存储的。Key相当于扩大了索引的内容,不再局限于数组中的数字。

 HashMap

HashMap的底层实现采用了Hash表,这是一种非常重要的数据结构。key的hashcode值用于分割其在Entry[]中的位置,并在后面存储数据。具有极快的访问速度,但是其遍历顺序却是不确定的(因为在Hashmap的散列里,我们利用的散列方法会导致其遍历顺序的变化)。HashMap最多只允许记录一条键为null的记录。同时HashMap非线程安全的。如果想满足线程安全,可以使用synchronizedMap或者ConcurrentHashMap。

        HashMap在Java7中的实现是利用的一个数组+链表。数组中每个元素都是一个单向链表

        而HashMap为了进一步提高效率,在Java8中,引入了红黑树。

HashMap在Java8中引入了红黑树,当链表的长度大于8之后,Java就会自动将链表转换成红黑树。将此前查找的时间复杂度由O(n)下降到了O(logn)

 

下面我们实现一种最基础的数组加链表形式的Map。分别要实现其put ,get 功能,并且要保证Key的唯一性。同时,我们重写toString方法,方便我们遍历整个Map。并且使用泛型操作。

package 集合.Map.手写HashMap;

import java.util.Arrays;

/**
 * @program:多线程和IO
 * @descripton:
 * @author:ZhengCheng
 * @create:2021/10/11-19:43
 **/
public class HashMap_ <T,E>{
    private Node[] Entry ;
    private int size ;
    public HashMap_() {
        init();
    }

    private void init() {
        size = 16;
        Entry = new Node[size];
    }
    //key对应的HashCode
    private int gethashCode(T key){
        return key.hashCode();
    }
    public void put(T key,E val){
        int hash = gethashCode(key);
        int index = getPosition(hash);

        if (Entry[index] == null){
            Entry[index] = new Node(hash,key,val);
        }else {
            //遍历列表判断是否冲突
            Node check = checkHash(hash,index);
            if (check == null){
                Node temp = Entry[index];
                while (temp.next == null){
                    temp.next = new Node(hash,key,val);
                }
            }else {
                System.out.println("冲突,添加失败");
                return;
            }
        }
    }

    private Node checkHash(int hash ,int index) {
         Node temp = Entry[index];
         while (temp.next!=null && temp.getHash()!=hash){
             temp = temp.next;
         }
         if (temp.next == null && temp.getHash() !=hash){
             return null;
         }
         return temp;
    }

    private int getPosition(int hash){
        return hash&(size-1);
    }
    public E get(T key){
        int hash = gethashCode(key);
        //比较有无hash?如何快速比较呢?没有方法
        int index = getPosition(hash);
        Node temp =checkHash(hash,index);
        if (temp != null){
            E v = (E) temp.getVal();
            return v;
        }else {
            System.out.println("无");
        }
        return null;
    }
    //方便查看map里的键值对内容  遍历数组遍历链表
    @Override
    public String toString() {
        String res = "";
        for (int i = 0; i < Entry.length; i++) {
            if (Entry[i] != null){
                //遍历链表
                Node tmp = Entry[i];
                while (tmp.next != null){
                    res += tmp.toString();
                    tmp = tmp.next;
                }
                res += tmp.toString();
            }
        }
        return res;
    }
}
class Node <T,E>{
    public int hash;
    private T key;
    private E val;
    public Node next ;

    public int getHash() {
        return hash;
    }

    public void setHash(int hash) {
        this.hash = hash;
    }

    public T getKey() {
        return key;
    }

    public void setKey(T key) {
        this.key = key;
    }

    public E getVal() {
        return val;
    }

    @Override
    public String toString() {
        return "Node{" +
                "key=" + key +
                ", val=" + val +
                '}';
    }

    public void setVal(E val) {
        this.val = val;
    }

    public Node(int hash, T key, E val) {
        this.hash = hash;
        this.key = key;
        this.val = val;
    }
}
public class testDemo {
    public static void main(String[] args) {
        HashMap_<Integer, Integer> map = new HashMap_<>();
        map.put(1,23);
        map.put(1,22);
        map.put(2,1);
        map.put(3,1);
        map.put(4,1);

        Integer i = map.get(1);
        System.out.println(i);
        System.out.println(map);
    }
}

冲突,添加失败
23
Node{key=1, val=23}Node{key=2, val=1}Node{key=3, val=1}Node{key=4, val=1}

Process finished with exit code 0

TreeMap

public class TreeMap<K,V>
    extends AbstractMap<K,V>
    implements NavigableMap<K,V>, Cloneable, java.io.Serializable
private final Comparator<? super K> comparator;
private transient Entry<K,V> root;
private transient int size = 0;
private transient int modCount = 0;

TreeMap实现了SortedMap接口(实现了NavigatableMap ,NM是实现了Sorted的),能够把它保存的记录根据键的排序(默认Comparable升序或者自己使用Comparable重新排序)可以用Iterator遍历Treemap。

        当我们需要排序的映射时,建议使用TreeMap。

注意:在使用TreeMap时,key必须要实现Comparable接口,或者在构造TreeMap时传入Comparator,否则会在运行中抛出ClassCastException。

后续的ConcurrentHashMap,HashTableLinkHashMap在提到了再深入了解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值