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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/544343.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

git reset, git checkout, git revert 区别 (译)

博客原文地址: http://blog.mexiqq.com/index.php/archives/3/题记&#xff1a;团队中大多数成员使用 sourceTree 和 github 两款 git 工具&#xff0c;然而大家对于图形化工具提供的 reset,checkout,revert 功能点并不是很了解&#xff0c;甚至于混淆,然后凭借猜测去使用。功夫…

Redis笔记之基本数据结构 动态字符串SDS

简单动态字符串 传统上的C语言的字符串表示是以空字符结尾的字符数组&#xff08;C字符串&#xff09;&#xff0c;redis自己实现一个动态字符串&#xff08;SDS&#xff09;&#xff0c;两者之间的区别以及使用SDS的好处有&#xff1a; 结构不同。C字符串以空字符结尾的字符…

weakhashmap_Java WeakHashMap size()方法与示例

weakhashmapWeakHashMap类的size()方法 (WeakHashMap Class size() method) size() method is available in java.util package. size()方法在java.util包中可用。 size() method is used to get the number of key-value pairs that exist in this map. size()方法用于获取此映…

扯一把 Spring 的三种注入方式,到底哪种注入方式最佳?

1. 实例的注入方式首先来看看 Spring 中的实例该如何注入&#xff0c;总结起来&#xff0c;无非三种&#xff1a;属性注入set 方法注入构造方法注入我们分别来看下。1.1 属性注入属性注入是大家最为常见也是使用最多的一种注入方式了&#xff0c;代码如下&#xff1a;Service p…

在项目中引入领域驱动设计的经验

Chris Patuzzo近期在一次演讲中介绍了领域驱动设计&#xff08;DDD&#xff09;的原则&#xff0c;并结合一个基于Ruby on Rails的真实项目进行讲解。在这次项目之前&#xff0c;Chris所在的团队为重新设计公司的主营网站所做的两个概念验证都因为可伸缩性方面的问题而失败了。…

Redis笔记之基本数据结构 链表

链表 链表具有空间存储不连续&#xff0c;增删节点快的优点&#xff0c;因此redis在列表键、发布与订阅、慢查询、监视器等使用了链表作为底层实现。由于C语言中没有内置的链表实现&#xff0c;因此redis自己进行了实现。 双向链表。每个listtNode都有perv和next指针&#x…

treeset java_Java TreeSet iterator()方法与示例

treeset javaTreeSet类的iterator()方法 (TreeSet Class iterator() method) iterator() method is available in java.util package. iterator()方法在java.util包中可用。 iterator() method is used to iterate the elements of this TreeSet is ascending or increasing or…

SpringCloud组件:Ribbon负载均衡策略及执行原理!

大家好&#xff0c;我是磊哥。今天我们来看下微服务中非常重要的一个组件&#xff1a;Ribbon。它作为负载均衡器在分布式网络中扮演着非常重要的角色。本篇主要内容如下&#xff1a;在介绍 Ribbon 之前&#xff0c;不得不说下负载均衡这个比较偏僻的名词。为什么说它偏僻了&…

Redis笔记之基本数据结构 字典

字典 符号表、关联数组或者映射&#xff0c;有点类似于java中的map&#xff0c;用于保存键值对key-value。字典中的键key是独一无二的。底层实现为哈希表。下面进行简述&#xff1a; 哈希表。哈希表主要包含table数组、size、sizemask以及used。table用于保存哈希表节点&…

【零基础学习iOS开发】【02-C语言】02-第一个C语言程序

本文目录 前言一、编写第一个C语言程序-Hello World二、编译程序三、链接程序四、运行程序五、总结六、学习建议七、clang指令汇总回到顶部前言 前面已经唠叨了这么多理论知识&#xff0c;从这讲开始&#xff0c;就要通过接触代码来学习C语言的语法。学习任何一门语言&#xff…

安卓平板体验Java开发,还能白嫖一年阿里无影云,真香!(内含白嫖方法,人人可领)...

作者 | 磊哥来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;阿里无影云早有耳闻&#xff0c;前两天看朋友发体验照片&#xff0c;可能是程序员天生爱折腾的特性又发挥作用了&#xff0c…

Linux命令(三)

echo&#xff1a;输出信息echo ”abc”echo “字符串” |passwd --stdin USERNAME :利用管道修改用户密码输出重定向&#xff1a;>覆盖输出&#xff08;会覆盖原文件中的内容&#xff09;>>追加输出 &#xff08;原有内容会被保留&#xff09;Set –c &#xff1a…

strictmath_Java StrictMath scalb()方法与示例

strictmathStrictMath类scalb()方法 (StrictMath Class scalb() method) Syntax: 句法&#xff1a; public static double scalb(double do , int sf);public static float scalb(float fl , int sf);scalb(double do , int sf) method is used to return do* 2 raised to the…

你知道group by的工作原理和优化思路吗?

前言 日常开发中&#xff0c;我们经常会使用到group by。亲爱的小伙伴&#xff0c;你是否知道group by的工作原理呢&#xff1f;group by和having有什么区别呢&#xff1f;group by的优化思路是怎样的呢&#xff1f;使用group by有哪些需要注意的问题呢&#xff1f;本文将跟大家…

strictmath_Java StrictMath hypot()方法与示例

strictmathStrictMath类hypot()方法 (StrictMath Class hypot() method) hypot() method is available in java.lang package. hypot()方法在java.lang包中可用。 hypot() method is used to return the square root of sqrt(sq(d1)sq(d2)) without any intermediate operation…

关Jquery判断input type=checkbox元素是否被选中的判断

2019独角兽企业重金招聘Python工程师标准>>> 在用到复选框的时候&#xff0c;想在js中判断chekbox是否被选中 <input name"isPermit" id"isPermit" type"checkbox"> 百度了很多的判断方法 1、 if($("#isPermit").att…

Redis夺命十二问,你能扛到第几问?

Redis是面试中绕不过的槛&#xff0c;只要在简历中写了用过Redis&#xff0c;肯定逃不过。今天我们就来模拟一下面试官在Redis这个话题上是如何一步一步深入&#xff0c;全面考察候选人对于Redis的掌握情况。小张&#xff1a;面试官&#xff0c;你好。我是来参加面试的。面试官…

Java Scanner nextLine()方法与示例

扫描仪类nextLine()方法 (Scanner Class nextLine() method) nextLine() method is available in java.util package. nextLine()方法在java.util包中可用。 nextLine() method is used to get the skipped line. nextLine()方法用于获取跳过的行。 nextLine() method is a non…

bzoj 1192

http://www.lydsy.com/JudgeOnline/problem.php?id1192 好像学过一个东西&#xff1a; [0..2^(N1)-1]内的数都的都可以由2^0,2^1,...,2^N这N1个数中若干个相加得到。 #include<cstdio> #include<cstdlib> #include<iostream> #include<fstream> #incl…

Spring Boot Admin 报警提醒和登录验证功能实现!

作者 | 磊哥来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;Spring Boot Admin&#xff08;SBA&#xff09;是一个开源的社区项目&#xff0c;用于管理和监控 Spring Boot 应用程序&…