Map接口实现类的特点(JDK8)
1)Map与Collection并列存在。用于保存具有映射关系的数据Key-Value;
2)Map中的key和value可以是任何引用类型的数据,会封装到HashMap$Node对象中;
3)Map中的key不允许重复,其原因和HashSet相同;
4)Map中的value可以重复;
5)Map的key可以为null,value也可以为null,key为null只能有一个,value为null可以有多个;
6)常用String类作为Map的key;
7)key和value之间存在单向一对一关系,即通过指定的key总能找到对应的value。
8)Map存放数据的key-value,一对k-v是存放在一个Node中的,因为Node实现了Entry接口,事实上在底层将Node节点的内容封装成entry对象(将k-v进行组合),然后把entry对象放进EntrySet的集合中(将Key里面的对象封装到Set集合中,提供keySet()方法获取集合对象(存储了所有添加元素key的信息),将Value里面的对象封装到Collection集合中,提供values()方法获取集合对象(存储了所有添加元素value的信息),遍历时可以单独取出添加元素的key的值和value的值,EntrySet集合中存储的对象地址(hash值)是与Node 节点存储内容(对象的地址)是一样的。
测试代码
package com.pero.map_;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* @author Pero
* @version 1.0
*/
@SuppressWarnings({"all"})
public class Map_ {
public static void main(String[] args) {
//Map接口实现类的特点
//1.用于保存有映射关系的数据Key-Value(双列元素)
//2.Map中的key和value可以是任何引用类型的数据,会封装到HashMap$Node对象中;
//3.Map中的key不允许重复,新值替换旧值;
//4.Map中的value可以重复;
//5.Map的key可以为null,value也可以为null,key为null只能有一个,value为null可以有多个;
//6.常用String类作为Map的key;
//7.key和value之间存在单向一对一关系,即通过指定的key总能找到对应的value。
Map map = new HashMap();
map.put("number01","pero");
map.put("number02","jake");
map.put(new Car(),new Person());
//1)k-v最后是HashMap$Node node = newNode(hash,key,value,null)
//2)k-v为了方便程序员遍历,还会创建EntrySet集合,该集合存放的元素类型是Entry
// 而一个Entry对象就包含有k-v,即transient Set<Map.Entry<K,V>> entrySet;
//3)entrySet中,定义的类型是Map.Entry,但是实际存放的是HashMap$Node
// 因为在HashMap类的内部定义了static class Node<K,V> implements Map.Entry<K,V>
//4)把HashMap$Node对象存放到entrySet中方便了我们的遍历,因为Map.Entry接口提供了
// K getKey() 和 V getValue() 方法
//set是一个Set集合的对象,里面存储的EntrySet集合的内容,[k=v,k=v,k=v...]
Set set = map.entrySet();
System.out.println(set.getClass()); //set的运行类型HashMap$EntrySet
for (Object objecct : set) {
System.out.println(objecct.getClass()); //entry的运行类型是HashMap$Node
//因为当前遍历的内容的编译类型是Object型,但是运行类型是HashMap$Node
//从HashMap$Node 中取出k-v,先做向下转型
Map.Entry entry = (Map.Entry) objecct;
//getKey()和getValue()方法是在HashMap$Node类中重写了,单独返回key值和value值
System.out.println(entry.getKey()+"-"+entry.getValue());
System.out.println(objecct);
}
System.out.println("====================================================");
//在table表(以数组+链表+红黑树的方式存储Node节点)中,
// 为了方便管理在底层将Node节点的内容封装成entry对象(将k-v进行组合),
// 然后把entry对象放进EntrySet的集合中
// (将Key里面的对象封装到Set集合中,提供keySet()方法获取集合对象(存储了所有添加元素key的信息))
// (将Value里面的对象封装到Collection集合中,提供values()方法获取集合对象(存储了所有添加元素value的信息))
// (遍历时可以单独取出添加元素的key的值和value的值)
// EntrySet集合中存储的对象地址(hash值)是与Node 节点存储内容(对象的地址)是一样的
Set set1 = map.keySet();
System.out.println(set1.getClass()); //HashMap$KeySet
for (Object o :set1) {
System.out.println(o);
}
Collection values = map.values();
System.out.println(values.getClass()); //HashMap$Values
for (Object o :values) {
System.out.println(o);
}
System.out.println("====================================================");
map.put("number01","smith"); //当有相同的k时,k对应的v替换原来的v
//当k不同时,在不同的k下,底层经过对k值的hash运算会分配不同的空间来存储,可以存储相同的v
map.put("number03","jake");
map.put(null,null);
map.put(null,"cba"); //到目前为止只有一个k为null,v的值null被"cba"取代
map.put("number04",null);
map.put("number05",null); //新的k-v,value为null,可以存储多个
//一般用String类作为Map的Key,但是其他任意类都可以作为Key
map.put(1,"lucy");
map.put(new Object(),"tom");
System.out.println(map.get("number03"));//根据k可以找到映射关系的v
//输出结果是无序的,key在底层存储时依旧是按照hash值经过运算后存储到对应的空间中
System.out.println(map);
}
}
class Car{
}
class Person{
}
Map接口常用方法
package com.pero.set_;
import java.util.HashMap;
import java.util.Map;
/**
* Map接口常用方法
*
* @author Pero
* @version 1.0
*/
public class MapMethod {
public static void main(String[] args) {
Map map = new HashMap();
map.put("n1",new Book("小王子",68));
map.put("n2","n3");
map.put("jake","lucy");
map.put("smith","lucy");
map.put(null,"king");
map.put("tom",null);
map.put("n2","n4"); //替换
System.out.println(map);
//remove()方法
map.remove(null); //remove(key);删除key和value
map.remove("tom",null); //remove(key,value);删除key和value
System.out.println(map);
//get()方法
Object n2 = map.get("n2"); //get(key);返回一个对象value
System.out.println(n2);
//size()方法
System.out.println("k-v="+map.size()); //返回k-v串的个数
//isEmpty()方法
System.out.println(map.isEmpty()); //判断map集合中元素个数是否为0
//clear()方法,清空k-v,map集合变成空集合
//map.clear();
//System.out.println(map.isEmpty());
//containsKey()方法和containValue()方法分别查找k或者v是否存在,如果存在返回true,如果不存在返回false
System.out.println(map.containsKey("n1"));
System.out.println(map.containsValue("lucy"));
}
}
class Book{
private String name;
private double price;
public Book(String name, double price) {
this.name = name;
this.price = price;
}
}
Map接口遍历方法
package com.pero.set_;
import java.util.*;
/**
* Map接口遍历的方法
*
* @author Pero
* @version 1.0
*/
@SuppressWarnings({"all"})
public class MapFor {
public static void main(String[] args) {
Map map = new HashMap();
map.put("n1", 1);
map.put("n2", 2);
map.put("n3", 3);
map.put("n4", 4);
map.put("n5", 5);
map.put("n6", 6);
map.put("n7", 7);
//【第一组】通过keySet()方法先取出所有的key,然后通过key取出对应的value
Set set = map.keySet(); //set是存储map中所有key的Set集合
//第一种:增强for
for (Object key : set) {
//通过获取建key来获取与其映射的value
System.out.println(key + "=" + map.get(key));
}
//第二种:迭代器
Iterator iterator = set.iterator();
while (iterator.hasNext()) {
Object key = iterator.next();
System.out.println(key + "=" +map.get(key));
}
//【第二组】通过values()方法直接取出value
//第一种:增强for
Collection values = map.values(); //values是存储map中所有value的Collection集合
for (Object value :values) {
System.out.println(value);
}
//第二种:迭代器
Iterator iterator1 = values.iterator();
while (iterator1.hasNext()) {
Object value = iterator1.next();
System.out.println(value);
}
//【第三组】通过entrySet()方法取出k-v
Set set1 = map.entrySet(); //EntrySet<Map.Entry<K,V>>
//第一种:增强for
for (Object entry : set1) { //entry的编译类型是Object
//将entry 转成 Map.Entry
//System.out.println(entry.getClass()); //entry的运行类型是HashMap$Node
//向下转型
//HashMap$Node -实现-> Map.Entry(提供getKey()和getValue()方法来获取key和value)
// HashMap$Node类没有重写getKey()和getValue()方法,
// 但是实现了Map.Entry接口,向下转型成Map.Entry
// 则entryTure集合可以调用getKey()和getValue()方法
Map.Entry entryTure = (Map.Entry) entry;
System.out.println(entryTure);
System.out.println(entryTure.getKey()+"-"+entryTure.getValue());
}
//第二种:迭代器
Iterator iterator2 = set1.iterator();
while (iterator2.hasNext()) {
Object entry = iterator2.next();
Map.Entry entryTure = (Map.Entry) entry;
System.out.println(entryTure);
System.out.println(entryTure.getKey()+"-"+entryTure.getValue());
}
}
}
练习代码
package com.pero.set_;
import java.util.*;
/**
* 使用HashMap添加3个员工对象,要求:
* 键:员工id
* 值:员工对象
* 并遍历显示工资>180000的员工(遍历方式至少两种)
* 员工类:姓名,工资,员工id
*
* @author Pero
* @version 1.0
*/
@SuppressWarnings({"all"})
public class MapExercise {
public static void main(String[] args) {
HashMap hashMap = new HashMap();
EmployeeNew jake = new EmployeeNew("jake", 12000, 11010);
EmployeeNew lucy = new EmployeeNew("lucy", 19000, 11011);
EmployeeNew tom = new EmployeeNew("tom", 21000, 11012);
hashMap.put(jake.getId(), jake);
hashMap.put(lucy.getId(), lucy);
hashMap.put(tom.getId(), tom);
//途径
//hashMap.keySet()
//hashMap.values()
//hashMap.entrySet()
System.out.println("==========================取出values第一种遍历方式===========================");
//先取出values集合
Collection values = hashMap.values();
Iterator iterator = values.iterator();
while (iterator.hasNext()) {
//这里取出的对象是employee
Object employee = iterator.next();
//将employee对象转成其运行类型,可以使用其运行类型内的方法(多态)
EmployeeNew people = (EmployeeNew) employee;
if (people.getSalary()>18000){
System.out.println(people);
}
}
System.out.println("==========================取出values第二种遍历方式===========================");
for (Object employee :values) {
//这里取出的对象是employee
EmployeeNew people = (EmployeeNew) employee;
if (people.getSalary()>18000){
System.out.println(people);
}
}
System.out.println("==========================取出keySet集合第一种遍历方式===========================");
//先取出keySet集合
Set set1 = hashMap.keySet();
Iterator iterator1 = set1.iterator();
while (iterator1.hasNext()) {
//这里取出的对象是id
Object id = iterator1.next();
//通过id(K键)取出employee
Object employee = hashMap.get(id);
EmployeeNew people = (EmployeeNew) employee;
if (people.getSalary()>18000){
System.out.println(people);
}
}
System.out.println("==========================取出keySet集合第二种遍历方式===========================");
for (Object key :set1) {
Object employee = hashMap.get(key);
EmployeeNew people = (EmployeeNew) employee;
if (people.getSalary()>18000){
System.out.println(people);
}
}
System.out.println("==========================取出EntrySet集合第一种遍历方式===========================");
//取出EntrySet集合
Set set = hashMap.entrySet();
for (Object id_employee : set) {
//转型成Map.Entry接口下的类对象,可以使用getkey和getvalue方法
Map.Entry employeeTrue = (Map.Entry) id_employee;
//取出对象employee
Object employee = employeeTrue.getValue();
EmployeeNew people = (EmployeeNew) employee;
if (people.getSalary()>18000){
System.out.println(people);
}
}
System.out.println("==========================取出EntrySet集合第二种遍历方式===========================");
Iterator iterator2 = set.iterator();
while (iterator2.hasNext()) {
Object id_employee = iterator2.next();
Map.Entry employeeTrue = (Map.Entry) id_employee;
Object employee = employeeTrue.getValue();
EmployeeNew people = (EmployeeNew) employee;
if (people.getSalary()>18000){
System.out.println(people);
}
}
}
}
class EmployeeNew {
private String name;
private double salary;
private int id;
public EmployeeNew(String name, double salary, int 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 int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public String toString() {
return '{' + name + '\'' + ", salary=" + salary + ", id=" + id + '}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
EmployeeNew that = (EmployeeNew) o;
return Double.compare(that.salary, salary) == 0 && id == that.id && Objects.equals(name, that.name);
}
@Override
public int hashCode() {
return Objects.hash(name, salary, id);
}
}