JAVA 集合框架
一、JAVA集合框架中分为两大类:
装载数据的集合类和操作数据的工具类
Java集合类是基于Collction接口,在根据不同需求分类为set、List和Map三大接口
Java集合就像一种容器,可以通过相应的方法将多个对象的引用放在容器中,容器中的元素(对象的引用)类型都为Object类型。所以可以存放通过向上转型,存放任意类型的对象引用,但从容其中取出元素是必须向下转型(强制)为原来的类型。
值得注意的是:集合类容器中的元素不存放基本数据类型,可存放包装类型。
1.1、装载数据的集合类:
集合类通过Collection接口定义了集合类共有的一些基本方法,这些方法分为基本操作(添加,删除,修改和查询容器元素),批量操作(批量添加,删除容器元素)和数组操作(集合与数组转换)
1.1 List接口:
它继承与Collection接口,是一个允许重复元素的有序集合。List接口的实现类(具体类)常用的有ArrayLiset(顺序表集合)和LinkedList(链表集合)。
1.2、ArrayLiset(顺序表集合):
ArrayList类扩展AbstractList并实现List接口。ArrayList类提供一个随需要而增长的动态数组。在java中,标准数组时过顶长度的,在数组创建之后,他们不能被增加或缩短,这也就意味我们必须事先知道数组可以容纳多少元素。但是,直到运行时才能直到需要多大数组,ArrayList类就是为了解决这个问题。
2.1 特点:
对于使用索引查询元素效率较高,它可以使用索引快速定位元素位置,但删除或插入元素效率较低,因为使用了数组,需要移动后面的元素以调整索引的顺序。它的使用最广泛,可在几何元素增加或删除操作不频繁时使用,最合适做查询操作。
3、Java泛型:
由于集合中保存的元素都是Object类型,当一个元素从集合中取出来后都是Object类型的对象引用,所以我们必须对其进行向下强制转换,为了解这种麻烦,JDK1.5中支持新特性-——java泛型。
所谓泛型是指在定义(类的定义、方法的定义、形式参数的定义、成员变量的定义等)的时候,指定它为通用类型,也就是数据类型可以是任意的类型,具体调用的时候要将通用类型转换成指定的类型使用。
泛型是对Java语言的类型系统的一种扩展,以支持穿件可以按类型进行参数化的类。可以把类型参数看作是适用参数化类型时指定的类型的一个占位符,就像方法的形式参数是运行时传递的值的占位符一样。
二、泛型的优点:
java语言引入泛型的好处是安全简单。泛型的好处是在编译的时候检查类型安全,并且所有的向下强制转型都是自动和隐式的,提高了代码的重用率。
注意:在静态方法、静态初始化快、静态成员变量里面不允许使用泛型。
Java泛型:
由于集合中保存的元素都是Object类型,当一个元素从集合中取出来后都是Object类型的对象引用,所以我们必须对其进行向下强制转换,为了解决这麻烦。JDK1,.5中支持----一项新特性---java泛型。
所谓泛型是指在定义(类的定义,方法的定义,形式参数的定义,成员变量的定义,)的时候,指定他为通用型,也就是数据类型可以是任意类型,具体调用的时候要将通用类型指定类型使用。
泛型是对java语言的系统一种扩展,以支持创建可以按类型进行转换参数的类。
可以把类型参数看做使用参数类型指定的类型的一个占位符。就像方法的形式参数试运行时传递的值占位符一样。
泛型的优点:
java引入泛型的好处就是安全简单。泛型的好处是在编译的时候减产安全,并且所有哦的向下强制转换都是自动和隐式的,提高代码的重用率。
注意:在静态方法中,在静态初始化块中静态成员变量不可以使用泛型。
4、LinkedList (链表集合):
LinkedList类扩展AbstructSquentialList并实现List接口。它提供了一个链表的数据结构。
特点:
因为LinkedLIst使用双向链表,所以针对频繁使用插入和删除元素,使用LinkList类效率较高,它的使用实现栈(数据结构)和队列(数据结构),当需要在集合中间位置频繁增加或删除元素时建议使用LinkedList类。
5、Iterator迭代器
Iterator接口是一种用于遍历集合。所谓遍历,是指从集合中取出每个元素的过程。
Boolean hasNext() //判断游标右边是否有元素
Object next() //返回迭代的下一个元素。
void remove() // 从迭代器指向的collection 中移除迭代器返回的最后一个元素(可选操作)。
三种遍历集合方法:
//for遍历集合元素
for (Student student :linkedList) {
System.out.println(student.toString());
}
System.out.println("---------------------");
//foreach遍历集合元素
for (Student student :linkedList) {
System.out.println(student);
}
System.out.println("---------------------");
//使用迭代器遍历集合元素
Iterator<Student>iterator = linkedList.listIterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
6、Vector(向量表集合):
Vector类扩展AbstractSequentiaList并实现List接口。与ArrayList的用法几乎完全相同,二者之间最大的区别在于Vector类是线程安全(线程同步),所以性能要稍低于ArrayList类。该实现类已过时,实际应用开发时尽量少用。
7、Stack(栈集合):
Stack类扩展Vector类,它提供了一个栈的数据结构。数据结构中的栈,在解决很多问题是由用的(比如括号匹配,迷宫求解,表达式求值等)该实现类已过时,实际应开发时,尽量少用。
8、Set接口:
它继承与Collection接口,是一个不允许存在重复元素的有序集合。Set接口添加,查找或删除元素都有很高的效率。Set接口的实现类(具体类)常用的有hashSet(哈希集合),LinkedhashSet(链表哈希集合)和TreeSet(有序树集合)。
9、HashSet(哈希集合):
HashSet类是Set借口实现类之一,使用较广泛,它不保存元素的有序顺序。HashSet类根据元素的哈希码进行存放,所以取出时也可以根据哈希吗快速找到。
注意:
因为Set接口中不能加入重复元素。所以他对于自定义类,需要重复提供元素的方法,即需要重写hashCode()和equals()
10、hashCode ()方法:
如果一个集合中有100个元素,再添加一个新元素时,是不是需要执行100次equals()方法呢?如果每增加一个元素就遍历一次集合,那么当元素很多时,后添加到集合中的元素比较次数就非常多,这样显然会大大降低效率。于是java采用哈希表(数据结构)的原理,使用哈希算法(也成为闪电算法)将元素直接指定到一个地址上。我们可以将hashCode方法的返回值看作是对象储存的物理地址的一个索引。添加新元素时,先通过索引查看这个位置是否存在元素,如果不存在,则可以直接将元素储存于此,不需要在调用equals方法;如果已经存在元素则再调用equals方法与新元素进行比较,相同则不存放,不同就再索引其他地址。这样就使实际带哦用equals方法的次数大大降低,提高了运算效率。
11、Equals方法和hashCode方法的说明:
1) 如果两个对象相同,那么他们的hashCode(哈希吗)一定要相同;
2) 如果两个对象的hashCode(哈希吗)相同,这两个对象并不一定相同。
注意:
Java规范中要求,如果程序员重写了equals方法,就一定要重写hashCode方法,当两个对象调用equals方法比较时,如果返回true,吗么他们的hashCode值要求返回相等的值。
12、LinkedHashSet(链表哈希集合):
他的使用和HashSet几乎相同,并使用链表记录元素的加入顺序。
13、TreeSet(有序树集合):
TreeSet类使用红黑树(数据结构)对加入的元素进行排序存放,如果加入TreeSet类中的元素是自定义,则需要实现比较器Comparable接口并重写CompareTo方法,用于元素之间的排序比较。
Character:
按Unicode值的数字大小排序。
String:
按字符串的字符的Unicode值大小排序。
三、Map接口:
它不是继承与Collection接口,用于维护键值对。Map中的键/值可以使任意类的实例化对象。在Map中不允许出现重复的键,所以存入Map中的键对应的类必须重写hashCode方法和equals方法。Map接口的实现类(具体类)常用的有HashMap、TreeMap和properties。
3.1、HashMap(哈希映射集合):
HashMap类是基于哈希表的Map接口实现,提供所有可选的映射操作,效率高,所以在实际应用开发中使用很广泛。由于HashMap的键要求不重复,建议尽量使用标准库类,避免自定义类重写equals方法和hashCode方法。
3.2、TreeMap(有序树映射集合):
TreeMap类的内部使用红黑树(数据结构)对“键”进行排序存放。所以放入TreeMap中的键值队必须是可排序的。如果自定义累作为“键”,那么就要同TreeMap相似,实现Compareable接口并重写CompareTo方法。
3.3、Properties(属性集合):
Properties类表示一个持久的属性集,他可保存在流中加载。属性列表中每个键及其对应值都是一个字符串。Properties类继承HashTable,自java2平台(JDK1.2版本)以来,HashTable类已经改进为可以实现Map接口,所以Properties类也具有Map的特性。但是Properties类存放的键值队都是字符串,在存放数据时不建议使用Put方法和PutAll方法,应该使用setProerty(String key,String Val )方法和getProperty(String key)方法。
//注意:
1) 如果涉及到堆栈、对列表等操作,应该考虑使用List接口的实现类。
2) 如果要进行大量的随机访问,应该使用ArrayList;
3) 如果经常进行插入和删除操作,应该使用LinkedeList;
4) 总是使用类型安全的泛型,避免在运行时出现ClassCastException异常;
5) 尽量使用JDK的标准类作为Map的键(如String、Integer等,可以避免自己实现比较器或equals方法和hashCode方法)
6) 尽量使用Collections和Arrays工具类,而非编写自己的实现类。他将会提高代码重用性,他有更好的稳定性和可维护性。
7) 应用开发尽量不要使用过时的Vector、HashTable和Stack。