为什么有集合: 如果我们要存储一组数的时候我们肯定能想到数组来存储 但是数组是有一定缺陷的 就是数组一旦定义之后就不能改变 我们需要的是一个动态能存储数的 来保存我们的数据 那么集合就是这样的一个动态长度的一个容器 java中对于各种数据结构的实现就是通过集合管来显示的
集合的API 都在java.util包底下
Collection接口 其底下的接口就是list接口和set接口 还有队列 Queue 在list接口下面还有ArrayList 和 LinkedList Vector (线程安全 但是一般不常用 )
而在Set接口底下是HashSet 和 TreeSet
ArrayList : 底层是通过 数组实现的 和数组的区别就是 数组是一旦定义了长度就不能改变了 而ArrayList定义只有长度是可以通过扩容机制来改变的 2 数组中存储的基本数据类型 而ArrayList则存储的是基本类型的封装类型 缺点也有就是在存储的时候会出现不断的装箱的过程因此从性能来考虑的时候 存储基本数据类型的时候还是得使用数组
LinkedList: 底层使用了双向链表 使用双向链表的优点就是插入和删除快 查询和修改相较于ArrayList来说还是比较慢的 都是通过add和get方法来增加和获取元素
HashSet : 单列集合 里面不能放重复元素
如何保证 HashSet里面的元素不重复 我们可以用源码分析一下
HashSet<String> hashSet = new HashSet<>();
hashSet.add("a");
hashSet.add("b");
hashSet.add("c");
hashSet.add("d");
hashSet.add("a");
System.out.println(hashSet);
结果是显而易见的 答案是abcd 这个底层肯定是不能通过equals进行比较 我们看见的equals都是重写过来的 如果你直接调用equals方法是Object的 而在Object中的equals是比较的对象地址 其它类中比较的是内容是否相等 而且equals效率低; HashSet 底层是通过hashCode和equals方法来实现去重操作的你而在Object中的hashCode()方法是根据内存中的地址的hash值 而在其它方法里面重写了的hashCode则是通过内容来计算出来的哈希值
Collection单链集合的顶级接口 底下有List接口 有ArrayList() 和 LinkedList()和 Set接口 有HashSet() 和 TreeSet() 而List是可重复的 只能存储引用类型 通过泛型来设置集合中存储的类型 Map接口 有 HashMap() TreeMap() HashTable()
ArrayList() 特点 查询快修改 增删慢 底层是由数组实现的
LinkedList() 特点 增删快 遍历查询慢(必须从头遍历) 底层是链表实现的
Vector() 特点 线程安全 底层是数组
ArrayList()源码分析 ; 底层会创建一个长度为10的数组 当ArrayList满了之后会扩容为原来的1.5倍 右移一位 通过grow()方法扩容
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
LinkedList() 要查找的元素大于 size/2 是从尾结点开始查找 否则从头结点开始查找
HashMap 键不能重复, 值可以重复键是 无序 可以存储一个为null的键 数组链表红黑树 当链表长度为8 且 数组长度大于64的时候 就会转为红黑树 初始长度为 16 每次扩容为原来的二倍 负载因子为0.75 扩容的方法为 resize()
Hashtable键不能重复,值可以重复 键是无序 不可以存储一个为null的键和值 是线程安全的.
TreeMap 键不能重复,值可以重复 键可以排序,作为键类型的类必需实现排序接口
HashSet不能存储重复的元素 当有hash 值相同的元素加进去的时候 会用equals方法来判断它们是否是同一种元素 内容是否相同