1.容器概述
1.1容器定义
Java容器类类库的用途是保存对象,可以将其分为2个概念。
1.1:Collection
一个独立元素的序列,这些元素都服从一条或多条规则。其中List必须按照插入的顺序保存元素、Set不能有重复的元素、Queue按照排队规则来确定对象的产生顺序(通常也是和插入顺序相同)
1.2:Map
一组成对的值键对对象,允许用键来查找值。ArrayList允许我们用数字来查找值,它是将数字和对象联系在一起。而Map允许我们使用一个对象来查找某个对象,它也被称为关联数组。或者叫做字典。
1.2容器与数组
从本质上讲,数组也是另外一种容器。
数组的优势: 是一种简单的线性序列,可以快速地访问数组元素,效率高。如果从效率和类型检查的角度讲,数组是最好的。
数组的劣势: 不灵活。容量需要事先定义好,不能随着需求的变化而扩容。比如:我们在一个用户管理系统中,要把今天注册的所有用户取出来,那么这样的用户有多少个?我们在写程序时是无法确定的。因此,在这里就不能使用数组。
1.3容器与接口
2.Collection接口
方法 | 说明 |
---|---|
boolean add(Object element) | 增加元素到容器中 |
boolean remove(Object element | 从容器中移除元素 |
boolean contains(Object element | 容器中是否包含该元素 |
int size() | 容器中元素的数量 |
boolean isEmpty() | 容器是否为空 |
void clear | 清空容器中所有的元素 |
Iterator iterator() | 获得迭代器,用于遍历所有元素 |
boolean containsAll(Collection c) | 本容器是否包含c容器中的所有元素 |
boolean addAll(Collection c | 将容器c中所有元素增加到本容器 |
boolean removeAll(Collection c) | 移除本容器和容器c中都包含的元素 |
boolean retainAll(Collection c) | 取本容器和容器c中都包含的元素,移除非交集元素 |
Object[] toArray() | 转化成Object数组 |
Collection 表示一组对象,它是集中、收集的意思。Collection接口的两个子接口是List、Set接口。所有List、Set的实现类都有上面的方法。
2.1 List接口
List是有序,可重复的容器,承诺可以将元素维护在特定的序列中。List接口在Collection的基础上加入了大量的方法,使得可以在List中间可以插入和移除元素。
有序: List中每个元素都有索引标记。可以根据元素的索引标记(在List中的位置)访问元素,从而精确控制这些元素。
可重复: List允许加入重复的元素。更确切地讲,List通常允许满足 e1.equals(e2) 的元素重复加入容器。
2.1.1 ArrayList
ArrayList底层是用数组实现的存储。 特点:查询效率高,增删效率低,线程不安全。我们一般使用它。ArrayList底层使用Object数组来存储元素数据。所有的方法,都围绕这个核心的Object数组来开展。此外,通过定义新的更大的数组,将旧数组中的内容拷贝到新数组,来实现扩容。 ArrayList的Object数组初始化长度为10,如果我们存储满了这个数组,需要存储第11个对象,就会定义新的长度更大的数组,并将原数组内容和新的元素一起加入到新数组中。
2.1.2 LinkList
双向链表也叫双链表,是链表的一种,它的每个数据节点中都有两个指针,分别指向前一个节点和后一个节点。 所以,从双向链表中的任意一个节点开始,都可以很方便地找到所有节点。
每个节点都应该有3部分内容:
class Node { //源码里面用的是Entry
Node previous; //前一个节点
Object element; //本节点保存的数据
Node next; //后一个节点
}
2.1.3 Vector
Vector底层是用数组实现的List,相关的方法都加了同步检查,因此“线程安全,效率低”。 比如,indexOf方法就增加了synchronized同步标记。
2.2 Set接口
Set接口继承自Collection,Set接口中没有新增方法,方法和Collection保持完全一致。我们在前面通过List学习的方法,在Set中仍然适用。因此,学习Set的使用将没有任何难度。
Set容器特点:无序、不可重复。无序指Set中的元素没有索引,我们只能遍历查找;不可重复指不允许加入重复的元素。更确切地讲,新元素如果和Set中某个元素通过equals()方法对比为true,则不能加入;甚至,Set中也只能放入一个null元素,不能多个。
2.2.1 HashSet
HashSet是采用哈希算法实现,底层实际是用HashMap实现的(HashSet本质就是一个简化版的HashMap),因此,查询效率和增删效率都比较高。
public class Test {
public static void main(String[] args) {
Set<String> s = new HashSet<String>();
s.add("hello");
s.add("world");
System.out.println(s);
s.add("hello"); //相同的元素不会被加入
System.out.println(s);
s.add(null);
System.out.println(s);
s.add(null);
System.out.println(s);
}
}
2.2.2 TreeSet
TreeSet底层实际是用TreeMap实现的,内部维持了一个简化版的TreeMap,通过key来存储Set的元素。 TreeSet内部需要对存储的元素进行排序,因此,我们对应的类需要实现Comparable接口。这样,才能根据compareTo()方法比较对象之间的大小,才能进行内部排序。
3.Map接口
3.1 Map概述
Map就是用来存储“键(key)-值(value) 对”的。 Map类中存储的“键值对”通过键来标识,所以“键对象”不能重复。
Map 接口的实现类有HashMap、TreeMap、HashTable、Properties等。
方法 | 说明 |
---|---|
Object put(Objece key,Object value | 存放键值对 |
Object get(Object key) | 通过键对象查找得到值对象 |
Object remove(Object key) | 删除键对象对应的键值对 |
boolean containsKey(Object key) | Map容器中是否包含键对象对应的键值对 |
boolean containsValue(Object value) | Map容器中是否包含值对象对应的键值对 |
int size() | 包含键值对的数量 |
boolean isEmpty() | Map是否为空 |
void putAll(Map t) | 将t的所有键值对存放到本map对象 |
void clear() | 清空本map对象所有键值对 |
3.2 HashMap与HashTable
代码示例:
public class TestMap {
public static void main(String[] args) {
Map<Integer, String> m1 = new HashMap<Integer, String>();
Map<Integer, String> m2 = new HashMap<Integer, String>();
m1.put(1, "one");
m1.put(2, "two");
m1.put(3, "three");
m2.put(1, "一");
m2.put(2, "二");
System.out.println(m1.size());
System.out.println(m1.containsKey(1));
System.out.println(m2.containsValue("two"));
m1.put(3, "third"); //键重复了,则会替换旧的键值对
Map<Integer, String> m3 = new HashMap<Integer, String>();
m3.putAll(m1);
m3.putAll(m2);
System.out.println("m1:" + m1);
System.out.println("m2:" + m2);
System.out.println("m3:" + m3);
}
}
HashTable类和HashMap用法几乎一样,底层实现几乎一样,只不过HashTable的方法添加了synchronized关键字确保线程同步检查,效率较低。
HashMap与HashTable的区别
- HashMap: 线程不安全,效率高。允许key或value为null。
- HashTable: 线程安全,效率低。不允许key或value为null。
3.3 HashMap底层实现
看懂了在整理0…0
http://www.sxt.cn/Java_jQuery_in_action/nine-hashmap-bottom.html
4.遍历集合的方法总结
4.1 遍历List
4.1.1 普通for循环
for(int i=0;i<list.size();i++){//list为集合的对象名
String temp = (String)list.get(i);
System.out.println(temp);
}
4.1.2 增强for循环(使用泛型!)
for (String temp : list) {
System.out.println(temp);
}
4.1.3 使用Iterator迭代器
for(Iterator iter= list.iterator();iter.hasNext();){
String temp = (String)iter.next();
System.out.println(temp);
}
4.1.4 使用Iterator迭代器二
Iterator iter =list.iterator();
while(iter.hasNext()){
Object obj = iter.next();
iter.remove();//如果要遍历时,删除集合中的元素,建议使用这种方式!
System.out.println(obj);
}
4.2 遍历Set方法一
4.2.1 增强for循环
for(String temp:set){
System.out.println(temp);
}
4.2.2 使用Iterator迭代器
for(Iterator iter = set.iterator();iter.hasNext();){
String temp = (String)iter.next();
System.out.println(temp);
}
4.3 遍历Map
4.3.1 根据key获取value
Map<Integer, Man> maps = new HashMap<Integer, Man>();
Set<Integer> keySet = maps.keySet();
for(Integer id : keySet){
System.out.println(maps.get(id).name);
}
4.3.2 使用entrySet
Set<Entry<Integer, Man>> ss = maps.entrySet();
for (Iterator iterator = ss.iterator(); iterator.hasNext();) {
Entry e = (Entry) iterator.next();
System.out.println(e.getKey()+"--"+e.getValue());
5.Collections工具类
类 java.util.Collections 提供了对Set、List、Map进行排序、填充、查找元素的辅助方法。
1.void sort(List) //对List容器内的元素排序,排序的规则是按照升序进行排序。
2.void shuffle(List) //对List容器内的元素进行随机排列。
3.void reverse(List) //对List容器内的元素进行逆续排列 。
4.void fill(List, Object) //用一个特定的对象重写整个List容器。
5.int binarySearch(List, Object)//对于顺序的List容器,采用折半查找的方法查找特定对象。