容器

容器主要是指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基础之自定义容器实现相关推荐

  1. Java基础知识(九) 容器

    Java基础知识 1. Java Collections 框架是什么 2. 什么是迭代器 3. ArrayList.Vector 和 LinkedList 有什么区别 4. HashMap.Hasht ...

  2. Java基础知识(十) 多线程

    Java基础知识 1. 什么是多线程?它与进程有什么区别?为什么要使用多线程 2. 同步和异步有什么区别 3. 如何实现Java多线程 4. run()方法与start()方法有什么区别 5. 多线程 ...

  3. JAVA 基础之容器集合(Collection和Map)

    目录 前言 一.Collection集合 1.1List集合 1.1.1ArrayList集合 1.1.2LinkedList集合 1.2Set集合 1.2.1HashSet集合 HashSet集合保 ...

  4. java开发之ServLet注解、自定义容器方式详解

    目录 一.为什么使用注解方式和自定义容器方式 二.注解方式步骤 1.创建javaEE8版本的web项目 2.创建一个类MyServlet继承HTTPServlet类并重写doGet()和doPost( ...

  5. JAVA基础(3)——容器(1)——常用容器分类

    JAVA基础系列规划: JAVA基础(1)--基本概念 JAVA基础(2)--数据类型 JAVA基础(3)--容器(1)--常用容器分类 JAVA基础(4)--容器(2)--普通容器 JAVA基础(5 ...

  6. java基础day11---空指针异常----引用类型--自定义类型赋值--封装

    day11 1.空指针异常--- --属于运行错误-java.long.NullPointerException --原因:当引用名称的值为null时,就不能访问某个对象中的属性或方法 热锅非要访问这 ...

  7. java基础—自定义一个比较器,对TreeSet 集合中的元素按指定方法来排序(java集合六)

    自定义一个比较器,对TreeSet 集合中的元素按指定方法来排序 import java.util.Comparator; import java.util.Iterator; import java ...

  8. Java基础篇:Java集合

    文章目录 1.概述 2.Collection接口 2.1 Collection接口方法 2.2 Iterator迭代器接口 2.3 Collection子接口之:List接口 2.4 Collecti ...

  9. [Spring 深度解析]第1章 Java基础

    第1章 ◄Java基础► 在学习Spring之前我们需要对Java基础语法有一定的了解,Java中最重要的两个知识点是注解和反射.注解和反射在Spring框架中应用的最广泛.掌握注解和反射,有助于后面 ...

最新文章

  1. pandas基于dataframe字符串数据列包含(contains)特定字符串来筛选dataframe中的数据行(rows where values contain substring)
  2. FastDFS+Nginx实现文件服务器(转载)
  3. STM32 基础系列教程 4 – 基本定时器
  4. 树莓派该文件名_树莓派学习笔记(2):常用linux命令
  5. 软件工程第八次作业-2017282110249
  6. sql 2005判断某个表或某个表中的列是否存在
  7. java contains 通配符_java删除文件支持通配符
  8. HTML CSS JS(一)
  9. esp8266 阿里云 arduino_NUCLEO-G071RB通过WiFi与NB连接阿里云
  10. mysql查看sql代价_mysql 代价
  11. apf svg matlab,【涨知识】APF和SVG的区别与联系
  12. golang goroutine实现_golang中的Mutex设计原理详解(一)
  13. 2款免费的图片压缩工具
  14. esxi查看许可过期_ESXi许可证将在 60 天后过期问题
  15. Android 矢量图动画(完结篇)
  16. 虚拟机安装Win10纯净版操作系统
  17. Java中的函数式编程(二)函数式接口Functional Interface
  18. 用户数据权利请求响应具体都包括哪些内容
  19. 测试硬盘供电不足的软件,移动硬盘供电不足怎么解决?移动硬盘供电不足的解决方法...
  20. 听java技术讲座心得体会_听讲座心得体会范文(精选3篇)

热门文章

  1. tomcat监控脚本
  2. Problem D: 顺序串的基本运算
  3. Problem G: 函数---判断日期(年月日)是否合法
  4. Find the Difference(leetcode389)
  5. webpack学习笔记1
  6. zabbix增加手机端4个url地址的返回值
  7. 李洪强iOS开发之FMDB线程安全的用法
  8. mysql学习笔记(1-安装简介)
  9. 130、 Android OkHttp完全解析(转载)
  10. 用python + openpyxl处理excel(07+)文档 + 一些中文处理的技巧