<转载>java中的集合
1.集合的特点:
都位于 java.util包中,不能存放基本类型的数据,而只能存放对象的引用,操作的数目可以不固定(类似于动态数组)。
2.分类:
有三个类:
a.Set(集):对象不按特定方式排序,没有重复元素。这个与数学中的集合概念最相似。
b.List(列表):按照索引位置排序,可以有重复元素,允许按照对象在集合中的索引位置检索对象。
c.Map(映射):每一个元素包含一个键值对。没有重复的键值对,但是值对象可以重复。
有两个接口:
Collection接口适用于Java集合中的Set和List(这两个类直接继承了这个接口),提供了一些通用操纵的静态方法。
Iterator接口隐藏了底层集合的数据结构,对外提供了遍历各种数据类型集合的统一接口。由collection集合的iterator得到一个Iterator。语法如下:
Iterator it = set.iterator();
(注意此后若通过collection方法修改了集合则使用next()方法时会出现异常,因为其运用了所谓快速失败机制。避免了潜在的共享资源竞争而导致的并发问题)。
3.Set集合:
主要有两个实现类:HashSet和TreeSet。
前者使用哈希算法,存取速度快,它还有一个子类LinkedHashSet类,性能更高。HashSet向集合中加入一个对象时,会调用对象的hashCode()方法得到哈希码,然后根据这个哈希码计算出对象在集合中的存放位置。
为了保证其能正常工作,要求当两个对象用equals()方法比较的结果为true时它们的哈希码也必须相同。这就要求我们如果在我们自己设计的类中覆盖了equals方法,那么也也应该覆盖hashCode()方法。用equals()方法比较的结果为false时,最好hashCode不同,减少哈希冲突,提高性能。
而后者则实现了SortedSet接口,具有排序功能。由于用户属性变化不会导致重新排序,所以适合加入不可变类。向其中加入自定义的类时要注意,实现其Comparable接口,并且euqals()得出的结论要与compareTo()得出的结论相同。另外,它还支持Comparator接口,可以定义一个实现了该接口的类CustomerComparator实现自定义的排序。在定义时使用如下的语法:
Set set = new TreeSet(new CustomerComparator);
4.List列表:
主要特征是以线性方式存储,集合中可存放重复元素。Thoughts Works 公司的一个顾问曾拟文说在Java 中强烈建议使用List替代所有的数组。在数组与List转换时使用asList的方法。
主要有两个实现类:ArrayList和LinkedList。
前者的特点是允许对元素进行快速随机访问,但插于和删除元素的速度较慢。一般用于代表可变数组。
后者的特点是采用链表数据结构,对顺序访问和删除、插入元素速度较快,但随机访问速度较慢。一般用于代表堆栈、队列和双向队列。
一个比较实用的接口是ListIterator接口,使用listIterator方法返回得到,它继承了Iterator接口,并且提供了专门操纵列表的方法。
Arrays类的一个方法asList()可以把一个数组包装成List对象,但此时这个List固定长度了,因为所有操作都会作用于底层数组。
以前还有一个叫做Vector类,现在已经不提倡使用了。
性能上,Java数组的随机访问和迭代操作速度最快,ArrayList的随机访问速度也较快,而LinkedList则进行插入和删除操作有最快的速度。
因此尽量不要在List中进行迭代操作,而使用addAll
或 removeAll
,传入包含要对其添加或移除元素的集合作为参数,将一个集合(特别是由数组转化而成的集合)的内容转移到另一个集合,或者从一个较大对象集合中移除一个较小对象集合,从而完成成员的增减。迭代可能会出现的问题如下:
- 每次添加或移除元素后重新调整集合将非常低效。
- 每次在获取锁、执行操作和释放锁的过程中,都存在潜在的并发困境。
- 当添加或移除元素时,存取集合的其他线程会引起竞争条件。
5.Map映射:
每一个元素包含一个键值对,而且值对象还可以Map映射类型,键对象不允许重复。
Map的entrySet()方法返回了一个Set集合,这个集合存放了Map.entry类型的元素,每个Map.Entry对象代表Map中的一个键值对。而keySet()方法返回集合中所有键对象的集合。
主要有两个实现类:HashMap和TreeMap,与Set的两个实现类特性和使用须知基本相同。
注意:永远不要将可变对象类型用作
HashMap
中的键,否则支持哈希码的键依赖于可变字段的内容,这样hashCode()
容易改变,产生 bug。6.使用的注意事项:
1)在泛型中可以使用类似Set 表示只接受Object类型及其子类型。或者Set表示接受String类型和其父类型。
2)可以使用更简便的遍历方法以代替Iterator,这个增强适用于实现
Iterable
接口的任何对象,而不仅仅是Collections
:for(String element : set){
System.out.println(element);
}
3)Set、List和Map实现类都没有采取同步机制,要注意并发问题。
4)Collections实用类,使用方法例如:Collections.sort(list);直接调用(因为是静态的嘛),注意与Collection接口区分。
5)List在移除一个成员时后一个其 “后面” 的各项会上升填补空位,这可能是与数组显著的不同吧。