集合本身就是容器,用于存储对象、遍历集合。不同集合具有自己的特性。
集合本身不支持基本类型,但由于参在自动装箱机制,可以存储基本类型。
Collection接口
Collection接口是顶层接口,常用的子接口有Set接口和List接口
List接口,有序,允许重复
Set接口,无序,不允许重复
Iterator迭代器
屏蔽集合之间的不同。存取元素的通用模式。
迭代——相当于编译,若集合中有元素,取出,判断下一个元素有没有,有就取出,直到没有元素。
- hasNext()
判断集合有没有可以元素可以迭代 - next()取出下一个元素-
使用方式
Iterator接口,需要实现类将接口方法重写。Collection接口中,有方法iterator(),返回值为Iterator。
作为Collection接口子类ArrayList,重写方法iterator(),返回Iterator类的实现类。
[面向接口编程]–迭代器执行过程当Iterator建立对象it时,内存中建立指针,指向-1位;hasNext()方法判断指针下一位是否有元素存在。next()方法中,指针下移,取元素。
Set接口
Set接口的实现类有HashSet类、LinkedHashSet类
- 特性
没有索引,不允许存储重复元素。
依赖于Map接口,由哈希表支持。
无序集合——不依赖于存入的顺序,可以存储null元素。 - hash表存储过程
(hashCode(),equals())——判断对象的唯一性
数组链表结构
1.调用对象的哈希值。new String(’'abc").hashCode=96354
2.集合在容器内查找,判断有没有和96354一样的哈希值
3.没有,哈希表的数组中存入该哈希值
4.集合调用对象哈希值。new String(“abc”).hashCode=96354
5.集合在容器内查找到一个对象,其值也为963546.集合会让后来的对象(4中)调用方法equals(已经存在的对象(1中))
7.两个对象,哈希值一样,equals方法返回true,集合判定该元素重复{若new String(“adc”).hashCode()=96354,与(1中)的哈希值相同,但equals()返回false,集合判定对象没有重复,此时,采用桶的存储方式}判断对象是否重复,需要判断hashCode()和equals()方法(哈希值的算法,可以参考String,让字符串中的每个字符都进行运算,采用31×原来的字符) - LinkedHashSet
继承HashSet,实现Set接口自身特性:
1.具有顺序,取出按存入有序(HashSet是无序)
2.双向链表,可以保证迭代的顺序
3.线程不安全的集合
List接口
List接口的实现类有ArrayList类、LinkedList类
- 特性
有序集合,取出的顺序与存入顺序一致。
具备索引。
允许存储重复元素。
-List接口与其父接口Collection相同的特性
add()
clear()
remove()
toArray()
size()
contains()
iterator() - List接口自身的特性
(具备索引)
add(int index,E element)——将元素插入列表的指定索引
get(int index)
remove(int index)——移除指定索引上的元素,返回值E,返回被删除之前的元素
set(int index,E element)——修改指定索引上的元素,返回被修改之前的元素 - List遍历
1.iterator——所有集合通用
2.for
3.增强for - ArrayList、Vector、LinkedList
ArrayList 和Vector都是使用数组方式存储数据,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢。
Vector中的方法由于添加了synchronized修饰,因此Vector是线程安全的容器,但性能上较ArrayList差,java.util.Vector从java1.2之后,实现List接口。Vector线程安全。运行速度慢。jdk1.2后被ArrayList取缔。
LinkedList使用双向链表实现存储,插入速度快。
判断集合唯一元素原理
ArrayList的contains()——调用存储对象的equals
HashSet的add()——重复无法添加,hashCode()equals(),可以自动添加
HashSet的contains()——依赖equals()
- 如果两个对象的哈希值相同,.hashCode()值相同,那么两个对象的equals一定返回true吗?(不一定) 如果两个对象的equals()返回true,那么两个对象的哈希值相同吗?(一定)
[sun公司对hashCode()有规定,在JAVA应用程序执行期间,在对同一个对象多次调用hashCode()方法时,必须一致返回相同的整数,前提是对象运用equals比较时的信息没有被修改]
[如果根据equals(Object)方法,两个对象是相等的,那么这两个对象调用hashCode方法时必须返回相同的整数]
[两个对象不相等,那么这两个对象在调用hashCode方法不要求一定生成不同的整数结果。但为不相等的对象生成不同的哈希值可以提高哈希表的性能。]
{批注:hashCode映射数组,equals映射链表,整个哈希表是数组链表结构。}
Map接口
Collection是单列集合。Map是双列集合,存储两个对象(映射关系键值对key-value),键不允许重复,值可以重复
- 接口Map<K,V>
实现类HashMap和LinkedHashMap - 方法
put(K,V)——将键值对存储到集合中(不可以存取重复键,当存储的是重复键,会覆盖原有键的值)方法的返回值一般是null(存储重复键时,返回被覆盖之前的值)
get(K)——如果集合中没有该键,返回null
remove(K,V)——移除键,返回被移除之前的值(没有返回null)
size()——返回长度个数
Map遍历方式
- keySet()获取Map集合中的所有键,返回Set集合(set对象.getClass()——java.util.HashMap$KeySet)利用键,获取值的方式做遍历
(1).调用Map集合的方法keySet,获取所有键,存储到Set集合中
(2).遍历Set集合,获取出Set集合中的所有元素(Map的键)
(3).调用Map集合方法get,通过键获取到值(增强for编译完就是iterator)
public static void keySet(HashMap<String, HashMap<String, String>> czbk) {
Set<String> classnameSet = czbk.keySet();
Iterator<String> classnameIt = classnameSet.iterator();
while (classnameIt.hasNext()) {
String classnameKey = classnameIt.next();
HashMap<String, String> classMap = czbk.get(classnameKey);
Set<String> studentNum = classMap.keySet();
Iterator<String> studentIt = studentNum.iterator();
while (studentIt.hasNext()) {
String numKey = studentIt.next();
String numVal = classMap.get(numKey);
System.out.println(classnameKey + "..." + numKey + "..." + numVal);
}
}
}
- EntryMap的静态内部接口——static interface Entry<K,V>——将键值对映射为一个对象entrySet()——返回Set集合getKey()getValue()
public static void entrySet(HashMap<String, HashMap<String, String>> czbk) {
Set<Map.Entry<String, HashMap<String, String>>> classnameSet = czbk.entrySet();
Iterator<Map.Entry<String, HashMap<String, String>>> classnameIt = classnameSet.iterator();
while (classnameIt.hasNext()) {
Map.Entry<String,HashMap<String,String>> classnameEntry = classnameIt.next();
String classnameKey = classnameEntry.getKey();
HashMap<String,String> classMap = classnameEntry.getValue();
Set<Map.Entry<String,String>> studentSet = classMap.entrySet();
Iterator<Map.Entry<String,String>> studentIt = studentSet.iterator();
while (studentIt.hasNext()){
Map.Entry<String,String> stu = studentIt.next();
System.out.println(classnameKey+":"+stu.getKey()+"..."+stu.getValue());
}
}
}