2015-4-19
一、Map集合
1、Map接口概述
将键映射到值的对象
一个映射不能包含重复的键
每个键最多只能映射到一个值
2、Map接口和Collection接口的不同
Map是双列的,Collection是单列的
Map的键唯一,Collection的子体系Set是唯一的
Map集合的数据结构值针对键有效,跟值无关
Collection集合的数据结构是针对元素有效
二者的区别:
Collection集合:
单个元素:单身
Collection中的Set集合中,元素唯一
Map:成对元素:夫妻,通常叫做键值对
Map集合中的键唯一,值可以重复
3、接口成员方法
添加功能:
V put(K key,V value) 添加键值与值
删除功能:
V remove(Object key) 删除一个键值的内容
void clear() 清除内容
判断功能:
boolean containsKey(Objectkey) 是否包含此键值
booleancontainsValue(Object value) 是否包含此值
boolean isEmpty() 是否为空
int size() 集合的大小
V get(Object key) 获取键值
获取功能:
Set<K> keySet() 获取键值key的Set集合
Collection<V>values()
Set<Map.Entry<K,V>>entrySet()获得一个包含多个键值对元素的Set集合
举例:map集合遍历
遍历方式一:
1: 键找值 通过指定的键,获取对应的值
a: 获取到Map集合中所有的键的Set集合
b: 遍历键的集合,得到每一个键
c: 通过当前的键,获取对应的值
//创建Map集合
Map<String,String>map = new HashMap<String,String>();
//添加元素
map.put("谢霆锋", "张柏芝");
map.put("李亚鹏", "王菲");
map.put("汪峰", "章子怡");
//遍历
//a: 获取到Map集合中所有的键的Set集合
Set<String>keys = map.keySet();
//b: 遍历键的集合,得到每一个键
for (String key :keys) {
//c: 通过当前的键,获取对应的值
Stringvalue = map.get(key);
//显示
System.out.println(key +"--" + value );
}
遍历方式二:
通过键值对元素对象,找对应的键,找对应的值 结婚证方式
a:获取所有键值对元素的Set集合
b:遍历Set集合,得到每一个键值对元素对象
c:通过键值对元素对象,获取键,获取值
方法:
Set<Map.Entry<K,V>> entrySet(): 获得一个包含多个键值对元素的Set集合
Map.Entry<K,V> 等价 结婚证<男的,女的>
class 结婚证<男的,女的> {
private 男的 man;
private 女的 woman;
public 男的 getMan(){
return man;
}
public 女的 getWoman(){
return woman;
}
}
Set<Map.Entry<K,V>> entrySet = map.entrySet();
Set< 结婚证<男的,女的>> entrySet = map.entrySet();
代码实现:
<span style="white-space:pre"> </span>//创建Map集合
Map<String,String>map = new HashMap<String,String>();
//添加元素
map.put("谢霆锋", "张柏芝");
map.put("李亚鹏", "王菲");
map.put("汪峰", "章子怡");
//遍历
//a:获取所有键值对元素的Set集合
Set<Map.Entry<String,String>>entrySet = map.entrySet();
//b:遍历Set集合,得到每一个键值对元素对象
for (Map.Entry<String,String> entry : entrySet) {
//c:通过键值对元素对象,获取键,获取值
Stringkey = entry.getKey();//获取键
Stringvalue = entry.getValue();//获取值
System.out.println(key+"--"+ value);
}
Entry接口的结构:
Map.Entry 接口
interface Map<K,V> {
interface Entry<K,V>{
K getKey();
V getValue();
V setValue();
}
}
class HashMap implements Map{
static classEntry<K,V> implements Map.Entry<K,V>
K getKey(){
...
}
V getValue(){
...
}
V setValue(){
...
}
}
}
二、HashMap集合
1、概述
底层:哈希表结构
存储允许使用 null 值和 null 键
线程不同步-- 效率高-- 不安全
Map集合中的键要求保证唯一, 那么,HashMap集合中,如何保证 键 的唯一呢?
重写 hashCode() 与 equals()方法
注意:这里面的唯一指的是 键唯一, 针对键有效, 与值无关
2、案例
举例一:使用HashSet集合存储字符串,并遍历
方式一:
//创建HashMap集合
HashMap<String,String>hm = new HashMap<String,String>();
//添加键值对元素到集合
hm.put("谢霆锋", "张柏芝");
hm.put("李亚鹏", "王菲");
hm.put("汪峰", "章子怡");
//遍历方式1 键找值
//a: 获取到Map集合中所有的键
Set<String>keys = hm.keySet();
//b: 获取到每一个键
for (String key :keys) {
//c: 通过键,找对应的值
Stringvalue = hm.get(key);
System.out.println(key+"---"+value);
}
方式二:
//创建HashMap集合
HashMap<String,String>hm = new HashMap<String,String>();
//添加键值对元素到集合
hm.put("谢霆锋", "张柏芝");
hm.put("李亚鹏", "王菲");
hm.put("汪峰", "章子怡");
//遍历方式2 键值对 找键 找值
//a: 获取所有的键值对元素对象
Set<Entry<String, String>> entrySet =hm.entrySet();
//b: 获取到每一个键值对元素对象
for(Entry<String, String> entry: entrySet) {
//c: 通过当前的键值对元素对象,获取键,获取值
String key =entry.getKey();// 获取键
String value =entry.getValue(); //获取值
System.out.println(key+"---"+value);
}
举例二:键为String,值为Student
//创建集合对象
HashMap<String,Student>map = new HashMap<String,Student>();
//添加元素
Student s1 = newStudent("周瑜", 28);
Student s2 = newStudent("小乔", 18);
Student s3 = newStudent("大乔", 19);
map.put("itcast001",s1);
map.put("itcast002",s2);
map.put("itcast003",s3);
map.put("itcast004",s1);
//遍历
//方式1 键找值
Set<String>keys = map.keySet();
//获取到每一个键
for (String key :keys) {
//通过当前的key, 获取对应的值 Student
Students = map.get(key);
System.out.println(key+"---" + s.getName() +"---"+ s.getAge());
}
举例三:键为Person,值为String
注意:
如果HashMap集合中的键是自定义类对象,那么需要重写hashCode()和equals()
//创建集合对象
HashMap<Person,String>map = new HashMap<Person,String>();
//添加元素
Person s1 = newPerson("周瑜", 28);
Person s2 = newPerson("小乔", 18);
Person s3 = newPerson("大乔", 19);
map.put(s1,"itcast001");
map.put(s2,"itcast002");
map.put(s3,"itcast003");
map.put(s3,"itcast004");// 由于s3 键已存储, 用itcast004 替换 itcast003
//遍历 键值对 找键找值
Set<Entry<Person,String>> entrySet = map.entrySet();
//获取到每一个键值对元素对象
for (Entry<Person,String> entry : entrySet) {
Personkey = entry.getKey();
Stringvalue = entry.getValue();
System.out.println(value+"---"+ key.getName() +"---"+key.getAge() );
}
三、LinkHashMap集合
1、概述
底层:哈希表 + 链表
有序(元素的存与取顺序一致)
线程不同步 -- 效率高-- 不安全
Map 接口的哈希表和链接列表实现,具有可预知的迭代顺序。
2、案例:创建LinkHashMap集合对象遍历
//创建集合对象
LinkedHashMap<String,String>map = new LinkedHashMap<String,String>();
//添加元素到集合
map.put("谢霆锋", "张柏芝");
map.put("李亚鹏", "王菲");
map.put("汪峰", "章子怡");
//遍历 键找值
Set<String>keys = map.keySet();
for (String key :keys) {
//键找 值
Stringvalue = map.get(key);
System.out.println(key+"---"+value);
}
四、TreeMap集合
1、概述
键是红黑树结构,可以保证键的排序和唯一性,实现不是同步的。
TreeMap<K,V>
底层:红黑树 (二叉树)
线程不同步 -- 效率高-- 不安全
TreeMap集合中如何保证键的唯一和排序的?
1:对键实现 自然排序接口 Comparable , 重写 compareTo(obj1)方法
2: 对键 实现比较器接口 Comparator, 重写compare(obj1,obj2)方法
举例一:使用TreeMap,遍历
<span style="white-space:pre"> </span>// 创建TreeMap集合对象
TreeMap<String,String>map = new TreeMap<String,String>();
// 添加元素到集合
map.put("x谢霆锋", "张柏芝");
map.put("l李亚鹏", "王菲");
map.put("w汪峰", "章子怡");
//遍历键值对 找键 找值方式
Set<Entry<String,String>> entrySet = map.entrySet();
//获取到每一个键值对元素对象
for(Entry<String, String> entry : entrySet) {
//获取键
Stringkey = entry.getKey();
//获取值
Stringvalue = entry.getValue();
System.out.println(key+"---"+value);
}
举例二:<Student, String>
//创建TreeMap集合对象, 同时实现比较器
TreeMap<Student,String>map = new TreeMap<Student,String>(new
Comparator<Student>(){
@Override
publicint compare(Student s1, Student s2) {
//名字
intnum = s1.getName().compareTo(s2.getName());
//年龄
intresult = (num==0) ? (s1.getAge() - s2.getAge()) : num ;
returnresult;
}
});
//添加元素到集合
Student s1 = newStudent("z周瑜", 28);
Student s2 = newStudent("x小乔", 18);
Student s3 = newStudent("d大乔", 19);
map.put(s1,"itcast001");
map.put(s2,"itcast002");
map.put(s3,"itcast003");
map.put(s1,"itcast110");
//遍历
Set<Student>keys = map.keySet();
//获取到每一个键
for (Student key: keys) {
//键找 值
Stringvalue = map.get(key);
System.out.println(value+"---"+key.getName()+"---"+key.getAge() );
}
五、集合的嵌套使用
1、案例
举例一:根据给定的字符串得出每个字母出现的次数
格式:a(3)b(3)c(2)d(5)e(1)
分析:
通过结果可以看出 字母与次数之间有对应关系,我们可以采用Map集合
又由于结果是一个有序的结果,我们最终决定采用 TreeMap集合
a(5)
TreeMap<Character, Integer>
a 1++ ++
b 1
1: 定义一个字符串 "aababcabcdabcde"
2:定义一个集合 TreeMap<Character, Integer> 用来存储字母与次数
3:遍历字符串,得到每一个字母
4:判断当前字母在集合中是否存在
存在:
把当前字母 在集合中存储的次数获取出来,次数加1后,再存进去
不存在:
把当前字母 与次数1 存进去
5: 组装结果字符串 a(5)b(4)c(3)d(2)e(1)
通过遍历Map集合得到每一个键与值 ,然后拼装
代码实现:
//1:定义一个字符串 "aababcabcdabcde"
String str ="aababcabcdabcde";
//2:定义一个集合 TreeMap<Character,Integer> 用来存储字母与次数
TreeMap<Character,Integer> map = new TreeMap<Character, Integer>(); // 自然排序
//3:遍历字符串,得到每一个字母
for (int i =0;i< str.length(); i++) {
//得到每一个字母
char ch= str.charAt(i);
//4:判断当前字母在集合中是否存在
if(map.containsKey(ch)) {
//把当前字母在集合中存储的次数获取出来, 次数加1后,再存进去
intcount = map.get(ch);
count++;
map.put(ch,count);
} else {
//把当前字母 与次数1 存进去
map.put(ch,1);
}
}
//System.out.println(map);
//5: 组装结果字符串 a(5)b(4)c(3)d(2)e(1)
//通过遍历Map集合得到每一个键与值 ,然后拼装
StringBuilder sb= new StringBuilder();
//方式2 键值对 找键 找值
Set<Entry<Character,Integer>> entrySet = map.entrySet();
//得到每一个键值对元素
for(Entry<Character, Integer> entry : entrySet) {
//找键 --- 字母
Characterc = entry.getKey();
//找值 --- 次数
Integern = entry.getValue();
sb.append(c).append("(").append(n).append(")");//a(5)
}
//打印结果
System.out.println(sb.toString());
案例二:HashMap嵌套HashMap
czbk
(基础班)jc
01 张三
02 李四
(就业班)jy
01 王五
02 赵六
分析:
1: 创建基础班HashMap集合 HashMap<String, String>
学号 姓名
2: 向基础班集合添加元素
3: 创建就业班HashMap集合 HashMap<String,String>
学号 姓名
4: 向就业班集合添加元素
5: 创建传智播客HashMap集合 HashMap<String, HashMap<String,String> >
基础班 基础班HashMap集合
就业班 就业班HashMap集合
6: 向传智播客HashMap 添加元素
7: 遍历
代码实现:
//1: 创建基础班HashMap集合 HashMap<String, String>
HashMap<String,String> jc = new HashMap<String, String>();
//2: 向基础班集合添加元素
jc.put("01","张三");
jc.put("02","李四");
//3: 创建就业班HashMap集合 HashMap<String, String>
HashMap<String,String> jy = new HashMap<String, String>();
//4: 向就业班集合添加元素
jy.put("01","王五");
jy.put("02","赵六");
//5:创建传智播客HashMap集合 HashMap<String,HashMap<String, String> >
HashMap<String,HashMap<String, String>> czbk = new HashMap<String,HashMap<String, String>>();
//6:向传智播客HashMap 添加元素
czbk.put("基础班", jc);
czbk.put("就业班", jy);
//7: 遍历
//System.out.println(czbk);
// 键找 值
//所有的班级名称
Set<String>classeNames = czbk.keySet();
for (StringclasseName : classeNames) {
//每一个班级名称
System.out.println(classeName);
//通过班级名称,找到对应班级的所有学生信息
HashMap<String,String> students = czbk.get(classeName);
//获得当前班级中所有学生的学号
Set<String>ids = students.keySet();
//得到每一个学生的学号
for(String id : ids) {
//通过学号获取对应姓名
Stringname = students.get(id);
System.out.println("\t"+id+ "---"+ name);
}
}
2、面试题 ★★★
(1)HashMap和Hashtable的区别?
HashMap:
线程不同步--- 效率高--- 不安全
存储的元素使用null键null值
Hashtable
线程同步—效率低---安全
不能够使用null键null值作为元素
代码举例:
HashMap<String,String>hashMap = new HashMap<String,String>();
hashMap.put(null,"王朝");
hashMap.put("itcast110",null);
hashMap.put(null,null);
System.out.println(hashMap);
Hashtable<String,String>hashtable = new Hashtable<String,String>();
//hashtable.put(null,"马汉");//NullPointerException
//hashtable.put("itcast365",null);//NullPointerException
//hashtable.put(null,null);//NullPointerException
System.out.println(hashtable);
(2)List、Set、Map等接口是否都继承子Map接口
Collection
|-- List
|--Set
Map
|--HashMap
|--TreeMap
(3)你常见的集合类有哪些,都有什么方法?
Collection
|- List
|-ArrayList
|-LinkedList
|-Vector
|- Set
|-HashSet
|-TreeSet
Map
|-HashMap
|-TreeMap
|-Hashtable
六、Collection类
1、概述
针对集合操作的工具类
2、成员方法
public static <T>void sort(List<T> list) 排序
public static <T>int binarySearch(List<?> list,T key) 二分查找
public static <T> Tmax(Collection<?> coll) 最大值
public static voidreverse(List<?> list) 反转
public static voidshuffle(List<?> list) 随机打乱
public static <T>boolean replaceAll(List<T> list, T oldVal, T newVal) 替换
3、集合的结构
集合
|-- Collection
|-- List
|-- Set
|-- Map
七、案例:通讯录实现
略。。。