集合是一个用来存放对象的容器。
注意:①、集合只能存放对象。比如你存一个 int 型数据 1放入集合中,其实它是自动转换成 Integer 类后存入的,Java中每一种基本类 型都有对应的引用类型。
②、集合存放的是多个对象的引用,对象本身还是放在堆内存中。
③、集合可以存放不同类型,不限数量的数据类型。
集合主要分为两大类:
Iterable接口 和 Map接口
实现Collection 接口 的接口和类 实现了 Iterable接口 , 可以调用Iterator进行迭代。
为什么不直接实现Iterator接口?因为Iterator的.next()方法都是基于当前位置的,会保留指针位置,当集合在不同方法间被传递时,由于当前迭代位置不可预置,那么next()方法的结果会变成不可预知。,使用Iterator只能添加reset()方法,用来重置当前迭代位置。实现Iterable接口每次调用迭代返回 都是一个重新计数的迭代器,且各个迭代器之间互不干扰。
Object next():返回迭代器刚越过的元素的引用,返回值是 Object,需要强制转换成自己需要的类型
boolean hasNext():判断容器内是否还有可供访问的元素
void remove():删除迭代器刚越过的元素
Set s=new HashSet();
Iterator i=s.iterator();
while(i.hasNext()){
Object obj=i.next();
1. ArrayList |
1.1.排列有序,可重复 |
1.2 底层使用数组 |
1.3 速度快,增删慢,getter()和setter()方法快 |
1.4 线程不安全 ArrayList是非线程安全的,即它没有同步,不过,可以通过Collections.synchronizedList()静态方法返回一个同步的实例,如: List synList = Collections.synchronizedList(list); |
1.1.1.5 当容量不够时,ArrayList是当前容量 * 1.5 + 1 |
2 Vector |
2.1 排列有序,可重复 |
2.2 底层使用数组 |
2.3 速度快,增删慢 |
2.4 线程安全,效率低 |
2.5 当容量不够时,Vector默认扩展一倍容量 |
3 LinkedList |
3.1 排列有序,可重复 |
3.2 底层使用双向循环链表数据结构 |
3.3 查询速度慢,增删快,add()和remove()方法快 |
3.4 线程不安全 |
注意: HashSet
1.HashSet先调用HashCode方法算出Hash值,对比Hash值.相同进行下一步(建议重写HashCode方法)
2.调用对象的Equals方法(建议重写Equals方法)
1.1 排列无序, 不可重复
1.2 底层使用Hash表实现
1.3 存取速度快
1.4 内部是HashMap
HashSet的实现原理总结如下:
①是基于HashMap实现的,默认构造函数是构建一个初始容量为16,负载因子为0.75 的HashMap。封装了一个 HashMap 对象来存储所有的集合元素,所有放入 HashSet 中的集合元素实际上由 HashMap 的 key 来保存,而 HashMap 的 value 则存储了一个 PRESENT,它是一个静态的 Object 对象。
②当我们试图把某个类的对象当成 HashMap的 key,或试图将这个类的对象放入 HashSet 中保存时,重写该类的equals(Object obj)方法和 hashCode() 方法很重要,而且这两个方法的返回值必须保持一致:当该类的两个的 hashCode() 返回值相同时,它们通过 equals() 方法比较也应该返回 true。通常来说,所有参与计算 hashCode() 返回值的关键属性,都应该用于作为 equals() 比较的标准。
③HashSet的其他操作都是基于HashMap的。
2 TreeSet
注意:TreeSet
1.元素具备自然排序的特点,就按照自然顺序进行排序
2.如果元素不具备自然排序的特点,那么元素需要实现Comparable接口,自定义比较规则,重写CompareTo方法
2.1 排列有序, 不可重复
2.2 底层使用二叉树实现
2.3 排序存储
2.4 内部是TreeMap的SortedSet
2.5非线程安全的
3 LinkedHashSet
3.1 采用hash表存储,并用双向链表记录插入顺序
3.2 内部是LinkedHashMap
3.3 非线程安全的
3.4 存储元素的顺序是按照元素的插入顺序存储
注:双向链表每个结点除了自身的数值域之外还有两个指针域,分别指向前驱结点和后继结点。
1 Queue |
1.3.1 在两端出入的List,所以也可以用数组或链表来实现 |
Deque接口是Queue接口的子接口,代表一个双端队列。同时Deque不仅可以作为双端队列使用,而且可以被当成栈来使用,所以可以使用出栈,入栈的方法。
Queue中方法:
add 增加一个元索 如果队列已满,则抛出一个IIIegaISlabEepeplian异常
remove 移除并返回队列头部的元素 如果队列为空,则抛出一个NoSuchElementException异常
element 返回队列头部的元素 如果队列为空,则抛出一个NoSuchElementException异常
offer 添加一个元素并返回true 如果队列已满,则返回false
poll 移除并返问队列头部的元素 如果队列为空,则返回null
peek 返回队列头部的元素 如果队列为空,则返回null
put 添加一个元素 如果队列满,则阻塞
take 移除并返回队列头部的元素 如果队列为空,则阻塞
ArrayQueue实现了Queue
/**
* peek(),element()该方法获取队列头部的元素,但是不删除该元素。
* poll()该方法也是获取队列头部的元素,但是删除该元素。
*/
ArrayDeque stack = new ArrayDeque();
stack.push(2);
stack.push(5);
stack.peek();
stack.pop();
TreeMap--实现--->NavigableMap----实现---->SortedMap---继承-->Map
HashMap
键不可重复,值可重复
底层哈希表 (数组+链表/红黑树)
当链表长度为8时,链表转成红黑树。长度减少至6时,由红黑树转成链表。
线程不安全
允许key值为null,value也可以为null
2 hashtable
键不可重复,值可重复
底层哈希表(数组+链表)
线程安全
key、value都不允许为null
TreeMap
键不可重复,值可重复
底层黑红二叉树
1. Properties:
1) 它是Hashtable的子类,专门用来读取属性文件(如Win中的ini文件等);
2) 由于它继承自Hashtable,因此它底层就是Map,只不过Properties这个Map有点儿特殊:
i. 专门用来将Map和属性文件关联(可以将属性文件中的key=value对加载到程序中成为Map,也可以将Map写入属性文件,就是以“key=value”的形式写入);
ii. 由于属性文件中的key-value都是字符串,因此Properties的key-value也只能存放字符串(String);
3) Properties的专用对象方法(用来和属性文件关联,并以属性文件的形式访问Map中的内容):使用这个类就是专门关联和处理属性文件的,不要把它当成一个Map来使用(要有好的习惯,因为当成纯Map使用,由于它是Hashtable,因此不是特别好,就只用它关联属性文件的功能):
2. LinkedHashMap:
1) 就像LinkedHashSet之于HashSet,LinkedHashMap用一张额外链表维护Entry的插入顺序,并且迭代的时候更加高效;
2) LinkedHashMap在用forEach默认方法迭代时底层就是对这张额外的链表进行迭代,因此迭代最好优先选用forEach方法;
3.TreeMap:基于红黑二叉树的NavigableMap的实现,线程非安全,不允许null,key不可以重复,value允许重复,存入TreeMap的元素应当实现Comparable接口或者实现Comparator接口,会按照排序后的顺序迭代元素,两个相比较的key不得抛出classCastException。主要用于存入元素的时候对元素进行自动排序,迭代输出的时候就按排序顺序输出