您的位置:首页 > 职场人生

黑马程序员——Java基础—集合框架(三)

2015-04-09 16:09 495 查看
———Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ———

一Map集合

二Map扩展知识

集合框架(三)

一、Map集合

1.概述

Map
集合用于存储键值对,且它保证键的唯一性,并且每个键最多只能映射一个值。
Map
集合是
Set
集合的底层实现,其和
Collection
在集合框架中并列存在。

2.Map集合共性方法

1)添加操作

-V put(K key, V value):添加指定的键值对

-void putAll(Map<? extends K, ? extends V>, m):添加指定Map集合

注意:

put()会返回该键对应的被覆盖的值

第一次存储put(“01”, “zhangsan”);返回null;”01”键对应的被覆盖的值为null;

第二次存储put(“01”, “wangwu”);返回”zhangsan”;”01”键对应的被覆盖的值为”zhangsan”;

2)删除操作

-void clear():清楚所有映射关系

-V remove(Object key):根据键删除映射值

3)判断操作

-boolean containsKey(Object key):判断是否包含指定键的映射关系

-boolean containsValue(Object value):判断是否包含指定值的映射关系

-boolean isEmpty():判断是否为空

4)获取操作

-V get(Object Key):通过键获得值

-int size():获取Map长度

-Collection values():返回所有的映射的值

-Set entrySet():返回包含的映射关系

-Set keySet():返回包含的键

3.Map集合子类

Map

HashTable

HashMap

TreeMap

1)HashTable

HashTable
底层是哈希表数据结构。此类实现一个哈希表,该哈希表将键映射到相应的值上。任何非null的对象都可以做键或值。为了成功在哈希表中存储和获取对象,用作键的对象必须实现
hashCode()
方法和
equals()
方法。
HashTable
类是线程同步的。

2)HashMap

HashMap
底层是哈希表数据结构。此类与
HashTable
大致相同,但允许使用
null
的对象作为键或值。
HashMap
不保证映射的顺序,特别是它不保证该顺序恒久不变。
HashMap
类是线程不同步的,效率高于
HashTable


3)TreeMap

TreeMap
底层是二叉树数据结构。此类可以实现为
Map
集合中的键排序。
TreeMap
线程不同步。

4.Map集合方法应用

演示
Map
集合基本方法。

示例代码:

package com.heisejiuhuche.Collection;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

public class MapDemo {
public static void main(String[] args) {
Map<String, String> hm = new HashMap<String, String>();

/* 添加操作 */
hm.put("01", "java01");
hm.put("02", "java02");
hm.put("03", "java03");
hm.put("04", "java04");

System.out.println(hm);

/* 清空Map集合 */
hm.clear();
/* 删除04键及其值 */
hm.remove("04");
System.out.println(hm);

/* Map中是否包含指定键或值 */
System.out.println(hm.containsKey("02"));
System.out.println(hm.containsValue("java03"));

/* 通过键获取值 */
System.out.println(hm.get("01"));
/* 获取Map长度 */
System.out.println(hm.size());

Collection<String> c = hm.values();

for(String str : c) {
System.out.println("Collection: " + str);
}
}
}


程序输出结果:

{01=java01, 02=java02, 03=java03, 04=java04}
{01=java01, 02=java02, 03=java03}
true
true
java01
3
Collection: java01
Collection: java02
Collection: java03


5.Map集合元素取出方式

1)keySet()方法

Map
中所有的
key
存入
Set
集合,再通过
Set
集合的迭代器将所有
key
取出,最后通过
get()
方法获取每个
key
的对应值。

示例代码:

package com.heisejiuhuche.Collection;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class MapDemo {
public static void main(String[] args) {
keySet();
entrySet();
}

private static void keySet() {
Map<String, String> hm = new HashMap<String, String>();

hm.put("01", "java01");
hm.put("02", "java02");
hm.put("03", "java03");
hm.put("04", "java04");

for(Iterator<String> it = hm.keySet().iterator(); it.hasNext(); ) {
String key = it.next();
System.out.println(key + "::" + hm.get(key));
}
}
}


程序输出结果:

01::java01
02::java02
03::java03
04::java04


2)entrySet()方法

Map
集合中的映射关系存入到
Set
集合中。该关系的数据类型是
Map.Entry


示例代码:

package com.heisejiuhuche.Collection;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class MapDemo {
public static void main(String[] args) {
keySet();
entrySet();
}

private static void entrySet() {
Map<String, String> hm = new HashMap<String, String>();

hm.put("01", "java01");
hm.put("02", "java02");
hm.put("03", "java03");
hm.put("04", "java04");

for(Iterator<Map.Entry<String, String>> it = hm.entrySet().iterator();  it.hasNext(); ) {
Map.Entry<String, String> me = it.next();
System.out.println(me.getKey() + "-----" + me.getValue());
}
}
}


程序输出结果:

01-----java01
02-----java02
03-----java03
04-----java04




高能:

Map.Entry中的Entry,是一个接口。它是Map接口中的内部接口。示例代码:

interface Map {
public static interface Entry {
public abstract Object getKey();
public abstract Object getValue();
}
}


6.Map练习

1)练习1

每一个学生有对应的归属地,用
Map
集合存储学生
Student
,地址
String
。学生的属性有姓名,年龄。当姓名和年龄相同时视为同一学生,保证学生唯一性。

示例代码:

package com.heisejiuhuche.Collection;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class MapTest {
public static void main(String[] args) {
Map<MyStudent, String> m = new HashMap<MyStudent, String>();

m.put(new MyStudent("lisi01", 12), "beijing");
m.put(new MyStudent("lisi03", 14), "shanghai");
m.put(new MyStudent("lisi03", 14), "hangzhou");
m.put(new MyStudent("lisi04", 15), "chengdu");
m.put(new MyStudent("lisi02", 13), "shenzhen");

/*
* keySet()取出
*/
for(Iterator<MyStudent> it = m.keySet().iterator(); it.hasNext(); ) {
MyStudent stu = it.next();
System.out.println(stu.toString() + "------" + m.get(stu));
}

/*
* entrySet()取出
*/
for(Iterator<Map.Entry<MyStudent, String>> iter = m.entrySet().iterator(); iter.hasNext(); ) {
Map.Entry<MyStudent, String> me = iter.next();
MyStudent stu = me.getKey();
String str = me.getValue();
System.out.println(stu.toString() + "::" + str);
}
}
}

class MyStudent implements Comparable<MyStudent> {
private String name;
private int age;

MyStudent(String name, int age) {
this.name = name;
this.age = age;
}

public void setName(String name) {
this.name = name;
}

public void setAge(int age) {
this.age = age;
}

public String getName() {
return name;
}

public int getAge() {
return age;
}

/*
* 复写compareTo方法,确保存入二叉树数据结构中有比较性
*/
public int compareTo(MyStudent stu) {
int num = new Integer(this.age).compareTo(new Integer(stu.age));

if(num == 0) {
return this.name.compareTo(stu.name);
}

return num;
}

/*
* 复写hashCode方法,确保键的唯一性
*/
public int hashCode() {
return this.name.hashCode() + this.age * 37;
}

/*
* 复写equals方法,确保键的唯一性
*/
public boolean equals(Object obj) {
if(!(obj instanceof MyStudent)) {
throw new ClassCastException("Class not match...");
}
MyStudent stu = (MyStudent)obj;
return this.name.equals(stu.name) && this.age == stu.age;
}

public String toString() {
return this.name + "===" + this.age;
}
}


程序输出结果:

lisi03===14------hangzhou
lisi01===12------beijing
lisi04===15------chengdu
lisi02===13------shenzhen
lisi03===14::hangzhou
lisi01===12::beijing
lisi04===15::chengdu
lisi02===13::shenzhen


2)练习2

对学生对象的姓名进行升序排序。

示例代码(MyStudent类同上):

package com.heisejiuhuche.Collection;

import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

public class TreeMapTest {
public static void main(String[] args) {
Map<MyStudent, String> tm = new TreeMap<MyStudent, String>(new MyComparator());

tm.put(new MyStudent("alisi03", 14), "shanghai");
tm.put(new MyStudent("blisi03", 14), "hangzhou");
tm.put(new MyStudent("dlisi04", 15), "chengdu");
tm.put(new MyStudent("lisi02", 13), "shenzhen");
tm.put(new MyStudent("lisi01", 12), "beijing");

for(Iterator<Map.Entry<MyStudent, String>> it = tm.entrySet().iterator(); it.hasNext(); ) {
Map.Entry<MyStudent, String> me = it.next();
MyStudent stu = me.getKey();
String str = me.getValue();
System.out.println(stu.toString() + "***" + str);
}
}
}

class MyComparator implements Comparator<MyStudent> {
public int compare(MyStudent s1, MyStudent s2) {
int num = s1.getName().compareTo(s2.getName());

if(num == 0) {
return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
}

return num;
}
}


声明了比较器,按姓名排序。程序输出结果:

alisi03===14***shanghai
blisi03===14***hangzhou
dlisi04===15***chengdu
lisi01===12***beijing
lisi02===13***shenzhen


3)练习3

获取
"abg%c*_-dabc*()!gf"
字符串中每个字母出现的次数。打印结果为:
a(1)c(2)....


示例代码:

package com.heisejiuhuche.Collection;

/**
* 1.将字符串转换为字符数组;声明TreeMap集合
* 2.遍历字符数组,将每一个字母(不是字母忽略)在TreeMap中的键取值
* 3.如果该字母没有值,就将该字母和1存入TreeMap
* 4.如果有值,就获取该字母键所对应的值,将该值自增1,并和字母一起存入TreeMap
* 5.声明StringBuilder容器,将最终结果按格式存入容器,打印
*/

import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

public class TreeMapTest1 {
public static void main(String[] args) {
String str = "abag%c*_-dadbc*()!gfkk";

System.out.println(charCount(str));
}

public static String charCount(String str) {
/* 声明集合 */
Map<Character, Integer> tm = new TreeMap<Character, Integer>();

/* 将字符串转换为字符数组 */
char[] ch = str.toCharArray();

/* 声明变量用于获取字母键对应的值 */
int count = 0;

/* 遍历字符数组,将每个字母键在集合中做匹配 */
for (int x = 0; x < ch.length; x++) {
if (!Character.isLetter(ch[x])) {
continue;
}

/* 获取每个字母键对应的值 */
Integer value = tm.get(ch[x]);

/* 如果值不为空,则用count记录value */
if (!(value == null)) {
count = value;
}
/*
* 如果值不为空,count则为value的值,自增1; 如果值为空,count则为0,自增1
*/
count++;
/* 将字母和count存入集合 */
tm.put(ch[x], count);
/* count清零,以便下次使用 */
count = 0;
}

/* 声明StringBuilder容器 */
StringBuilder sb = new StringBuilder();

/* 取出最终结果的键值对,分别按格式存入StringBuilder */
for (Iterator<Map.Entry<Character, Integer>> it = tm.entrySet()
.iterator(); it.hasNext();) {
Map.Entry<Character, Integer> me = it.next();
sb.append(me.getKey()).append("(").append(me.getValue())
.append(")");
}

return sb.toString();
}
}


程序输出结果:

a(3)b(2)c(2)d(2)f(1)g(2)k(2)


二、Map扩展知识

Map集合的集合嵌套。现在有一所学校,学校中有很多教室,每个教室里面有很多学生,学生有学号和姓名。学校和教室是一个映射关系,教室里面的学生的学号和姓名是一个映射关系。那么可以理解成,一个Map存储着学生的映射,这个学生Map构成教室,嵌套在学校和教室的映射关系Map中。现在要求,在教室中添加学生映射,在学校中添加教室,最后打印每个教室中学生的学好和姓名。

示例代码:

package com.heisejiuhuche.Collection;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class TreeMapEmbedTest {
public static void main(String[] args) {
Map<String, Map<String, String>> school = new HashMap<String, Map<String, String>>();

Map<String, String> classroom1 = new HashMap<String, String>();

Map<String, String> classroom2 = new HashMap<String, String>();

school.put("classroom1", classroom1);
school.put("classromm2", classroom2);

classroom1.put("01", "zhangsan");
classroom1.put("02", "wangwu");
classroom2.put("03", "zhaoliu");
classroom2.put("04", "zhouqi");

printMap(school);
}

/* 循环遍历外层学校集合,取出教室名和教室集合,并打印;
* 再遍历教室集合,取出学生学号和姓名,并打印;
*/
private static void printMap(Map<String, Map<String, String>> hm) {
for(Iterator<Map.Entry<String, Map<String, String>>> itSch = hm.entrySet().iterator(); itSch.hasNext(); ) {
Map.Entry<String, Map<String, String>> me1 = itSch.next();
HashMap<String, String> stu = (HashMap)me1.getValue();
System.out.println(me1.getKey());
for(Iterator<Map.Entry<String, String>> itCla = stu.entrySet().iterator(); itCla.hasNext(); ) {
Map.Entry<String, String> me2 = itCla.next();
System.out.println(me2.getKey() + "::" + me2.getValue());
}
}
}
}


程序输出结果:

classromm2
03::zhaoliu
04::zhouqi
classroom1
01::zhangsan
02::wangwu


一般情况下,不会出现这样的集合嵌套;因为学生的属性学号和姓名,会被封装成学生类。那么上述情况变为,学校和教室是一个对应关系,教室和学生类是一个对应关系。学校和教室的关系存储在Map集合,教室中存储学生对象而不是映射关系,所以教室变为一个List集合即可。

示例代码:

package com.heisejiuhuche.Collection;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class TreeMapEmbedTest2 {
public static void main(String[] args) {
Map<String, List<Stu>> school = new HashMap<String, List<Stu>>();

List<Stu> classroom1 = new ArrayList<Stu>();
List<Stu> classroom2 = new ArrayList<Stu>();

school.put("classroom1", classroom1);
school.put("classroom2", classroom2);

classroom1.add(new Stu("01", "zhangsan"));
classroom1.add(new Stu("02", "wangwu"));
classroom2.add(new Stu("03", "zhaoliu"));
classroom2.add(new Stu("04", "zhouqi"));

printMap(school);
}

/*
* 循环遍历外层学校集合,取出教室名和教室集合,并打印;
* 再遍历教室集合,取出学生学号和姓名,并打印;
*/
private static void printMap(Map<String, List<Stu>> hm) {
for(Iterator<Map.Entry<String, List<Stu>>> itSch = hm.entrySet().iterator(); itSch.hasNext(); ) {
Map.Entry<String, List<Stu>> me1 = itSch.next();
System.out.println(me1.getKey());
ArrayList<Stu> stu = (ArrayList)me1.getValue();
for(Iterator<Stu> itStu = stu.iterator(); itStu.hasNext(); ) {
System.out.println(itStu.next().toString());
}
}
}
}

/*
* 声明学生类
*/
class Stu {
private String id;
private String name;

Stu(String id, String name) {
this.id = id;
this.name = name;
}

public String toString() {
return this.id + "::" + this.name;
}
}


程序输出结果:

classroom1
01::zhangsan
02::wangwu
classroom2
03::zhaoliu
04::zhouqi


———Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ———
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: