------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ------
Java集合类是一种特别有用的工具类,可以用于存储数量不等的多个对象,并可以实现常用的数据结构,如栈、队列等。除此之外,java集合还可以用于保存具有映射关系的关系数组。Java集合大致可分为Set、List和Map三种体系,其中Set代表无序、不可重复的集合;List代表有序、重复的集合;而Map则代表具有映射关系的集合。
下图是集合框架图:
上图包括:
1、集合接口:6个接口(短虚线表示),表示不同集合类型,是集合框架的基础。
2、抽象类:5个抽象类(长虚线表示),对集合接口的部分实现。可扩展为自定义集合类。
3、实现类:8个实现类(实线表示),对接口的具体实现。
在很大程度上,一旦您理解了接口,您就理解了框架。虽然您总要创建接口特定的实现,但访问实际集合的方法应该限制在接口方法的使用上;因此,允许您更改基本的数据结构而不必改变其它代码。
1、Collection接口
Collection接口是List、Set的父接口,该接口里定义了如下操作集合元素的方法。
1、单元素添加、删除操作:
boolean add(Object o):将对象添加给集合
boolean remove(Object o): 如果集合中有与o相匹配的对象,则删除对象o
2、查询操作:
int size() :返回当前集合中元素的数量
boolean isEmpty() :判断集合中是否有任何元素 boolean contains(Object o) :查找集合中是否含有对象o
Iterator iterator() :返回一个迭代器,用来访问集合中的各个元素
3、组操作 :作用于元素组或整个集合
boolean containsAll(Collection c): 查找集合中是否含有集合c 中所有元素
boolean addAll(Collection c) : 将集合c 中所有元素添加给该集合
void clear(): 删除集合中所有元素
void removeAll(Collection c) : 从集合中删除集合c 中的所有元素
void retainAll(Collection c) : 从集合中删除集合c 中不包含的元素
4、Collection转换为Object数组 :
Object[] toArray() :返回一个内含集合所有元素的array
Object[] toArray(Object[] a) :返回一个内含集合所有元素的array。运行期返回的array和参数a的型别相同,需要转换为正确型别。
此外,您还可以把集合转换成其它任何其它的对象数组。但是,您不能直接把集合转换成基本数据类型的数组,因为集合必须持有对象。
2、Set集合
Set集合和Collection基本上完全一样,它没有提供任何额外的方法,只是Set不允许包含重复元素。下面将分别介绍Set的三个实现类:HsahSet、TreeSet和EnumSet。
2.1 HashSet类
HashSet底层数据是哈希表,当add()方法向HashSet集合中存放一个元素时,HashSet会调用对象的hashCode()方法来得到对象的HashCode值,然后根据该HashCode值决定该对象在HashSet中的存储位置。如果两个元素通过equals()方法比较返回true,但他们的HashCode()方法返回值不相等。HashSet将会把它们存储在不同的位置,依然可以添加成功。
简单的说,HashSet集合判断两个元素相等的标准是两个对象通过equals方法比较相等,并且两个对象的HashCode方法返回值也相等。
如果HashCode值不同,则不会调用equals()方法。
2.2 TreeSet类
TreeSet是SortedSet接口的实现类,可以确保集合元素处于排序状态。它的底层数据是二叉树数据结构,有两种排序方式:
2.2.1 自然排序
TreeSet会调用集合元素的compaerTo(Object obj)方法来比较元素之间的大小关系,然后将集合按升序排列,也称自然排列。
Java提供了一个Comparable接口,该接口定义了一个CompreTo(Object obj)方法,该方法返回一个整数值,实现该接口的类必须实现该方法,那么实现了该接口的类的对象就可以比较大小。当一个对象调用该方法与另一个对象进行比较时,例如obj1.compareTo(obj2),如果该方法返回0,表明相等;如果返回一个正整数,则表明obj1大于obj2;如果该方法返回一个负整数,则表明obj1小于obj2。
如果试图把一个对象加入到TreeSet时,则该对象的类必须实现Comparable接口,否则程序将会抛出异常。
注意:向TreeSet集合添加元素时,只有第一个元素无须实现Comparable接口,后面添加的都必须实现。
2.2.2 定制排序
TreeSet的自然排序是根据元素的大小,TreeSet将它们升序排列。如果需要实现定制排序,例如降序排列,则可以通过Comparator接口的帮助。该接口包含一个compare(T o1,T o2)方法,该方法用于比较o1和o2的大小:如果该方法返回正整数,则表明o1大于o2;如果该方法返回0,则表明等于;如果返回负整数,则表明小于。
具体的方法是:定义一个类实现Comparator接口,并复写compare方法,然后将该类的实例作为参数传到TreeSet集合的构造函数中去。
2.3EnumSet类
EnumSet类是一个专为枚举类设计的集合类,EnumSet中的所有元素都必须是指定枚举类型的枚举值,给枚举类型在创建EnumSet是显式或隐式地指定。EnumSet的集合元素也是有序的,它以枚举值在Enum类内的定义顺序来决定集合元素的顺序。
EnumSet内部是以向量的形式存储,这种存储方式非常紧凑、高效,因此EnumSet对象占用内存很小,运行效率很好。尤其是进行批量操作时,如果参数也是EnumSet集合,则该批量操作的执行速度也非常快。
它的常用方法如下:
1.Static EnumSet allOf(class elementType):创建一个包含指定枚举类里所有枚举值的EnumSet集合。 2.Static EnumSet complementOf(EnumSet s):创建一个其元素类型与指定EnumSet里元素类型相同的EnumSet集合。 3.Static EnumSet copyOf(Collection c): 使用一个普通集合来创建EnumSet集合。 4.Static EnumSet nonOf(Class elementType): 创建一个元素类型为指定枚举类型的空EnumSet。
3、List集合
List集合代表一个元素有序、可重复的集合,集合中每个元素都有其对应的顺序索引。List集合允许使用重复元素,可以通过索引来访问指定位置的集合元素。List除了拥有Collection接口里的全部方法外,还增加了一些根据索引来操作集合元素的方法,具体如下:
1.void add(int dindex,Object element):将元素element插入到List集合的index处 2.boolean addAll(int index,Collection c):将集合c所包含的所有元素都插入到List集合的index处 3.Object get(int index):返回集合index索引处的元素 4.int indexOf(Object o):返回对象o在List集合中第一次出现的位置索引 5.int lastIndexOf(Object o):返回对象o在List集合中最后一次出现的位置索引 6.Object remove(int index):删除并返回index索引处的元素 7.Object set(int index,Object element):将索引处的元素替换成element对象,返回新元素。
所有的List实现类都可以调用这些方法来操作集合元素。与Set集合相比,List增加了根据索引来插入、替换和删除集合元素的方法。
3.1 ArrayList实现类
ArrayList底层是数组数据结构,特点是查询快,增删稍慢。 ArrayList是List接口的可变数组的实现。实现了所有可选列表操作,并允许包括 null 在内的所有元素。除了实现 List 接口外,此类还提供一些方法来操作内部用来存储列表的数组的大小。
每个ArrayList实例都有一个容量,该容量是指用来存储列表元素的数组的大小。它总是至少等于列表的大小。随着向ArrayList中不断添加元素,其容量也自动增长。自动增长会带来数据向新数组的重新拷贝,因此,如果可预知数据量的多少,可在构造ArrayList时指定其容量。在添加大量元素前,应用程序也可以使用ensureCapacity操作来增加ArrayList实例的容量,这可以减少递增式再分配的数量。
注意:此实现不是同步的。如果多个线程同时访问一个ArrayList实例,而其中至少一个线程从结构上修改了列表,那么它必须保持外部同步。
3.2 LinkedList实现类
LinkedList 类底层是链表结构,特点是增删快,查询慢。此类实现 Queue 接口,为 add、poll 等提供先进先出队列操作。其他堆栈和双端队列操作可以根据标准列表操作方便地进行再次强制转换。虽然它们可能比等效列表操作运行稍快,但是将其包括在这里主要是出于方便考虑.
1、增加
addFirst();
addLast();
2、获取元素,但不删除元素。如果集合中没有元素,会出现NoSuchElementException
getFirst();
getLast();
3、获取元素,并删除元素。如果集合中没有元素,会出现NoSuchElementException
removeFirst();
removeLast();
在JDK1.6以后,出现了替代方法。
1、增加
offFirst();
offLast();
2、获取元素,但是不删除。如果集合中没有元素,会返回null。
peekFirst();
peekLast();
3、获取元素,并删除元素。如果集合中没有元素,会返回null。
pollFirst();
pollLast();、
4、Map集合
Map用于保存具有映射关系的数据,因此Map集合里保存着两组值,一组用于存储key,另一组用于保存Value,key和value都可以是任何引用类型的数据。Map的Key不允许重复,即同一个Map对象的任何两个key通过equals方法比较总是返回false。
Key和value之间存在单向一对一关系,即通过指定的key总能找到唯一的、确定的value。它的子类如下:
1.Hashtable:底层是哈希表数据结构,不可以存入null键null值。该集合是线程同步的。JDK1.0,效率低。
2.HashMap:底层是哈希表数据结构。允许使用null键null值,该集合是不同步的。JDK1.2,效率高。
3. TreeMap:底层是二叉树数据结构。线程不同步。可以用于给Map集合中的键进行排序。
下面是Map类的常用方法:
1.添加:
value put(key,value):返回前一个和key关联的值,如果没有返回null交
2.判断:
boolean containsKey(key)
boolean containsValue(key)
boolean isEmpty();
3.获取:
value get(key):通过键获取值,如果没有该键,返回null。可以通过返回空来判断是否包含指定键
int size():获取键值的对数
下面是Map集合的两种取出方式:
1.使用keySet方法,将Map中的所有键值存入到Set集合中,因为Set有迭代器,可以通过迭代取出所有的键,再根据get(key)方法取出每一个对应的值。下面是具体的示例代码:
public class MyUtil1 { public static void iteratorMap1(Map m) { Set set=m.keySet();//用接口实例接口 Iterator iter = set.iterator(); while (iter.hasNext()) {//遍历二次,速度慢 String k=(String)iter.next(); System.out.println(k +"="+ m.get(k)); //System.out.println(iter.next()+"="+ m.get(iter.next())); //因为指针判断下一个有没有值 iter.next是当前对象 但是 m.get(iter.next())是下一个值 }
2.使用entrySet方法将Map集合映射关系存到set集合中,而这个关系数据类型是Map.Entry,下面是具体的示例代码:
public static void iteratorMap(Map m){ Iterator i=m.entrySet().iterator(); while(i.hasNext()){//只遍历一次,速度快 Map.Entry e=(Map.Entry)i.next(); System.out.println(e.getKey()+"="+e.getValue()); //System.out.println(e.setValue(""));//返回value的值 } }
注意:什么时候使用Map集合呢?当数据之间存在映射关系时,就应该考虑到用Map集合。
本文从集合框架体系开始讲起,简单的讲述了java集合框架的三个主要体系:Set、List和Map,希望对大家有所帮助。