黑马程序员--集合框架【3】

本文深入讲解Java中的Map集合,包括其基本操作如添加、删除、判断等,以及HashMap、Hashtable和TreeMap的具体特点与应用场景。并通过示例演示如何利用Map集合解决实际问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

------------------- android培训java培训、期待与您交流!------------------




/*
Map集合:该集合存储键值对。一对一对往里存。而且要保证键的唯一性。
1,添加。
put(K key, V value) 
putAll(Map<? extends K,? extends V> m) 
 
2,删除。
clear() 
remove(Object key) 
 
3,判断。
containsValue(Object value) 
containsKey(Object key) 
isEmpty() 
 
 
4,获取。
get(Object key) 
size() 
values() 
 
entrySet() 
keySet() 
 
Map
|--Hashtable:底层是哈希表数据结构,不可以存入null键null值。该集合是线程同步的。jdk1.0.效率低。
|--HashMap:底层是哈希表数据结构,允许使用 null 值和 null 键,该集合是不同步的。将hashtable替代,jdk1.2.效率高。
|--TreeMap:底层是二叉树数据结构。线程不同步。可以用于给map集合中的键进行排序。
 
 
和Set很像。
其实大家,Set底层就是使用了Map集合。
 
 
*/
import java.util.*;
class  MapDemo
{
public static void main(String[] args) 
{
Map<String,String> map = new HashMap<String,String>();
 
//添加元素,添加元素,如果出现添加时,相同的键。那么后添加的值会覆盖原有键对应值。
//并put方法会返回被覆盖的值。
System.out.println("put:"+map.put("01","zhangsan1"));
System.out.println("put:"+map.put("01","wnagwu"));//新值代替旧值!!!!-------一定记住
map.put("02","zhangsan2");
map.put("03","zhangsan3");
 
System.out.println("containsKey:"+map.containsKey("022"));//不存在:false
//System.out.println("remove:"+map.remove("02"));//删除同时,返回键对应的值!//不存在,返回null
 
System.out.println("get:"+map.get("023"));//null
 
map.put("04",null);//hashMap支持存入空
System.out.println("get:"+map.get("04"));
//可以通过get方法的返回值来判断一个键是否存在。通过返回null来判断。
 
 
 
//获取map集合中所有的值。
Collection<String> coll = map.values();//返回集合,所以用Collection
 
System.out.println(coll);
System.out.println(map);
 
 
}
}
/*
打印结果:
put:null
put:zhangsan1
containsKey:false
get:null
get:null
[null, wnagwu, zhangsan2, zhangsan3]
{04=null, 01=wnagwu, 02=zhangsan2, 03=zhangsan3}
*/



-------------------------------------------------------------------------------------------------------- 

/*
map集合的两种取出方式:
1,Set<k> keySet:将map中所有的键存入到Set集合。因为set具备迭代器。
所有可以迭代方式取出所有的键,在根据get方法。获取每一个键对应的值。
 
Map集合的取出原理:将map集合转成set集合。在通过迭代器取出。
 
 
2,Set<Map.Entry<k,v>> entrySet:将map集合中的映射关系存入到了set集合中,
而这个关系的数据类型就是:Map.Entry
 
Entry其实就是Map中的一个static内部接口。
为什么要定义在内部呢?
因为只有有了Map集合,有了键值对,才会有键值的映射关系。
关系属于Map集合中的一个内部事物。
而且该事物在直接访问Map集合中的元素。
 
 
 
*/
 
import java.util.*;
 
 
class MapDemo2 
{
public static void main(String[] args) 
{
Map<String,String> map = new HashMap<String,String>();//HashMap实现了接口Map
 
map.put("02","zhangsan2");
map.put("03","zhangsan3");
map.put("01","zhangsan1");
map.put("04","zhangsan4");
 
 
 
//将Map集合中的映射关系取出。存入到Set集合中。
Set<Map.Entry<String,String>> entrySet = map.entrySet();//泛型嵌套---将映射(Map.entry类型)存到set中
  //<结婚证<丈夫,妻子>>
 
Iterator<Map.Entry<String,String>> it = entrySet.iterator();//迭代器泛型和set一样
 
while(it.hasNext())
{
Map.Entry<String,String> me = it.next();//结婚证
 
String key = me.getKey();//丈夫
String value = me.getValue();//妻子
 
System.out.println(key+":"+value);
 
}
 
/*
//先获取map集合的所有键的Set集合,keySet();
Set<String> keySet = map.keySet();//String代表键的类型
 
//有了Set集合。就可以获取其迭代器。
Iterator<String> it = keySet.iterator();//String和集合一样
 
while(it.hasNext())
{
String key = it.next();//取到所有的键值
 
//有了键可以通过map集合的get方法获取其对应的值。
String value  = map.get(key);
System.out.println("key:"+key+",value:"+value);
}
 
*/
 
}
}
 
 
/*
Map.Entry 其实Entry也是一个接口,它是Map接口中的一个内部接口。
 
 
 
 
interface Map//接口
{
//能加static一定是内部接口//因为只有成员才能用static修饰
public static interface Entry//内部接口-------//先有Map集合,才能有关系 ,所以entry要定义成内部接口
{
public abstract Object getKey();
public abstract Object getValue();
 
}
}
 
class HashMap implements Map//实现
{
class Hahs implements Map.Entry
{
public  Object getKey(){}
public  Object getValue(){}
}
 
}
*/


--------------------------------------------------------------------------------------------------------  

/*
每一个学生都有对应的归属地。
学生Student,地址String。
学生属性:姓名,年龄。
注意:姓名和年龄相同的视为同一个学生。
保证学生的唯一性。
 
 
 
1,描述学生。
 
2,定义map容器。将学生作为键,地址作为值。存入。
 
3,获取map集合中的元素。
 
*/
 
import java.util.*;
class Student implements Comparable<Student>//如果Student继承Person,也可以写Person
{
private String name;
private int age;
Student(String name,int age)
{
this.name = name;
this.age = age;
}
 
public int compareTo(Student s)//先按年龄排序;年龄相同再按姓名排序
{
int num = new Integer(this.age).compareTo(new Integer(s.age));
 
if(num==0)
return this.name.compareTo(s.name);
return num;
}
 
 
//hashCode和equals保证了键值的唯一性!!
public int hashCode()//覆盖!   //默认比较地址值//需要复写hashcode
{
return name.hashCode()+age*34;
}
 
public boolean equals(Object obj)//覆盖!
{
if(!(obj instanceof Student))
throw new ClassCastException("类型不匹配");
 
Student s = (Student)obj;
 
return this.name.equals(s.name) && this.age==s.age;
}
 
 
 
 
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
//setName,setAge也一定要写
 
public String toString()
{
return name+":"+age;
}
}
 
 
 
class  MapTest
{
public static void main(String[] args) 
{
HashMap<Student,String> hm = new HashMap<Student,String>();
 
hm.put(new Student("lisi1",21),"beijing");
hm.put(new Student("lisi1",21),"tianjin");//键一样,新的覆盖旧的。。北京的就不打印了!
hm.put(new Student("lisi2",22),"shanghai");
hm.put(new Student("lisi3",23),"nanjing");
hm.put(new Student("lisi4",24),"wuhan");
 
//第一种取出方式 keySet
 
Set<Student> keySet = hm.keySet();//键值是Student
 
Iterator<Student> it = keySet.iterator();
//上面两句合并
//Iterator<Student> it = hm.keySet().iterator();
 
while(it.hasNext())
{
Student stu = it.next();
String addr = hm.get(stu);
System.out.println(stu+".."+addr);
}
 
 
//第二种取出方式 entrySet
Set<Map.Entry<Student,String>> entrySet = hm.entrySet();
 
Iterator<Map.Entry<Student,String>> iter = entrySet.iterator();
 
while(iter.hasNext())
{
Map.Entry<Student,String> me = iter.next();
Student stu = me.getKey();
String addr = me.getValue();
System.out.println(stu+"........."+addr);
}
}
}
 


--------------------------------------------------------------------------------------------------------  

/*
需求:对学生对象的年龄进行升序排序。
 
因为数据是以键值对形式存在的。
所以要使用可以排序的Map集合。TreeMap。
*/
 
 
//不用写Student类,因为上个练习MapTest2,已经生成Student.class
 
import java.util.*;
 
class StuNameComparator implements Comparator<Student>
{
public int compare(Student s1,Student s2)
{
int num = s1.getName().compareTo(s2.getName());//先按名字
if(num==0)
return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));//再按年龄
 
return num;
}
}
 
 
class  MapTest2
{
public static void main(String[] args) 
{
//TreeMap,打印时,有自然顺序
//TreeMap<Student,String> tm = new TreeMap<Student,String>();
 
TreeMap<Student,String> tm = new TreeMap<Student,String>(new StuNameComparator());
 
tm.put(new Student("blisi3",23),"nanjing");
tm.put(new Student("lisi1",21),"beijing");
tm.put(new Student("alisi4",24),"wuhan");
tm.put(new Student("lisi1",21),"tianjin");//新的代替旧的!
tm.put(new Student("lisi2",22),"shanghai");
 
 
Set<Map.Entry<Student,String>> entrySet = tm.entrySet();
 
Iterator<Map.Entry<Student,String>> it = entrySet.iterator();
 
while(it.hasNext())
{
Map.Entry<Student,String> me = it.next();
 
Student stu = me.getKey();
String addr = me.getValue();
System.out.println(stu+":::"+addr);
}
}
}
 


--------------------------------------------------------------------------------------------------------  

/*
练习:
"sdfgzxcvasdfxcvdf"获取该字符串中的字母出现的次数。
 
希望打印结果:a(1)c(2).....
 
通过结果发现,每一个字母都有对应的次数。
说明字母和次数之间都有映射关系。
 
注意了,当发现有映射关系时,可以选择map集合。
因为map集合中存放就是映射关系。
 
 
什么使用map集合呢?
当数据之间存在这映射关系时,就要先想map集合。
 
思路:
1,将字符串转换成字符数组。因为要对每一个字母进行操作。
 
2,定义一个map集合,因为打印结果的字母有顺序,所以使用treemap集合。
 
3,遍历字符数组。
将每一个字母作为键去查map集合。
如果返回null,将该字母和1存入到map集合中。
如果返回不是null,说明该字母在map集合已经存在并有对应次数。
那么就获取该次数并进行自增。,然后将该字母和自增后的次数存入到map集合中。覆盖掉原来键所对应的值。
 
4,将map集合中的数据变成指定的字符串形式返回。
 
 
 
*/
import java.util.*;
class  MapTest3
{
public static void main(String[] args) 
{
String s= charCount("ak+abAf1c,dCkaAbc-defa");
System.out.println(s);
}
 
public static String charCount(String str)
{
char[] chs = str.toCharArray();
 
TreeMap<Character,Integer> tm = new TreeMap<Character,Integer>();//必须存对象包装类,不能使char或int
 
 
int count = 0;
for(int x=0; x<chs.length; x++)
{
 
 
if(!(chs[x]>='a' && chs[x]<='z' || chs[x]>='A' && chs[x]<='Z'))//只判断字母
continue;//如果不在区间内,继续下一次循环
 
Integer value = tm.get(chs[x]);
 
 
if(value!=null)
count = value;
count++;
tm.put(chs[x],count);//直接往集合中存储字符和数字,为什么可以,因为自动装箱。
 
//count用完之后要清零!!!
count = 0;
 
/*
if(value==null)
{
tm.put(chs[x],1);
}
else
{
value = value + 1;
tm.put(chs[x],value);
}
*/
 
 
}
 
//System.out.println(tm);
 
StringBuilder sb = new StringBuilder();
 
Set<Map.Entry<Character,Integer>> entrySet = tm.entrySet();
Iterator<Map.Entry<Character,Integer>>  it = entrySet.iterator();
 
while(it.hasNext())
{
Map.Entry<Character,Integer> me = it.next();
Character ch = me.getKey();
Integer value = me.getValue();
sb.append(ch+"("+value+")");
}
 
return sb.toString();
}
 
}
 


--------------------------------------------------------------------------------------------------------  

/*
map扩展知识。
 
map集合被使用是因为具备映射关系。
 
"yureban"   Student("01" "zhangsan");
 
"yureban" Student("02" "lisi");
 
"jiuyeban" "01" "wangwu";
"jiuyeban" "02" "zhaoliu";
 
一个学校有多个教室。每一个教室都有名称。
 
 
*/
import java.util.*;
 
class Student
{
private String id;
private String name;
Student(String id,String name)
{
this.id = id;
this.name = name;
}
public String toString()
{
return id+":::"+name;
}
}
 
class  MapDemo3
{
 
public static void demo()
{
HashMap<String,List<Student>> czbk = new HashMap<String,List<Student>>();
 
List<Student> reyu = new ArrayList<Student>();
List<Student> jiuye = new ArrayList<Student>();
 
czbk.put("yureban",reyu);//list集合添加进去
czbk.put("jiuyeban",jiuye);
 
 
reyu.add(new Student("01","zhagnsa"));
reyu.add(new Student("04","wangwu"));
jiuye.add(new Student("01","zhouqi"));
jiuye.add(new Student("02","zhaoli"));
 
 
 
Iterator<String> it = czbk.keySet().iterator();//遍历传智播客房间!
 
while(it.hasNext())//循环嵌套形式
{
String roomName = it.next();
List<Student> room = czbk.get(roomName);
 
System.out.println(roomName);
getInfos(room);
}
 
}
 
public static void getInfos(List<Student> list)
{
Iterator<Student> it = list.iterator();
while(it.hasNext())
{
Student s = it.next();
System.out.println(s);
}
}
 
 
 
 
public static void main(String[] args) 
{
 demo();
 
/*
HashMap<String,List<Student>> czbk = new HashMap<String,List<Student>>();
 
HashMap<String,String> yure = new HashMap<String,String>();
 
HashMap<String,String> jiuye = new HashMap<String,String>();
 
czbk.put("yureban",yure);
czbk.put("jiuyeban",jiuye);
 
 
yure.put("01","zhagnsan");
yure.put("02","lisi");
 
jiuye.put("01","zhaoliu");
jiuye.put("02","wangwu");
 
 
 
//遍历czbk集合。获取所有的教室。
Iterator<String> it = czbk.keySet().iterator();
 
while(it.hasNext())
{
String roomName = it.next();
HashMap<String,String> room = czbk.get(roomName);
 
System.out.println(roomName);
getStudentInfo(room);//大圈套小圈,循环
}
 
 
//getStudentInfo(jiuye);//打印就业班学生
//getStudentInfo(yure);//打印预热班学生
*/
 
}   
                                  //教室<学号,姓名>
public static void getStudentInfo(HashMap<String,String> roomMap)
{
Iterator<String> it = roomMap.keySet().iterator();
 
while(it.hasNext())
{
String id = it.next();
String name = roomMap.get(id);
System.out.println(id+":"+name);
}
}
}
 


--------------------------------------------------------------------------------------------------------   

转载于:https://www.cnblogs.com/Stone-sw/archive/2013/03/19/2969415.html

1.方法中的内部类能不能访问方法中的局部变量,为什么? 2.分析运行结果,说明原理。(没有分析结果不得分) import java.util.ArrayList; class Data { int val; } public class Test { public static void main(String args[]) { Data data = new Data(); ArrayList list = new ArrayList(); for (int i = 100; i < 103; i++) { data.val = i; list.add(data); } for (Data d : list) { System.out.println(d.val); } } } 3.编写一个类,在main方法中定义一个Map对象(采用泛型), * 加入若干个对象,然后遍历并打印出各元素的key和value。 4.编写一个类,在main方法中定义一个Map对象(采用泛型), * 加入若干个对象,然后遍历并打印出各元素的key和value。 5.定义一个文件输入流,调用read(byte[] b)方法将exercise.txt * 文件中的所有内容打印出来(byte数组的大小限制为5)。 6.存在一个JavaBean,它包含以下几种可能的属性: 1:boolean/Boolean 2:int/Integer 3:String 4:double/Double 属性名未知,现在要给这些属性设置默认值,以下是要求的默认值: String类型的默认值为字符串 www.itheima.com int/Integer类型的默认值为100 boolean/Boolean类型的默认值为true double/Double的默认值为0.01D. 只需要设置带有getXxx/isXxx/setXxx方法的属性,非JavaBean属性不设置,请用代码实现 7.有一个类为ClassA,有一个类为ClassB,在ClassB中有一个方法b,此方法抛出异常, * 在ClassA类中有一个方法a,请在这个方法中调用b,然后抛出异常。 * 在客户端有一个类为TestC,有一个方法为c ,请在这个方法中捕捉异常的信息。 * 完成这个例子,请说出java中针对异常的处理机制。 8.编写一个程序,获取10个1至20的随机数,要求随机数不能重复。 9.编写一个程序,它先将键盘上输入的一个字符串转换成十进制整数, * 然后打印出这个十进制整数对应的二进制形式。 * 这个程序要考虑输入的字符串不能转换成一个十进制整数的情况, * 并对转换失败的原因要区分出是数字太大,还是其中包含有非数字字符的情况。 * 提示:十进制数转二进制数的方式是用这个数除以2, * 余数就是二进制数的最低位,接着再用得到的商作为被除数去除以2, * 这次得到的余数就是次低位,如此循环,直到被除数为0为止。 * 其实,只要明白了打印出一个十进制数的每一位的方式 * (不断除以10,得到的余数就分别是个位,十位,百位), * 就很容易理解十进制数转二进制数的这种方式。 10.有100个人围成一个圈,从1开始报数,报到14的这个人就要退出。然后其他人重新开始,从1报数,到14退出。 * 问:最后剩下的是100人中的第几个人?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值