JAVA基础之自定义容器实现
容器
容器主要是指Collection所包含的实现类,常用的有List、Map以及Set三种结构。本文主要介绍了几种常见的集合实现类,对它们进行自定义实现。
- ArrayList:有序的容器列表,顺序存储着元素,可以使用下标进行索引,底层使用数组实现,使用数组拷贝实现扩容,下标索引快,插入效率低。
public class MyArrayList {private int size;private int DEFAULT_CAPACITY = 10;private Object[] elements;MyArrayList(int capacity) {elements = new Object[capacity];}MyArrayList() {elements = new Object[DEFAULT_CAPACITY];}/*** 增加元素** @param o*/public void add(Object o) {ensureCapacity();elements[size++] = o;}/*** 指定位置增加元素** @param index* @param o*/public void add(int index, Object o) throws Exception {indexCheck(index);ensureCapacity();System.arraycopy(elements, index, elements, index + 1, size - index);elements[index] = o;++size;}/*** 确保容量*/private void ensureCapacity() {if (size >= elements.length) {int oldSize = elements.length;Object[] newElements = new Object[oldSize + (oldSize >> 1)];System.arraycopy(elements, 0, newElements, 0, size);elements = newElements;}}/*** 按照下标进行索引** @param index* @return*/public Object get(int index) throws Exception {indexCheck(index);return elements[index];}/*** 下标合法性检测** @param index* @return* @throws Exception*/private boolean indexCheck(int index) throws Exception {if (index < 0 || index >= size) {throw new Exception("输入不合法");}return true;}/*** 根据下标删除元素** @param index* @throws Exception*/public void remove(int index) throws Exception {indexCheck(index);System.arraycopy(elements, index + 1, elements, index, size - index);--size;}/*** 根据对象删除元素** @param o*/public void remove(Object o) {if (o == null) {return;} else {for (int i = 0; i < size; i++) {if (elements[i].equals(o)) {System.arraycopy(elements, i + 1, elements, i, size - i);--size;return;}}}}/*** 返回元素个数** @return*/public int size() {return size;}/*** 清空容器*/public void clear() {for (int i = 0; i < size; i++) {elements[i] = null;}size = 0;}public static void main(String[] args) throws Exception {MyArrayList myArrayList = new MyArrayList();for (int i = 1; i <= 12; i++){myArrayList.add(i + "a");}myArrayList.add(2, "cccc");for (int i = 0; i < myArrayList.size(); i++){System.out.println(myArrayList.get(i));}System.out.println(myArrayList.size());myArrayList.clear();System.out.println(myArrayList.size());}
}
输出:
1a
2a
cccc
3a
4a
5a
6a
7a
8a
9a
10a
11a
12a
13
0
- LinkedList:有序链表顺序存储,可以根据下标进行索引,底层采用双向链表,插入速度快,根据下标索引慢。
public class MyLinkedList {private class Node{private Node per;private Node next;private Object val;Node(Object o){val = o;}}private int size;private Node root;private Node last;/*** 增加一个元素* @param o*/public void add(Object o){Node node = new Node(o);if(root == null){root = node;last = node;}else {last.next = node;node.per = last;last = node;}++size;}/*** 在指定位置添加元素* @param index* @param o* @throws Exception*/public void add(int index, Object o) throws Exception {indexCheck(index);Node tmp = root;for (int i = 0; i < index; i++){tmp = tmp.next;}Node node = new Node(o);node.next = tmp;node.per = tmp.per;tmp.per.next = node;++size;}private void indexCheck(int index) throws Exception {if (index < 0 || index > size)throw new Exception("输入错误");}/*** 根据下标进行索引* @param index* @return* @throws Exception*/public Object get(int index) throws Exception {indexCheck(index);Node tmp = root;for (int i = 0; i < index; i++){tmp = tmp.next;}return tmp.val;}/*** 返回尺寸* @return*/public int size(){return size;}/*** 清空容器*/public void clear(){Node tmp = last;for (int i = size - 1; i > 0; i--){last = last.per;tmp = null;}size = 0;}public static void main(String[] args) throws Exception {MyLinkedList myLinkedList = new MyLinkedList();for (int i = 1; i <= 12; i++){myLinkedList.add(i + "a");}myLinkedList.add(2, "cccc");for (int i = 0; i < myLinkedList.size(); i++){System.out.println(myLinkedList.get(i));}System.out.println(myLinkedList.size());myLinkedList.clear();System.out.println(myLinkedList.size());}
}
结果:
1a
2a
cccc
3a
4a
5a
6a
7a
8a
9a
10a
11a
12a
13
0
- HashMap:键值对,要求key唯一,底层使用数组-链表实现,先用元素的Hash值找到对应数组位置,这时可能会出现Hash冲突,为了解决问题,每个数组指向一个链表,以解决Hash冲突问题。
public class MyHashMap {private class Node{private Node next;private Object key;private Object value;Node(Object key, Object value){this.key = key;this.value = value;}}private int size;private Node[] elements;private int DEFAULT_CAPACITY = 100;MyHashMap(){elements = new Node[DEFAULT_CAPACITY];}/*** 增加一个键值对* @param key* @param value*/public void put(Object key, Object value){int index = calculateIndex(key);ensureCapacity(index);if (elements[index] == null){elements[index] = new Node(key, value);}else {Node root = elements[index];while (root.next != null){// key 唯一if (root.key.equals(key)){root.value = value;return;}root = root.next;}root.next = new Node(key, value);}++size;}/*** 确保容量* @param index*/private void ensureCapacity(int index){if (index >= elements.length ){Node[] newElements = new Node[index + 1];System.arraycopy(elements, 0, newElements, 0, elements.length);elements = newElements;}}/*** 计算下标* @param key* @return*/private int calculateIndex(Object key){int index = key.hashCode() % DEFAULT_CAPACITY;index = index > 0 ? index : -index;return index;}/*** 是否存在key* @param key* @return*/public boolean containsKey(Object key){int index = calculateIndex(key);Node root = elements[index];while (root != null){if (root.key.equals(key))return true;root = root.next;}return false;}/*** 通过key获取键值对value* @param key* @return*/public Object get(Object key){int index = calculateIndex(key);Node root = elements[index];while (root != null){if (root.key.equals(key))return root.value;root = root.next;}return null;}/*** 是否为空* @return*/public boolean isEmpty(){return size == 0;}/*** 尺寸* @return*/public int size(){return size;}/*** 是否包含键* @param value* @return*/public boolean containsValue(Object value){for (int i = 0; i < elements.length; i++){if (elements[i] == null)continue;Node root = elements[i];while (root != null){if (root.value.equals(value))return true;root = root.next;}}return false;}/*** 删除一个元素* @param key*/public void remove(Object key){int index = calculateIndex(key);Node root = elements[index];Node perNode = null;if (root != null){while (root != null){if (elements[index].key.equals(key)){elements[index] = root.next;--size;return;}else if (root.key.equals(key)){perNode.next = root.next;--size;return;}perNode = root;root = root.next;}}}public static void main(String[] args) {MyHashMap myHashMap = new MyHashMap();myHashMap.put("aaa", 1);myHashMap.put("bbb", 2);myHashMap.put("ccc", 3);System.out.println(myHashMap.containsKey("aaa"));System.out.println(myHashMap.containsKey("ddd"));System.out.println(myHashMap.containsValue(1));System.out.println(myHashMap.containsValue(4));System.out.println(myHashMap.size());System.out.println(myHashMap.isEmpty());System.out.println(myHashMap.get("aaa"));System.out.println(myHashMap.get("bbb"));System.out.println(myHashMap.get("ccc"));myHashMap.remove("aaa");System.out.println(myHashMap.size());}
}
结果:
true
false
true
false
3
false
1
2
3
2
- HashSet:集合,没有重复的元素,底层使用Map实现。在这里使用jdk自带的HashMap类进行实现。
public class MyHashSet {public HashMap<Object, Object> hashMap;private int size;private Object DEFAULT_OBJECT = new Object();MyHashSet(){hashMap = new HashMap<>();}public void add(Object o){if (!contains(o)){hashMap.put(o, DEFAULT_OBJECT);++size;}}public boolean contains(Object o){return hashMap.containsKey(o);}public int size(){return size;}public boolean isEmpty(){return size == 0;}public void clear(){hashMap.clear();size = 0;}public void remove(Object o){hashMap.remove(o);}public static void main(String[] args) {MyHashSet myHashSet = new MyHashSet();myHashSet.add("aaa");myHashSet.add("bbb");myHashSet.add("aaa");System.out.println(myHashSet.contains("bbb"));System.out.println(myHashSet.size());System.out.println(myHashSet.isEmpty());myHashSet.remove("aaa");myHashSet.clear();System.out.println(myHashSet.size());}
}
结果:
true
2
false
0
JAVA基础之自定义容器实现相关推荐
- Java基础知识(九) 容器
Java基础知识 1. Java Collections 框架是什么 2. 什么是迭代器 3. ArrayList.Vector 和 LinkedList 有什么区别 4. HashMap.Hasht ...
- Java基础知识(十) 多线程
Java基础知识 1. 什么是多线程?它与进程有什么区别?为什么要使用多线程 2. 同步和异步有什么区别 3. 如何实现Java多线程 4. run()方法与start()方法有什么区别 5. 多线程 ...
- JAVA 基础之容器集合(Collection和Map)
目录 前言 一.Collection集合 1.1List集合 1.1.1ArrayList集合 1.1.2LinkedList集合 1.2Set集合 1.2.1HashSet集合 HashSet集合保 ...
- java开发之ServLet注解、自定义容器方式详解
目录 一.为什么使用注解方式和自定义容器方式 二.注解方式步骤 1.创建javaEE8版本的web项目 2.创建一个类MyServlet继承HTTPServlet类并重写doGet()和doPost( ...
- JAVA基础(3)——容器(1)——常用容器分类
JAVA基础系列规划: JAVA基础(1)--基本概念 JAVA基础(2)--数据类型 JAVA基础(3)--容器(1)--常用容器分类 JAVA基础(4)--容器(2)--普通容器 JAVA基础(5 ...
- java基础day11---空指针异常----引用类型--自定义类型赋值--封装
day11 1.空指针异常--- --属于运行错误-java.long.NullPointerException --原因:当引用名称的值为null时,就不能访问某个对象中的属性或方法 热锅非要访问这 ...
- java基础—自定义一个比较器,对TreeSet 集合中的元素按指定方法来排序(java集合六)
自定义一个比较器,对TreeSet 集合中的元素按指定方法来排序 import java.util.Comparator; import java.util.Iterator; import java ...
- Java基础篇:Java集合
文章目录 1.概述 2.Collection接口 2.1 Collection接口方法 2.2 Iterator迭代器接口 2.3 Collection子接口之:List接口 2.4 Collecti ...
- [Spring 深度解析]第1章 Java基础
第1章 ◄Java基础► 在学习Spring之前我们需要对Java基础语法有一定的了解,Java中最重要的两个知识点是注解和反射.注解和反射在Spring框架中应用的最广泛.掌握注解和反射,有助于后面 ...
最新文章
- pandas基于dataframe字符串数据列包含(contains)特定字符串来筛选dataframe中的数据行(rows where values contain substring)
- FastDFS+Nginx实现文件服务器(转载)
- STM32 基础系列教程 4 – 基本定时器
- 树莓派该文件名_树莓派学习笔记(2):常用linux命令
- 软件工程第八次作业-2017282110249
- sql 2005判断某个表或某个表中的列是否存在
- java contains 通配符_java删除文件支持通配符
- HTML CSS JS(一)
- esp8266 阿里云 arduino_NUCLEO-G071RB通过WiFi与NB连接阿里云
- mysql查看sql代价_mysql 代价
- apf svg matlab,【涨知识】APF和SVG的区别与联系
- golang goroutine实现_golang中的Mutex设计原理详解(一)
- 2款免费的图片压缩工具
- esxi查看许可过期_ESXi许可证将在 60 天后过期问题
- Android 矢量图动画(完结篇)
- 虚拟机安装Win10纯净版操作系统
- Java中的函数式编程(二)函数式接口Functional Interface
- 用户数据权利请求响应具体都包括哪些内容
- 测试硬盘供电不足的软件,移动硬盘供电不足怎么解决?移动硬盘供电不足的解决方法...
- 听java技术讲座心得体会_听讲座心得体会范文(精选3篇)