一、集合基本特性
1 概述
数组长度是固定,当添加的元素超过了数组的长度时需要对数组重新定义,太麻烦,java内部给我们提供了集合类,能存储任意对象,长度是可以改变的,随着元素的增加而增加,随着元素的减少而减少。
2 数组与集合区别
(1)数组既可以存储基本数据类型,又可以存储引用数据类型,基本数据类型存储的是值,引用数据类型存储的是地址值;
集合只能存储引用数据类型(对象)集合中也可以存储基本数据类型,但是在存储的时候会自动装箱变成对象
(2)数组长度是固定的,不能自动增长;集合的长度的是可变的,可以根据元素的增加而增长
3 使用场景
如果元素个数是固定的推荐用数组;
如果元素个数不是固定的推荐用集合
二 、Java集合框架架构图
(UML类图相关说明:http://8aa512c4.wiz03.com/share/s/2aFhb41ayQ4W29lNzu3wxPge3lBgTt0N3A9H2j7Wdu0Ovgo_
)
三、Iterator
1 迭代器原理
迭代器是对集合进行遍历,而每一个集合内部的存储结构都是不同的,所以每一个集合存和取都是不一样, 那么就需要在每一个类中定义hasNext()和next()方法,这样做是可以的, 但是会让整个集合体系过于臃肿,迭代器是将这样的方法向上抽取出接口, 然后在每个类的内部,定义自己迭代方式, 这样做的好处有二,第一规定了整个集合体系的遍历方式都是hasNext()和next()方法,第二,代码有底层内部实现,使用者不用管怎么实现的,会用即可。
2 常用方法
next()方法返回迭代的下一个元素。
hashNext()如果仍有元素可以迭代返回true。
remove()从迭代器指向的集合中移除最后一个元素。
3 应用场景
(1)并发修改异常产生的原因及解决方案?
有一个集合,请问,我想判断里面有没有"world"这个元素,如果有,我就添加一个"javaee"元素,请写代码实现。
List list = new ArrayList(); list.add("a"); list.add("b"); list.add("world"); list.add("d"); list.add("e"); /*Iterator it = list.iterator(); while(it.hasNext()) { String str = (String)it.next(); if(str.equals("world")) { list.add("javaee"); //这里会抛出ConcurrentModificationException并发修改异常 } }*/
(2)迭代器遍历的过程中集合是不允许修改的。
(3)解决方案。
迭代器遍历元素的过程中如果需要修改请采用ListIterator(特有功能)。
ListIterator lit = list.listIterator(); //如果想在遍历的过程中添加元素,可以用ListIterator中的add方法 while(lit.hasNext()) { String str = (String)lit.next(); if(str.equals("world")) { lit.add("javaee"); } }
(4)Enumeration和Iterator接口的区别?
Enumeration的速度是Iterator的两倍,也使用更少的内存。Enumeration是非常基础的,也满足了基础的需要。但是,与Enumeration相比,Iterator更加安全,因为当一个集合正在被遍历的时候,它会阻止其它线程去修改集合。 迭代器取代了Java集合框架中的Enumeration。迭代器允许调用者从集合中移除元素,而Enumeration不能做到。为了使它的功能更加清晰,迭代器方法名已经经过改善。
4 ListIterator
(1)常用方法
boolean hashNext()是否有下一个
Object next() 返回下一个元素
Object hasPrevious()是否有前一个
Object previous() 返回上一个元素
...add set 等方法
5 ListIterator与Iterator的区别?
从以上内容中也可以总结出ListIterator与Iterator的区别:ListIterator遍历只针对List集合而Iterator遍历操作是针对所有集合的
Iterator 对集合只能是前向遍历,ListIterator 既可以前向也可以后向。
ListIterator 实现了 Iterator 接口,并包含其他的功能,比如:增加元素,替换元素,获取前一个和后一个元素的索引,等等。
四、List集合
1 List集合特点
ArrayList: 底层数据结构是数组,查询快,增删慢。线程不安全,效率高。 Vector:底层数据结构是数组,查询快,增删慢。 线程安全,效率低。 Vector相对ArrayList查询慢(线程安全的) Vector相对LinkedList增删慢(数组结构) LinkedList: 底层数据结构是链表,查询慢,增删快。 线程不安全,效率高。 Vector和ArrayList的区别:(1)Vector是线程安全的,效率低;ArrayList是线程不安全的,效率高。(2)共同点:都是数组实现的 ArrayList和LinkedList的区别(1)ArrayList底层是数组结构,查询和修改快(2) LinkedList底层是链表结构的,增和删比较快,查询和修改比较慢 共同点:都是线程不安全的 使用说明:查询多用ArrayList;增删多用LinkedList;如果都多ArrayList
2 Vector集合特点
(1)Vector特有功能
public void addElement(E obj)public E elementAt(int index)public Enumeration elements()
(2)使用示例
Vector v = new Vector(); //创建集合对象,List的子类 v.addElement("a"); v.addElement("b"); v.addElement("c"); v.addElement("d"); //Vector迭代 Enumeration en = v.elements(); //获取枚举 while(en.hasMoreElements()) { //判断集合中是否有元素 System.out.println(en.nextElement());//获取集合中的元素 }
(3)Vector不推荐使用的原因?
Vector所有方法都是同步,有性能损失。
Vector早期版本出现的。
Vector初始length是10 超过length时 以100%比率增长,相比于ArrayList更多消耗内存。
五、Set集合(接口)
1 概述
(1)set集合特点无序,不允许重复。常用的实现类有HashSet ,TreeSet。特点见下图
(2)资料参考:http://blog.csdn.net/zhangweiiou/article/details/48946623
2 HashSet
HashSet原理
(1)HashSet继承了AbstractSet实现了Set接口,在底层使用HashMap的key进行元素存储,从而保证了元素的唯一性。
(2)我们使用Set集合都是需要去掉重复元素的, 如果在存储的时候逐个equals()比较, 效率较低,哈希算法提高了去重复的效率, 降低了使用equals()方法的次数
(3)当HashSet调用add()方法存储对象的时候, 先调用对象的hashCode()方法得到一个哈希值, 然后在集合中查找是否有哈希值相同的对象,如果没有哈希值相同的对象就直接存入集合,如果有哈希值相同的对象, 就和哈希值相同的对象逐个进行equals()比较,比较结果为false就存入, true则不存
将自定义类的对象存入HashSet去重复
类中必须重写hashCode()和equals()方法
hashCode(): 属性相同的对象返回值必须相同, 属性不同的返回值尽量不同(提高效率)
equals(): 属性相同返回true, 属性不同返回false,返回false的时候存储
3 TreeSet
概述:
TreeSet是用来排序的, 可以指定一个顺序, 对象存入之后会按照指定的顺序排列。
用法:
a.自然顺序(Comparable)TreeSet类的add()方法中会把存入的对象提升为Comparable类型调用对象的compareTo()方法和集合中的对象比较根据compareTo()方法返回的结果进行存储b.比较器顺序(Comparator)创建TreeSet的时候可以指定 一个Comparator如果传入了Comparator的子类对象, 那么TreeSet就会按照比较器中的顺序排序add()方法内部会自动调用Comparator接口中compare()方法排序调用的对象是compare方法的第一个参数,集合中的对象是compare方法的第二个参数c.两种方式的区别TreeSet构造函数什么都不传, 默认按照类中Comparable的顺序(没有就报错ClassCastException)TreeSet如果传入Comparator, 就优先按照Comparator
Comparable接口:
定义:此接口强行对实现它的每个类进行整体排序,此排序称为自然排序。实现此接口的对象列表(和数组)可以通过 Collections.sort(和 Arrays.sort)进行自动排序。(默认排序升序)对于类 C 的每一个 e1 和 e2 来说,当且仅当 e1.compareTo(e2) == 0 与 e1.equals(e2) 具有相同的 boolean 值时,类 C 的自然排序才叫做与 equals 一致。注意,null 不是任何类的实例,即使 e.equals(null) 返回 false,e.compareTo(null) 也将抛出 NullPointerException。
方法: compareTo(T o) 比较此对象与指定对象的顺序。
http://blog.csdn.net/nvd11/article/details/27393445
Java集合框架中的工具类
1 概述:集合框架中的工具类有Arrays和Collections两种。
2 Arrays: 此类包含了用来操作数组的各种方法如:搜索,排序。
应用场景之 - 数据与集合的转换
(1)集合转数组:
String [] strArr = list.toArray(new String[list.size()]);
(2)数组转集合:
Integer[]arr = {11,22,33,44,55};List<Integer> list = Arrays.asList(arr);
3 Collections 操作集合的工具类
集合迭代的三种方式总结
区别
(1)普通for循环,可以删除
(2)迭代器,可以删除,但是必须使用迭代器自身的remove方法,否则会出现并发修改异常
(3)增强for循环不能删除
掌握增强for循环的内部实现原理
for(type element: array)
{
System.out.println(element);
}
集合中的几个概念
1 集合初始化容量;负载因子;扩充容量说明;http://www.cnblogs.com/xiezie/p/5511840.html
负载因子:比如说散列表长度为m,其中有n个位置已放了值,那么负载因子 a=n/m。
2 fail-fast 机制是java集合(Collection)中的一种错误机制。
fail-fast机制在遍历一个集合时,当集合结构被修改(同步修改),会抛出Concurrent Modification Exception。
解决办法采用:CopyOnWriteArrayList(类)。对以上内容涉及到的概念进行如下说明:
fail-safe机制
:保证任何对集合的修改操作都会在一个复制集合上操作。因此不会抛出ConcurrentModificationException异常。产生两个问题1)复制集合会产生大量临时对象,增大系统开销。2)无法保证读取的数据是原始数据结构中的数据。
2.1什么叫同步修改?
当一个线程正在遍历一个集合时,此时又有另一个线程修改了集合的内容(添加,删除,或修改)这就叫做同步修改(并发修改)。
2.2fail-fast是如何检测的?
为了保证集合在遍历的过程中不被修改,迭代器内部维护了一个标记“
modCount
”,当集合发生改变内部标记“
modCount
”也会发生改变,而迭代器每次在遍历集合的过程中hashNext()和next()都会检查这个标记,当发现这个标记发生改变了就会抛出,
ConcurrentModificationException异常。