一、为什么要学习集合框架?
数组的长度是固定的并且它不能像集合那样可以存储不同的对象和数据类型!
二、集合框架 的主要接口
Collection:是存放一组对象最大的接口,一般很少会直接使用这个接口
List:Collection的子接口,也是最常用的接口,这接口对Collection接口进行了大量的扩充,有序,可重复的集合
List接口的特有功能:
1.添加功能-add(int index,Object e):向集合指定索引处,添加指定的元素,原有元素依次后移
2.删除功能-remove(int index):通过下表找到指定的元素从集合中删除,返回值为被删除的元素。
3.获取功能-get(int index):获取指定下标的元素,返回该元素。
4.迭代器功能-listIterator():不常用
5.修改功能-set(int index,Object e):通过下标处的元素,替换成指定的元素
List接口的子类:ArryList、Vector、LinkedList
1.ArrayList:底层数据结构是数组,查询速度快,增删慢。线程不安全,效率高。
2.Vector:底层数据结构是数组,查询速度快,增删慢。线程安全,效率低。
3.LinkedList:底层数据结构是链表,查询速度慢,增删快。线程不安全,效率高。
Set接口:Collection接口的子类,没有对Collection接口进行扩充,无序,不可重复的集合。
Set接口的子类:HashSet
底层数据结构是哈希表(是一个元素为链表的数组), 哈希表底层依赖两个方法:hashCode()和equals() 。HashSet首先会比较哈希值是否相同,如果相同则继续执行equals()方法,返回true(元素重复,不添加)。返回false(直接把元素添加到集合)。如果不同就直接把元素添加到集合,用hashCode()和equals()方法可以保存元素的唯一性。
Map接口:代表有映射关系的集合,将键映射到值的对象。一个映射不能包含重复的键;每个键只能映射到一个值。
Map有HashMap、Hashtable、Properties、TreeMap
HashMap:哈希表的Map接口的实现,次实现提供所有可选的映射操作,并允许null和null键
获取hashMap的key和value的demo:
public class entrySetDemo{
public static void main(String[] args){
Map<String,String> m=new HashMap<String,String>();
Set<Map.Entry<String,String>> s=m.entrySet();
Iterator<Map.Entry<String,String>> i=s.iterator();
while(i.hasNext()){
Map.Entry<String,String> e=i.next();
String key=e.getKey();//返回与此项对应的键。
String value=e.getValue();//返回与此项对应的值。如果已经从底层映射中移除了映射关系(通过迭代器的 remove 操作),则此调用的结果是不确定的。
}
}
}
Hshtable:也是实现一个哈希表,改哈希表将键映射到相应的值,且key值不可为空!是线程安全
Properties:该类表示了一个持久的属性集,properties可保存在流中或从流中加载;属性列表中每个键及其对应值都是一个
字符串;改类可以读或写如数据到流中。次类线程是安全的,多个线程可以共享当properties对象而无需进行外部的同步操作
public class Factory {
private static Properties prop = new Properties();
static {
try {
InputStream is = Factory.class.getResourceAsStream("./factory.properties");
prop.load(is);// 加载输入流
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
public static Object getImpl(String className){
//操作从配置文件读取到内存中的配置信息
String fullName = prop.getProperty(className);
Object obj = null;
try {
obj = Class.forName(fullName).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return obj;
}
注:properties的方法只能改变已在内存中的信息,不能直接修改文件内容(可以讲修改后的数据通过输出流写到文件中!)
HashMap采用散列表的算法实现
TreeMap采用红黑树算法实现,利用key进行排序。
Map接口用户放置对象的集合,key不可重复,value可重复,重复的key会覆盖前面的value!
Iterator:集合的输出接口,用户遍历集合的内容,只能从前到后的单向输出。
List<String> list = new ArrayList<String>();
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
ListIterator:是Iterator的子接口,可以进行双向输出。
Enumeration:是最早的输出接口,用户输出指定集合中的内容。
SortedSet:单值得排序接口,实现此接口的集合类,里面的内容是可以排序的,使用比较器排序。
SortedMap:存放一对值得排序接口,实现此接口的集合类,里面的内容按照key排序,使用比较器排序
Queue:队列接口,此接口的子类可以实现队列操作,改类也继承了Collection。LinkedList实现了Queue接口。Queue接口
管理了对LinkedList的方法访问权限(即在方法中的参数类型如果是Queue时,只能访问Queue接口所定义的方法,而不能直接访问
Linked的非Queue方法)。使得只有恰当的方法才可以使用。队列是一种先进先出的方式管理数据。java提供的线程安全的Queue
可以分为阻塞队列和非阻塞队列,其中阻塞队列的典型例子是BlockingQueue,非阻塞队列的例子是ConcurrentLinkedQueue,在
实际应用中根据实际需要选择。
注:什么叫线程安全?线程安全的类指的是类内共享的全局变量的访问必须是不受多线程形式影响的。如果由于多线程的
访问(比如:修改、遍历、查看)而使得这些变量结构或被破坏或者针对这些变量的原子性被破坏,则这个类就不是线程安全的。
BlockingQueue顾名思义:“阻塞队列”可以提供阻塞功能的队列
功能有 入队 add
出队 remove
查询 peek
add、remove、element()方法不会阻塞线程,当不满足约束条件时,会抛出lllegalStateException异常。例如:当队列
被元素填满后,在调用add,会抛出异常
offer、poll、peek()方法不会阻塞线程,也不会抛出异常。当队列被元素填满后。再条用offer,则不会插入元素,函数返回false
要想实现阻塞功能,需要调用put、take()方法。当不满足越苏条件时,会阻塞线程。