如何自定义集合类并继承 AbstractList/AbstractMap:从头开始实现一个自己的集合类!

举报
喵手 发表于 2025/04/29 11:41:32 2025/04/29
【摘要】 开篇语哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。  我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,...

开篇语

哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛

  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。

  我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。

小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!

前言

在 Java 中,AbstractListAbstractMapjava.util 包中的两个抽象类,分别用于简化 ListMap 的自定义实现。如果你需要构建一个自定义的集合类,并且希望它符合 ListMap 的规范,可以继承这两个抽象类中的一个,来简化你的实现过程。今天我们将详细探讨如何继承 AbstractListAbstractMap 来实现自定义集合类。

1. 继承 AbstractList

AbstractListjava.util.List 接口的一个抽象实现类,提供了一些 List 操作的默认实现,比如 size()isEmpty()。但是,你仍然需要实现其中的核心方法,如 get(int index)add(E element)remove(int index)

1.1 继承 AbstractList 创建自定义列表

我们可以通过继承 AbstractList 来实现一个简单的自定义列表类。例如,假设我们想实现一个基于数组的简单列表。

示例代码:

import java.util.AbstractList;

public class MyArrayList<E> extends AbstractList<E> {
    private Object[] elements;
    private int size;

    // 构造方法,初始化一个初始容量的数组
    public MyArrayList(int capacity) {
        elements = new Object[capacity];
        size = 0;
    }

    @Override
    public E get(int index) {
        if (index < 0 || index >= size) {
            throw new IndexOutOfBoundsException("Index out of bounds");
        }
        return (E) elements[index];
    }

    @Override
    public int size() {
        return size;
    }

    @Override
    public boolean add(E e) {
        if (size == elements.length) {
            grow();
        }
        elements[size++] = e;
        return true;
    }

    // 扩展数组大小
    private void grow() {
        int newCapacity = elements.length * 2;
        Object[] newArray = new Object[newCapacity];
        System.arraycopy(elements, 0, newArray, 0, elements.length);
        elements = newArray;
    }

    @Override
    public E remove(int index) {
        if (index < 0 || index >= size) {
            throw new IndexOutOfBoundsException("Index out of bounds");
        }
        E oldValue = (E) elements[index];
        int numMoved = size - index - 1;
        if (numMoved > 0) {
            System.arraycopy(elements, index + 1, elements, index, numMoved);
        }
        elements[--size] = null; // 清空最后一个元素
        return oldValue;
    }
}

代码分析:

  • 构造方法MyArrayList(int capacity) 用来初始化一个指定初始容量的数组。
  • get(int index):返回指定索引位置的元素。如果索引越界,抛出 IndexOutOfBoundsException 异常。
  • size():返回当前列表的大小。
  • add(E e):向列表中添加元素。如果数组已满,调用 grow() 方法扩展数组。
  • remove(int index):删除指定索引位置的元素,之后将后面的元素向前移动,保持数组的连续性。

AbstractList 为我们提供了许多有用的方法实现,比如 addAll()removeAll()clear() 等,因此只需要实现 get(int index)size()remove(int index) 这些基本方法。

1.2 扩展:实现其他 List 操作

继承 AbstractList 后,我们还可以进一步覆盖和扩展其他操作,如插入元素、修改元素等。这些操作在 AbstractList 中有默认实现,通常需要根据自己的需求重写。


2. 继承 AbstractMap

AbstractMapjava.util.Map 接口的一个抽象实现类,用于简化 Map 的实现。你需要实现 get(Object key)put(K key, V value)remove(Object key)size() 等核心方法。

2.1 继承 AbstractMap 创建自定义映射类

假设我们要实现一个简单的基于数组的 Map 类。

示例代码:

import java.util.AbstractMap;
import java.util.Map;
import java.util.Set;
import java.util.HashSet;

public class MyHashMap<K, V> extends AbstractMap<K, V> {
    private Object[] keys;
    private Object[] values;
    private int size;
    private static final int INITIAL_CAPACITY = 16;

    // 构造函数,初始化键值对数组
    public MyHashMap() {
        keys = new Object[INITIAL_CAPACITY];
        values = new Object[INITIAL_CAPACITY];
        size = 0;
    }

    @Override
    public V get(Object key) {
        for (int i = 0; i < size; i++) {
            if (keys[i].equals(key)) {
                return (V) values[i];
            }
        }
        return null; // 如果没有找到键,则返回null
    }

    @Override
    public V put(K key, V value) {
        if (size == keys.length) {
            grow();
        }
        for (int i = 0; i < size; i++) {
            if (keys[i].equals(key)) {
                V oldValue = (V) values[i];
                values[i] = value;
                return oldValue;
            }
        }
        keys[size] = key;
        values[size] = value;
        size++;
        return null;
    }

    // 扩展数组大小
    private void grow() {
        int newCapacity = keys.length * 2;
        Object[] newKeys = new Object[newCapacity];
        Object[] newValues = new Object[newCapacity];
        System.arraycopy(keys, 0, newKeys, 0, keys.length);
        System.arraycopy(values, 0, newValues, 0, values.length);
        keys = newKeys;
        values = newValues;
    }

    @Override
    public Set<Map.Entry<K, V>> entrySet() {
        Set<Map.Entry<K, V>> entrySet = new HashSet<>();
        for (int i = 0; i < size; i++) {
            final int index = i;
            entrySet.add(new AbstractMap.SimpleEntry<>( (K) keys[index], (V) values[index]));
        }
        return entrySet;
    }

    @Override
    public int size() {
        return size;
    }

    @Override
    public V remove(Object key) {
        for (int i = 0; i < size; i++) {
            if (keys[i].equals(key)) {
                V oldValue = (V) values[i];
                System.arraycopy(keys, i + 1, keys, i, size - i - 1);
                System.arraycopy(values, i + 1, values, i, size - i - 1);
                keys[--size] = null;
                values[size] = null;
                return oldValue;
            }
        }
        return null;
    }
}

代码分析:

  • 构造方法MyHashMap() 初始化了一个指定初始容量的键值对数组。
  • get(Object key):遍历所有的键值对,找到对应键的值。如果不存在,返回 null
  • put(K key, V value):将键值对存入数组。如果键已经存在,更新其值;否则,插入新键值对。
  • grow():扩展键值对数组大小。
  • entrySet():返回一个包含所有键值对的 Set,通过 AbstractMap.SimpleEntry 来包装每个键值对。
  • size():返回 Map 中的元素数量。
  • remove(Object key):删除指定键的键值对,并将后续元素前移。

2.2 扩展:实现其他 Map 操作

AbstractList 类似,AbstractMap 也为大部分操作提供了默认实现,因此你只需实现核心的几个方法,并根据需要扩展其他方法。

3. 总结

继承 AbstractListAbstractMap 是实现自定义集合类的一个简单而高效的方式。通过继承这些抽象类,你可以专注于实现核心的操作,如元素的插入、删除、查找等,而不必重新实现一些常见的基础方法。你可以根据需要继续扩展或覆盖其他方法,以便完全满足自己的需求。

  • 继承 AbstractList:适合实现基于数组或链表的列表集合。
  • 继承 AbstractMap:适合实现基于数组、链表、哈希表等的映射集合。

无论是创建自定义的 List 还是 Map,只要合理设计,便能创建出既高效又符合业务需求的集合类。这为你在开发过程中提供了极大的灵活性,帮助你处理各种复杂的场景。

… …

文末

好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。

… …

学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!

wished for you successed !!!


⭐️若喜欢我,就请关注我叭。

⭐️若对您有用,就请点赞叭。
⭐️若有疑问,就请评论留言告诉我叭。


版权声明:本文由作者原创,转载请注明出处,谢谢支持!

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。