数据结构之链表下的Map

数据结构之链表下的Map

Map是一个以键值对存储的接口。Map下有两个具体的实现,分别是HashMap和HashTable.

  • Hashtable:底层是数组+链表,线程安全,效率低。不允许null键和null值
  • HashMap:底层是数组+红黑树,线程不安全,效率高。允许null键和null值

自定义Map接口

package com.company.map;

/**
 * @Author: wenhua
 * @CreateTime: 2023-01-10  19:56
 */
public interface Map<K, V> {

    // 获取元素个数
    int getSize();

    // 判断是否包含该元素
    boolean isContain(K key);

    // 判断map中元素是否为空
    boolean isEmpty();

    // 添加元素
    void add(K key, V value);

    // 通过键移除元素并返回元素
    V remove(K key);

    // 更新元素的键值对
    void set(K key, V value);

    // 通过键获取对应的值
    V get(K key);

}

自定义链表

package com.company.map;

/**
 * @Author: wenhua
 * @CreateTime: 2023-01-05  20:23
 */
public class Link<K extends Comparable, V> {

    /**
     * 键值对结点对象
     *
     * @param <K>
     * @param <V>
     */
    private class Node<K, V> {
        K key;
        V value;
        Node next;

        /**
         * 无参构造函数
         */
        public Node() {
            this(null, null);
        }

        /**
         * 有参构造函数
         *
         * @param key
         * @param value
         */
        public Node(K key, V value) {
            this.key = key;
            this.value = value;
            this.next = null;
        }

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

    private Node<K, V> head;
    private int size = 0;

    /**
     * 无参构造函数
     */
    public Link() {
    }

    /**
     * 有参构造函数
     *
     * @param key 节点数据
     */
    public Link(K key, V value) {
        head = new Node(key, value);
    }

    /**
     * 获取链表长度
     *
     * @return
     */
    public int getSize() {
        return size;
    }

    /**
     * 判断链表是否为空
     *
     * @return
     */
    public boolean isEmpty() {
        return size == 0;
    }

    /**
     * 添加链表元素
     * 特点:在链表的头部添加
     *
     * @param key
     * @param value
     */
    public void add(K key, V value) {
        if (isContain(key)) {
            set(key, value);
            return;
        }
        // 创建新节点
        Node newNode = new Node(key, value);
        // 将头结点数据连接在新节点后
        newNode.next = head;
        // 将新节点连接在头结点的下一个结点
        head = newNode;
        // 元素个数加1
        size++;
    }

    /**
     * 判断链表中是否存在该元素
     *
     * @param key
     * @return
     */
    public boolean isContain(K key) {
        if (isEmpty())
            return false;
        Node node = head;
        for (int i = 0; i < getSize(); i++) {
            if (node.key.equals(key))
                return true;
            node = node.next;
        }
        return false;
    }

    /**
     * @param key
     * @return
     */
    public V get(K key) {
        // 判断键是否存在,存在则进行更改,否则返回空
        if (isContain(key)) {
            Node temp = head;
            for (int i = 0; i < getSize(); i++) {
                if (temp.key.equals(key))
                    return (V) temp.value;
                temp = temp.next;
            }
        }
        return null;
    }

    /**
     * 更新操作
     *
     * @param key
     * @param value
     * @return
     */
    public boolean set(K key, V value) {
        // 获取需要更改的键值对结点对象
        Node node = getNode(key);
        // 如果结点不为空,则覆盖值即可
        if (node != null) {
            node.value = value;
            return true;
        }
        return false;
    }

    /**
     * 通过键获取指定的结点
     *
     * @param key
     * @return
     */
    private Node getNode(K key) {
        // 判断键是否存在,是则进行查找,否则返回空
        if (isContain(key)) {
            Node temp = head;
            for (int i = 0; i < getSize(); i++) {
                if (temp.key.equals(key))
                    return temp;
                temp = temp.next;
            }
        }
        return null;
    }

    /**
     * 移除指定元素
     *
     * @return
     */
    public V remove(K key) {
        V value = null;
        if (!isContain(key)) {
            System.out.println(key + "该元素不存在");
            return value;
        }
        if (head.key.equals(key)) {// 头结点元素为指定元素时
            value = head.value;
            // 将头结点的下一个结点赋值给头结点
            head = head.next;
            // 树的数据量减1
            size--;
            // 删除成功,返回
            return value;
        } else {// 其他结点为将要删除元素
            Node pre = head;
            Node temp = head.next;
            // for循环遍历,查找将要删除的元素位置
            for (int i = 0; i < getSize(); i++) {
                if (temp.key.equals(key)) {
                    value = (V) temp.value;
                    pre.next = temp.next;
                    size--;
                    return value;
                }
                pre = pre.next;
                temp = temp.next;
            }
        }
        return value;
    }

    @Override
    public String toString() {
        // 方式以:通过字符串拼接每个节点数据
        StringBuffer sbf = new StringBuffer();
        Node temp = head;
        for (int i = 0; i < getSize(); i++) {
            sbf.append(temp.key + ":" + temp.value);
            if (temp.next != null) {
                temp = temp.next;
                sbf.append(",");
            }
        }
        return sbf.toString();
    }
}

自定义链表实现Map接口

package com.company.map;

/**
 * @Author: wenhua
 * @CreateTime: 2023-01-10  09:46
 */
public class MyLinkMap<K extends Comparable,V>  implements Map<K,V> {

    private MyLink<K,V> myLink;

    public MyLinkMap(){
        myLink = new MyLink<K,V>();
    }

    @Override
    public boolean isEmpty() {
        return myLink.isEmpty();
    }

    @Override
    public boolean isContain(K key) {
        return myLink.isContain(key);
    }

    @Override
    public void add(K key,V value) {
        myLink.add(key,value);
    }

    @Override
    public V remove(K key) {
        return myLink.remove(key);
    }

    @Override
    public void set(K key, V value) {
        myLink.set(key,value);
    }

    @Override
    public V get(K key) {
        return (V) myLink.getByKey(key);
    }

    @Override
    public int getSize() {
        return myLink.getSize();
    }

    @Override
    public String toString() {
        return "MyLinkSet{" +
                "myLink=" + myLink +
                '}';
    }
}

Map实现类

package com.company.map;

/**
 * @Author: wenhua
 * @CreateTime: 2023-01-10  09:46
 */
public class LinkMap<K extends Comparable, V> implements Map<K, V> {

    private Link<K, V> link;

    public LinkMap() {
        link = new Link<K, V>();
    }

    @Override
    public boolean isEmpty() {
        return link.isEmpty();
    }

    @Override
    public boolean isContain(K key) {
        return link.isContain(key);
    }

    @Override
    public void add(K key, V value) {
        link.add(key, value);
    }

    @Override
    public V remove(K key) {
        return link.remove(key);
    }

    @Override
    public void set(K key, V value) {
        link.set(key, value);
    }

    @Override
    public V get(K key) {
        return link.get(key);
    }

    @Override
    public int getSize() {
        return link.getSize();
    }

    @Override
    public String toString() {
        return "LinkMap{" +
                "link=" + link +
                '}';
    }
}

测试

package com.company.map;

/**
 * @Author: wenhua
 * @CreateTime: 2023-01-10  21:57
 */
public class Main {

    public static void main(String[] args) {
        LinkMap<String,Integer> myMap = new LinkMap<String,Integer>();
        System.out.println("判断map对象是否为空:"+myMap.isEmpty());
        myMap.add("wenhua",23);
        System.out.println("判断map对象是否为空:"+myMap.isEmpty());
        System.out.println("获取map对象中元素个数:"+myMap.getSize());
        System.out.println(myMap.toString());
        System.out.println("通过键wenhua获取map对象中对应的元素:"+myMap.get("wenhua"));
        myMap.set("wenhua",24);
        System.out.println(myMap.toString());
        myMap.add("Jim",23);
        myMap.add("wenhua",23);
        System.out.println(myMap.toString());
        System.out.println("通过键wenhua移除并返回map对象中对应的元素:"+myMap.remove("wenhua"));
        System.out.println(myMap.toString());
    }
}

测试结果

判断map对象是否为空:true
判断map对象是否为空:false
获取map对象中元素个数:1
LinkMap{link=wenhua:23}
通过键wenhua获取map对象中对应的元素:23
LinkMap{link=wenhua:24}
LinkMap{link=Jim:23,wenhua:23}
通过键wenhua移除并返回map对象中对应的元素:23
LinkMap{link=Jim:23}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值