容器
容器主要是指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