集合

一.集合概述

为了保存数量不确定的数据,以及保存具有映射关系的数据,Java提供了集合类。集合类主要负责保存,盛装其他数据,因此集合类也被称为容器类。集合类和数组不一样,数组元素既可以是基本类型的值,也可以是对象(实际上保存的是对象的引用变量);而集合只能保存对象(实际上只是保存对象的引用变量)。

Java的集合类主要由两个接口派生而出:ConnectionMapConnectionMapJava集合框架的根接口,这两个接口又包含了一些子接口或实现类。

 

                                Connection集合体系

Set:无序集合

List:有序集合

HashMap:线程不安全,keyvalue允许为null

Hashtable:线程安全,key,value不允许为null

从上图可以看出,如果访问List集合中的元素,可以直接根据元素的索引来访问;如果访问Map集合中的元素,可以根据每项的key来访问其value;如果访问Set集合中的元素,则只能根据元素本身来访问(这也是Set集合里面的元素不允许重复的原因)。

二.CollectionIterator接口

CollectionList,SetQueue接口的父接口,该接口里定义的方法既可以用于操作Set集合,也可用于操作ListQueue集合。

集合类就像容器,显示生活中的容器,无非就是添加对象,删除对象,情况对象,判断对象是否为空等。

2.1 使用Lambda表达式遍历集合

Java8Iterable接口新增了一个forEach(Consumer action)默认方法,该方法所需参数的类型是一个函数式接口,而Iterable接口是Collection接口的父接口,因此Collection集合也可直接调用该方法。

当程序调用IterableforEach(Cousumer action)遍历集合元素时,程序会依次将集合元素传给ConsumeracceptT t)方法(该接口的唯一抽象方法)。正因为Consumer是函数式接口,因此使用Lambda表达式来遍历集合元素。

books.forEach(obj -> System.out.println("迭代集合元素:"+obj));

代码调用了IterableforEach()默认的方法来遍历集合元素,传给该方法的参数是一个Lambda表达式,该Lambda表达式的目标类型是ComsumerforEach()方法会自动将集合元素逐个的传给Lambda表达式的形参,这样Lambda表达式的代码体即可遍历到集合元素了。

三.Set集合

Set集合不允许包含相同的元素,如果试图把两个相同的元素加入到同一个Set集合中,则添加操作失败,add()方法返回false,且新元素不会被加入。

3.1 HashSet

   HashSet具有以下特点:

(1)不能保证元素的排列顺序,顺序可能与添加顺序不同,顺序也有可能发生变化。

(2)HashSet不是同步的,如果多个线程同时访问一个HashSet,假设有两个或两个以上线程同时修改了HashSet集合时,则必须通过代码来保证其同步。

(3)集合元素值可以是null

     HashSet集合判断两个元素是否相等的标准是两个对象通过equals()方法比较相等,并且两个对象的hashCode()方法返回值也相等。

3.2 LinkHashSet

     当遍历LinkedHashSet集合里的元素的时候,LinkedHashSet将会按照元素的添加顺序来访问集合中的元素。

3.3 TreeSet

   TreeSet可以确保集合元素处于排序状态。

3.4 EnumSet

   Enum中的所有元素都必须是指定枚举类型的枚举值,该枚举类型在创建EnumSet时显式或隐式的指定。EunmSet的元素集合也是有序的,EnumSet以枚举值在Enum类内的定义顺序来决定集合元素的顺序。

3.5 Set实现类的性能分析

   HashSet的性能总是比TreeSet好,因为TreeSet需要额外的红黑树算法来维护集合元素的次序,这是由维护链表所带来的额外开销造成的,但由于有了链表,遍历LinkedHashSet会更快。

   EnumSet是所有Set实现类中性能最好的,但它只能保存同一个枚举类的枚举值作为元素集合。

四.各种线性表的性能分析

   Java提供的List就是一个线性表接口,而ArrayListLinkedList又是线性表的两种典型实现:基于数组的线性表和基于链的线性表。Queue代表了队列,Deque代表了双端队列(既可以作为队列使用,又可以作为栈使用)

   LinkedList集合不仅提供了List的功能,还提供了了双端队列,栈的功能。

   一般来说,由于数组以一组连续的内存区来保存所有的数组元素,所以数组在随机访问时性能最好,所有的内部都以数组作为底层实现的集合在随机访问时性能都比较好;而内部以链表作为底层实现的集合在执行插入,删除操作时有较好的的性能。但总体来说,ArrayList的性能比LinkedList的性能要好,因此,大部分时候都应该考虑使用ArrayList

(1)如果要遍历List集合元素,对于ArrayList,Vetor集合,应该使用随机访问方法(get)来遍历集合元素,这样性能最好;对于LinkedList集合,则应该使用迭代器(Iterator)来遍历元素。

(2)如果需要经常插入,删除操作来改变包含大量数据的List集合的大小,可考虑使用LinkedList集合。使用ArrayList,Vetor集合可能要经常重新分配内部数组的大小,效果可能较差。

(3)如果有多个线程需要同时访问List集合中的元素,开发者可考虑使用Collection将集合包装成线程安全的集合。

原文地址:https://www.cnblogs.com/wangjian666/p/12150720.html