Java-Collection

来源:互联网 发布:转行做网络运营 编辑:程序博客网 时间:2024/06/14 11:16

一、集合基本特性


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"元素,请写代码实现。
  1. List list = new ArrayList();
  2. list.add("a");
  3. list.add("b");
  4. list.add("world");
  5. list.add("d");
  6. list.add("e");
  7. /*Iterator it = list.iterator();
  8. while(it.hasNext()) {
  9. String str = (String)it.next();
  10. if(str.equals("world")) {
  11. list.add("javaee"); //这里会抛出ConcurrentModificationException并发修改异常
  12. }
  13. }*/
(2)迭代器遍历的过程中集合是不允许修改的。
(3)解决方案。
 迭代器遍历元素的过程中如果需要修改请采用ListIterator(特有功能)。
  1. ListIterator lit = list.listIterator();
  2. //如果想在遍历的过程中添加元素,可以用ListIterator中的add方法
  3. while(lit.hasNext()) {
  4. String str = (String)lit.next();
  5. if(str.equals("world")) {
  6. lit.add("javaee");
  7. }
  8. }
(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集合特点

  1. ArrayList: 底层数据结构是数组,查询快,增删慢。线程不安全,效率高。
  2. Vector:底层数据结构是数组,查询快,增删慢。 线程安全,效率低。
  3. Vector相对ArrayList查询慢(线程安全的)
  4. Vector相对LinkedList增删慢(数组结构)
  5. LinkedList: 底层数据结构是链表,查询慢,增删快。 线程不安全,效率高。
  6. Vector和ArrayList的区别:
  7. (1)Vector是线程安全的,效率低;ArrayList是线程不安全的,效率高。
  8. (2)共同点:都是数组实现的
  9. ArrayList和LinkedList的区别
  10. (1)ArrayList底层是数组结构,查询和修改快
  11. (2) LinkedList底层是链表结构的,增和删比较快,查询和修改比较慢
  12. 共同点:都是线程不安全的
  13. 使用说明:查询多用ArrayList;增删多用LinkedList;如果都多ArrayList

2 Vector集合特点

(1)Vector特有功能
  1. public void addElement(E obj)
  2. public E elementAt(int index)
  3. public Enumeration elements()
(2)使用示例
  1. Vector v = new Vector(); //创建集合对象,List的子类
  2. v.addElement("a");
  3. v.addElement("b");
  4. v.addElement("c");
  5. v.addElement("d");
  6. //Vector迭代
  7. Enumeration en = v.elements(); //获取枚举
  8. while(en.hasMoreElements()) { //判断集合中是否有元素
  9. System.out.println(en.nextElement());//获取集合中的元素
  10. }
(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是用来排序的, 可以指定一个顺序, 对象存入之后会按照指定的顺序排列。
用法:
  1. a.自然顺序(Comparable)
  2. TreeSet类的add()方法中会把存入的对象提升为Comparable类型
  3. 调用对象的compareTo()方法和集合中的对象比较
  4. 根据compareTo()方法返回的结果进行存储
  5. b.比较器顺序(Comparator)
  6. 创建TreeSet的时候可以指定 一个Comparator
  7. 如果传入了Comparator的子类对象, 那么TreeSet就会按照比较器中的顺序排序
  8. add()方法内部会自动调用Comparator接口中compare()方法排序
  9. 调用的对象是compare方法的第一个参数,集合中的对象是compare方法的第二个参数
  10. c.两种方式的区别
  11. TreeSet构造函数什么都不传, 默认按照类中Comparable的顺序(没有就报错ClassCastException)
  12. 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)集合转数组:
  1. String [] strArr = list.toArray(new String[list.size()]);
(2)数组转集合:

  1. Integer[]arr = {11,22,33,44,55};
  2. 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异常。