集合类
数组和集合的比较:数组可以存储对象,也可以存储基本数据类型,但是缺点就是长度固定,不能改变;集合长度是可变的,但是集合只能存储对象,集合可以存储不同类型的对象。
Java容器类库一共有两种主要的类型:Collection和Map。
一、他们的主要区别就是容器中每个槽内所存储的元素个数不同。Connection类型中,每个槽中只有一个元素;Map类型中,持有Key—value(键值对)。两者的共同点就是Java容器类都可以自动调整自己的尺寸。
二、Collection接口是最基本的集合接口,它定义了一组允许重复的对象。Collection接口派生了三个子接口Set和List、Queue。
三、相互之间的比较:
- Set接口继承于Collection,它没有提供额外的方法,但是实现了Set接口的集合类中的元素是无序并且不能重复的。
- hashSet判断元素时候存在的方法是hashCode和equals方法;treeSet判断元素时候存在的方法是通过compareTo方法实现的。
- List接口也同样继承与Collection但是与Set接口区别的是List接口的集合类中的元素是对象有序并且可以重复。
- Queue:这是一个队列的接口。
Iterator接口:
Iterator接口,这是集合访问器,用于循环访问集合中的对象。
所有实现了Collection接口的容器类都有iterator方法,用于返回一个实现了Iterator接口的对象。Iterator对象称作迭代器,Iterator接口方法能以迭代方式逐个访问集合中各个元素,并可以从Collection中除去适当的元素。
Comparable接口
在实际应用中,我们往往有需要比较两个自定义对象大小的地方。而这些自定义对象的比较,就不像简单的整型数据那么简单,它们往往包含有许多的属性,我们一般都是根据这些属性对自定义对象进行比较的。所以Java中要比较对象的大小或者要对对象的集合进行排序,需要通过比较这些对象的某些属性的大小来确定它们之间的大小关系。
一般,Java中通过接口实现两个对象的比较,比较常用就是Comparable接口和Comparator接口。首先类要实现接口,并且使用泛型规定要进行比较的对象所属的类,然后类实现了接口后,还需要实现接口定义的比较方法(compareTo方法或者compare方法),在这些方法中传入需要比较大小的另一个对象,通过选定的成员变量与之比较,如果大于则返回1,小于返回-1,相等返回0。
HashSet的内部实现是有HashMap完成的,LinkedHashMap继承于HashSet,但是它内部是由LinkedHashMap完成实现的。同样,TreeSet的内部实现由TreeMap完成。
1、Iterator接口
Iterator接口,这是一个用于便利集合中元素的接口,主要包含hashNext(),next(),remove()这三个方法。他的一个子接口LinkedIterator在它的基础上又添加了三个方法:add(),previous(),hasPrevious().也就是说如果是先Iterator接口,那么在遍历集合中元素的时候,智能往后遍历,被遍历后的元素不会再遍历到,通常无需集合实现的是这个接口,比如HashSet(),HashMap();而那些元素有序的集合,实现的一般都是linkedIterator接口,实现这个接口的集合可以双向遍历,既可以通过nest()访问下一个元素,又可以通过previous()访问前一个元素,比如ArrayList.
2、Collection(集合的最大接口)继承关系
- List-----将以特定的次序存储元素,存入元素的次序可能和去除元素的次序不一样。(有序可重复)
- Set------不能存放重复的内容,所以检测内容是否重复就要靠hsahCode()和equals()两个方法进行区分。(无序不能重复)
- Queue-----队列接口
- SortedSet-----可以对集合中的数据进行排序
3、Collection定义了集合框架的公共功能:
3、List的常用子类
- ArrayList---线程不安全,擅长随机访问元素,但是在List中插入、删除、移动元素等操作比较慢。
- LinkedList---在List中插入、删除、移动元素等操作比较快,随机访问元素速度比较慢。
- Vector---线程安全,但是速度慢,已经被ArrayList取代。
4、Set接口
Set:元素是无序的(存入和取出的顺序不一定完全一致),元素不可以重复。
-----HashSet:低层是数据结构的哈希表,线程不安全,不同步。HashSet是通过两个方法hashCode()和equals()进行判断。
------TreeSet:有序的存放,线程不安全,可以对Set集合中的元素进行排序,通过compareTo()或者compare()方法来保证元素的唯一性,元素以二叉树的形式存放。
5、Object类
在实际的开发中经常会碰到区分同一个对象的问题,一个完整的类最好覆写Object类中的hashCode(),equals(),toString()这三个方法。
6、集合的输出
---4种常见的输出方式:
- Iterator:迭代输出,使用最多的输出方式
- ListIterator:Iterator的子接口,专门用于输出List中的内容。
- Enumeration
- Foreach
在迭代时,不可以通过集合对象的方法操作集合中的元素,因为会发生ConcurrentModificationException异常,所以,在迭代器时,只能使用迭代器操作元素,但是Iterator方法是有限的,只能对元素进行判断,取出,删除的操作,如果想要其他的操作入添加,修改等,就需要使用子接口ListIterator。该接口只能通过List集合的ListIterator方法获取到。
7、Map接口
Correction、Set、List接口都属于单值的操作,而Map中的每个元素都使用key——>value的形式存储在集合中。Map集合:该集合存储键值对。一对一对往里存。而且要保证键的唯一性。
8、Map接口的常用子类:
---hashMap:低层是数据结构的哈希表,允许使用null值和null键,该集合不是同步的,用于替代Hashtable。效率比较高。
---TreeMap:低层是数据结构的二叉树,线程不同步,可以用于给Map集合中的键值进行排序。
9、集合工具类
Collections:集合框架的工具类,里面定义的都是静态方法。
Collection和Collections的区别:
- Collection是集合框架中的一个顶层接口,它里面定义了单列集合的共性方法。
- Collections是集合框架的一个工具类,该类中的方法都是静态的。
- Collections中提供的方法有可以对List集合进行排序二分查找等方法。
- 通常常用的集合都是线程不安全的,因为要提高效率。如果多线程操作这些集合时,可以通过该工具类中的同步方法将线程不安全的集合转换成线程安全的。
10、比较
是否有序 |
是否允许元素重复 |
||
Collection |
否 |
是 |
|
List |
是 |
是 |
|
Set |
AbstractSet |
否 |
否 |
hashSet |
|||
TreeSet |
是(用二叉排序树) |
||
Map |
AbstractMap |
否 |
使用key-value来映射和存储数据,key必须唯一,value可以重复 |
HashMap |
|||
TreeMap |
是(用二叉排序树) |
11、总结
List:add/remove/get/set。
1,ArrayList:其实就是数组,容量一大,频繁增删就是噩梦,适合随机查找;
2,LinkedList:增加了push/[pop|remove|pull],其实都是removeFirst;
3,Vector:历史遗留产物,同步版的ArrayList,代码和ArrayList太像;
4,Stack:继承自Vector。Java里其实没有纯粹的Stack,可以自己实现,用组合的方式,封装一下LinkedList即可;
5,Queue:本来是单独的一类,不过在SUN的JDK里就是用LinkedList来提供这个功能的,主要方法是offer/pull/peek,因此归到这里呢。
Set:add/remove。可以用迭代器或者转换成list。
1,HashSet:内部采用HashMap实现的;
2,LinkedHashSet:采用LinkedHashMap实现;
3,TreeSet:TreeMap。
Map:put/get/remove。
1:HashMap/HashTable:中文叫散列表,基于哈希表实现,特点就是键值对的映射关系。一个key对应一个Value。HashMap中元素的排列顺序是不固定的。更加适合于对元素进行插入、删除和定位。
2:TreeMap,基于红黑树实现。TreeMap中的元素保持着某种固定的顺序。更加适合于对元素的顺序遍历。
3:LinkedHashMap:继承自HashMap。
4:Properties:是继承的HashTable。
补充:
1、在Java中使用Stack类进行栈的操作,Stack类是Vector 的子类,但是在使用时却不使用Vector类定义的方法,而是有自己的方法:
- 入栈操作:public E push(E item);
- 出栈操作:public E pop();
- 出栈和进栈的操作刚还是相反的,但是加入栈里边没有数据了,继续执行出栈操作的时候就会报EmptyStackException的异常。
2、属性操作类:properties
属性一般针对字符串数据,并且多有的字符串数据都会按照“key-Value”的形式保存,使用属性类最方便的特点是可以直接将这些属性以OutoutStream或者InputStream 的方式输出或者读取,而一般保存这些属性的文件为资源文件,资源文件的后缀一般都是.propreties。
Properties类的常用方法:
No. |
方法 |
类型 |
描述 |
1 |
Public Properties() |
构造器 |
构造一个空的属性类 |
2 |
Public Properties(Properties defaults) |
构造器 |
构造一个指定属性内容的属性类 |
3 |
Public String getProprety(String Key) |
常量 |
根据属性的Key取得属性的Value,如果没有Key,返回null |
4 |
Public String getProprety(String Key,String defaultValue) |
普通 |
根据属性的Key取得属性的Value,如果没有Key,返回defaultValue |
5 |
Pubic Object setProperty(String Key,String value) |
普通 |
设置属性 |
6 |
Public void load( InputStream inStream) throws IOException |
普通 |
从属性流中取出全部的属性内容 |
7 |
Public void store( OutputStream outStream,String comments) throws IOException |
普通 |
将属性内容通过输出流输出,同时声明属性的注释 |