24-08-08 javaSE Map集合
Map接口的特点
-
Map与Collection并列存在。用于保存具有映射关系的数据:Key-Value(双列元素)
-
Map 中的 key 和 value 可以是任何引用类型的数据,会封装到HashMap$Node 对象中
3. Map 中的 key 不允许重复,原因和HashSet 一样,前面分析过源码.
-
Map 中的 value 可以重复
-
Map 的key 可以为 null, value 也可以为null ,注意 key 为null,
只能有一个,value 为null ,可以多个 -
常用String类作为Map的 key
-
key 和 value 之间存在单向一对一关系,即通过指定的 key 总能找到对应的 value
@SuppressWarnings({"all"})
public class Map_ {
public static void main(String[] args) {
Map map = new HashMap();
map.put("no1", "韩顺平");//k-v
map.put("no2", "张无忌");//k-v
map.put("no1", "张三丰");//当有相同的k , 就等价于替换.
map.put("no3", "张三丰");//k-v
map.put(null, null); //k-v
map.put(null, "abc"); //等价替换
map.put("no4", null); //k-v
map.put("no5", null); //k-v
map.put(1, "赵敏");//k-v
map.put(new Object(), "金毛狮王");//k-v
// 通过get 方法,传入 key ,会返回对应的value
System.out.println(map.get("no2"));//张无忌
System.out.println("map=" + map);
}
}
张无忌
map={no2=张无忌, null=abc, no1=张三丰, 1=赵敏, no4=null, java.lang.Object@1eb44e46=金毛狮王, no3=张三丰, no5=null}
Map接口源码讲解
@SuppressWarnings({"all"})
public class MapSource_ {
public static void main(String[] args) {
Map map = new HashMap();
map.put("no1", "韩顺平");//k-v
map.put("no2", "张无忌");//k-v
map.put(new Car(), new Person());//k-v
Set set = map.entrySet();
System.out.println(set.getClass());// HashMap$EntrySet
for (Object obj : set) {
Map.Entry entry = (Map.Entry) obj;
System.out.println(entry.getKey() + "-" + entry.getValue() );
}
Set set1 = map.keySet();
System.out.println(set1.getClass());
Collection values = map.values();
System.out.println(values.getClass());
}
}
class Car {
}
class Person{
}
- k-v 最后是 HashMap$Node node = newNode(hash, key, value, null),Node是内部类
-
k-v 为了方便程序员的遍历,还会 创建 EntrySet 集合 ,该集合存放的元素的类型 Entry, 而一个Entry对象就有k,v 。相当于EntrySet<Entry<K,V>>
-
Set set = map.entrySet(); System.out.println(set.getClass());// HashMap$EntrySet
-
entrySet 中, 定义的类型是 Map.Entry ,但是实际上存放的还是 HashMap$Node,因为node类型实现了Entry;
- 当把 HashMap$Node 对象 存放到 entrySet 就方便我们的遍历, 因为 Map.Entry类 提供了重要方法K getKey(); V getValue();
for (Object obj : set) { System.out.println(obj.getClass()); //HashMap$Node
//为了从 HashMap$Node 取出k-v
//1. 先做一个向下转型
Map.Entry entry = (Map.Entry) obj;
System.out.println(entry.getKey() + "-" + entry.getValue() );
}
总结:首先HashMap里面的Note类型节点的引用会先转为Entry类型(因为node实现了entry)然后这个entry类型结点会放到EntrySet里面,EntrySet里面的key和Value值分别以set和collection形式存储,当然存储的也是引用。
我们可以更加直观的看到node->Entry的指向关系。
我们可以更直观的看到EntrySet里面的key和Value值分别以set和collection形式存储(为了能够单独拿出来)
Set set1 = map.keySet();
System.out.println(set1.getClass());
Collection values = map.values();
System.out.println(values.getClass());
KeySet继承AbstractSet,Values是继承AbstractSet的
我们对下面这张图片有了更清晰的认识
Map的常用方法
Map map = new HashMap();
map.put("邓超", new Book("", 100));//OK
map.put("邓超", "孙俪");//替换-> 一会分析源码
map.put("王宝强", "马蓉");//OK
map.put("宋喆", "马蓉");//OK
map.put("刘令博", null);//OK
map.put(null, "刘亦菲");//OK
map.put("鹿晗", "关晓彤");//OK
map.put("hsp", "hsp的老婆");
System.out.println("map=" + map);
// remove:根据键删除映射关系
map.remove(null);
System.out.println("map=" + map);
// get:根据键获取值
Object val = map.get("鹿晗");
System.out.println("val=" + val);
// size:获取元素个数
System.out.println("k-v=" + map.size());
// isEmpty:判断个数是否为0
System.out.println(map.isEmpty());//F
// clear:清除k-v
//map.clear();
System.out.println("map=" + map);
// containsKey:查找键是否存在
System.out.println("结果=" + map.containsKey("hsp"));//T
}
}
class Book {
private String name;
private int num;
public Book(String name, int num) {
this.name = name;
this.num = num;
}
}
输出如下:
Map接口三种途径的遍历方法
@SuppressWarnings({"all"})
public class MapFor {
public static void main(String[] args) {
Map map = new HashMap();
map.put("邓超", "孙俪");
map.put("王宝强", "马蓉");
map.put("宋喆", "马蓉");
map.put("刘令博", null);
map.put(null, "刘亦菲");
map.put("鹿晗", "关晓彤");
//第一组: 先取出 所有的Key , 通过Key 取出对应的Value
Set keyset = map.keySet();
//(1) 增强for
System.out.println("-----第一种方式-------");
for (Object key : keyset) {
System.out.println(key + "-" + map.get(key));
}
//(2) 迭代器
System.out.println("----第二种方式--------");
Iterator iterator = keyset.iterator();
while (iterator.hasNext()) {
Object key = iterator.next();
System.out.println(key + "-" + map.get(key));
}
//第二组: 把所有的values取出
Collection values = map.values();
//这里可以使用所有的Collections使用的遍历方法
//(1) 增强for
System.out.println("---取出所有的value 增强for----");
for (Object value : values) {
System.out.println(value);
}
//(2) 迭代器
System.out.println("---取出所有的value 迭代器----");
Iterator iterator2 = values.iterator();
while (iterator2.hasNext()) {
Object value = iterator2.next();
System.out.println(value);
}
//第三组: 通过EntrySet 来获取 k-v
Set entrySet = map.entrySet();// EntrySet<Map.Entry<K,V>>
//(1) 增强for
System.out.println("----使用EntrySet 的 for增强(第3种)----");
for (Object entry : entrySet) {
//向下转型 将entry 转成 Map.Entry
Map.Entry m = (Map.Entry) entry;
System.out.println(m.getKey() + "-" + m.getValue());
}
//(2) 迭代器
System.out.println("----使用EntrySet 的 迭代器(第4种)----");
Iterator iterator3 = entrySet.iterator();
while (iterator3.hasNext()) {
Object entry = iterator3.next();
//System.out.println(next.getClass());//HashMap$Node -实现-> Map.Entry (getKey,getValue)
//向下转型 Map.Entry
Map.Entry m = (Map.Entry) entry;
System.out.println(m.getKey() + "-" + m.getValue());
}
}
}
注:所有继承Collection接口的类都可以使用iterator迭代器。
输出结果如下:
-----第一种方式-------
邓超-孙俪
宋喆-马蓉
刘令博-null
null-刘亦菲
王宝强-马蓉
鹿晗-关晓彤
----第二种方式--------
邓超-孙俪
宋喆-马蓉
刘令博-null
null-刘亦菲
王宝强-马蓉
鹿晗-关晓彤
—取出所有的value 增强for----
孙俪
马蓉
null
刘亦菲
马蓉
关晓彤
—取出所有的value 迭代器----
孙俪
马蓉
null
刘亦菲
马蓉
关晓彤
----使用EntrySet 的 for增强(第3种)----
邓超-孙俪
宋喆-马蓉
刘令博-null
null-刘亦菲
王宝强-马蓉
鹿晗-关晓彤
----使用EntrySet 的 迭代器(第4种)----
邓超-孙俪
宋喆-马蓉
刘令博-null
null-刘亦菲
王宝强-马蓉
鹿晗-关晓彤进程已结束,退出代码为 0
Map接口练习题
@SuppressWarnings({"all"})
public class MapExercise {
public static void main(String[] args) {
Employee xiaoming = new Employee("小明", 50000, "123456");
Employee xiaohong = new Employee("小红", 10000, "123457");
Employee xiaofang = new Employee("小芳", 3000, "123458");
Map hashMap = new HashMap();
hashMap.put(xiaoming.getId(), xiaoming);
hashMap.put(xiaohong.getId(), xiaohong);
hashMap.put(xiaofang.getId(), xiaofang);
Set set = hashMap.keySet();
for (Object object : set) {
Employee employee = (Employee) hashMap.get(object);
if (employee.getSalary() > 18000)
System.out.println(object + "-" + hashMap.get(object));
}
// Iterator iterator = set.iterator();
// while (iterator.hasNext()) {
// Object next = iterator.next();
// System.out.println(next + "-" + hashMap.get(next));
// }
Set set1 = hashMap.entrySet();
// for (Object object : set1) {
// Map.Entry object1 = (Map.Entry) object;
// System.out.println(object1.getKey() + "-" + object1.getValue());
// }
Iterator iterator1 = set1.iterator();
while (iterator1.hasNext()) {
Object next = iterator1.next();
Map.Entry next1 = (Map.Entry) next;
Employee value = (Employee) next1.getValue();
if (value.getSalary() > 18000)
System.out.println(next1.getKey() + "-" + next1.getValue());
}
}
}
class Employee {
private String name;
private double salary;
private String id;
public Employee(String name, double salary, String id) {
this.name = name;
this.salary = salary;
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", salary=" + salary +
", id='" + id + '\'' +
'}';
}
}
HashMap小结
-
Map接口的常用实现类:HashMap、Hashtable和Properties。
-
HashMap是Map接口使用频率最高的实现类。
-
HashMap 是以key-val对的方式来存储数据(HashMap$Node类型)
-
key 不能重复,但是值可以重复,允许使用null键和null值。如果添加相同的key,则会覆盖原来的key-val,等同于修改.(key不会替换,val会替换)
替换源码部分:
-
与HashSet一样,不保证映射的顺序,因为底层是以hash表的方式来存储的.(jdk8的hashMap底层 数组+链表+红黑树)
-
HashMap没有实现同步,因此是线程不安全的,方法没有做同步互斥的操作,没有synchronized
hMap小结
-
Map接口的常用实现类:HashMap、Hashtable和Properties。
-
HashMap是Map接口使用频率最高的实现类。
-
HashMap 是以key-val对的方式来存储数据(HashMap$Node类型)
-
key 不能重复,但是值可以重复,允许使用null键和null值。如果添加相同的key,则会覆盖原来的key-val,等同于修改.(key不会替换,val会替换)
替换源码部分:
[外链图片转存中…(img-bRXakQ9z-1723519058095)]
-
与HashSet一样,不保证映射的顺序,因为底层是以hash表的方式来存储的.(jdk8的hashMap底层 数组+链表+红黑树)
-
HashMap没有实现同步,因此是线程不安全的,方法没有做同步互斥的操作,没有synchronized
持续更新。。。
标签:24,Map,map,08,System,println,null,out From: https://blog.csdn.net/2301_79291071/article/details/141159337