注意:
这里讲的是JDK8的Map接口特点
Map 与 Collection 并列存在。用于保存具有映射关系的数据: Key-Value
Map 中的 key 和 value 可以是任何引用类型的数据,会封装到 HashMap$Node 对象中
Map 中的 key 不允许重复,原因和 HashSet 一样,前面博文中分析过源码.
Map 中的 value 可以重复
Map 的 key 可以为 null , value 也可以为 null ,注意 key 为 null ,只能有一个,
value为null ,可以多个.
常用 String 类作为 Map 的 key
key 和 value 之间存在单向一对一关系,即通过指定的 key 总能找到对应的 value
package www.xz.map_;
import java.util.HashMap;
import java.util.Map;
/**
@author 许正
@version 1.0
*/
@SuppressWarnings({“all”})
public class Map_ {
public static void main(String[] args) {
//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
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);//等价于替换
map.put(null, “abc”);//k-v
map.put(“no4”, null);
map.put(“no5”, null);
map.put(1, “豪豪”);
map.put(new Object(), “秋山帅豪”);
//通过get() 方法,传入 key ,会返回相对应的 value
System.out.println(map.get("no3"));
System.out.println("map=" + map);
}
}
**8. Map存放数据的key-value示意图,一对k-v是放在一个HashMap$Node中的,
因为Node实现了Entry 接口,有些书上也说一对k-v就是一个Entry(如图) **
package www.xz.map_;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* @author 许正
* @version 1.0
*/
@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
//1. k-v最后是HashMap$Node node = newNode (hash, key, vaLue, nuLl)
//2. k-v为了方便程序员的遍历,还会创建EntrySet 集合,该集合存放的元素的类型Entry, 而一个Entry
// 对象就有k,v EntrySet> 即: transient Set
put:添加
remove:根据键删除映射关系
get:根据键获取值
size:获取元素个数
isEmpty:判断个数是否为0
clear:清除
containsKey:查找键是否存在
package www.xz.map_;
import java.util.HashMap;
import java.util.Map;
/**
@author 许正
@version 1.0
*/
@SuppressWarnings({“all”})
public class MapMethod {
public static void main(String[] args) {
//演示Map接口的常用方法
HashMap map = new HashMap();
map.put("邓超", new Book("", 100));
map.put("邓超", "孙丽");
map.put("王宝强", "马蓉");
map.put("宋喆", "马蓉");
map.put("秋山帅豪", null);
map.put(null, " 刘亦菲");
map.put("鹿晗", " 关晓彤");
System.out.println("map=" + map);
// 1) remove:根据键删除映射关系
map.remove(null);
System.out.println(“map” + map);
// 2) get:根据键获取值
Object o = map.get(“秋山帅豪”);
System.out.println(“帅豪对应的对象:” + o);
// 3) size:获取元素个数
System.out.println(map.size());
// 4) isEmpty:判断个数是否为0
System.out.println(map.isEmpty());
// 5) clear:清除
map.clear();
System.out.println(“map=” + map);
// 6) containsKey:查找键是否存在
System.out.println(map.containsKey(“秋山帅豪”));
}
}
class Book {
private String name;
private int num;
public Book(String name, int num) {
this.name = name;
this.num = num;
}
}
Map遍历的示意图(比List ,和Set复杂点,但是基本原理一样)
containsKey:查找键是否存在
keySet:获取所有的键
entrySet:获取所有关系k-v
values:获取所有的值
package www.xz.map_;
import java.util.*;
/**
@author 许正
@version 1.0
*/
@SuppressWarnings({“all”})
public class MapFor {
public static void main(String[] args) {
HashMap map = new HashMap();
map.put(“邓超”, new Book(“”, 100));
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 next = iterator.next();
System.out.println(next + "-" + map.get(next));
}
//第二组:把所有的Value 取出
Collection values = map.values();
//这里可以使用所有的ColLections使用的遍历方法
System.out.println("---取出所有的Value 增强for---");
for (Object value : values) {
System.out.println(value);
}
System.out.println("---取出所有的Value 迭代器---");
Iterator iterator2 = values.iterator();
while (iterator2.hasNext()) {
Object next = iterator2.next();
System.out.println(next);
}
//第三组:通过EntrySet 来获取k-v
Set entrySet = map.entrySet();
System.out.println("---使用EntrySet的 增强for(第三种)---");
for (Object o : entrySet) {
Map.Entry entry = (Map.Entry) o;
System.out.println(entry.getKey() + "-" + entry.getValue());
}
System.out.println("---使用EntrySet的 迭代器(第四种)---");
Iterator iterator3 = entrySet.iterator();
while (iterator3.hasNext()) {
Object next = iterator3.next();
Map.Entry next1 = (Map.Entry) next;
System.out.println(next1.getKey() + "-" + next1.getValue());
}
}
}
package www.xz.map_;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* @author 许正
* @version 1.0
*/
@SuppressWarnings({"all"})
public class MapExercise {
public static void main(String[] args) {
Map map = new HashMap();
Employee jack = new Employee("jack", 19000, 1);
Employee tom = new Employee("tom", 20000, 2);
Employee marry = new Employee("marry", 15000, 3);
map.put(jack.getId(), jack);
map.put(tom.getId(), tom);
map.put(marry.getId(), marry);
Set set = map.keySet();
System.out.println("遍历显示工资大于18000的员工:");
for (Object o : set) {
Object o1 = map.get(o);
Employee o11 = (Employee) o1;
if (o11.getSal() > 18000) {
System.out.println(o11);
}
}
//2. 使用EntrySet ->迭代器
System.out.println("使用EntrySet ->迭代器:");
Set set1 = map.entrySet();
Iterator iterator = set1.iterator();
while (iterator.hasNext()) {
Object next = iterator.next();
Map.Entry entry = (Map.Entry) next;
Employee employee = (Employee) entry.getValue();
if (employee.getSal()>18000){
// System.out.println(entry.getValue());
System.out.println(employee);
}
}
}
}
class Employee {
public String name;
private double sal;
private int id;
public Employee(String name, double sal, int id) {
this.name = name;
this.sal = sal;
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSal() {
return sal;
}
public void setSal(double sal) {
this.sal = sal;
}
public double getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + ''' +
", sal=" + sal +
", id=" + id +
'}';
}
}
扩容机制和[HashSet相同]
追一下源码!!!
package www.xz.map_;
import java.util.HashMap;
/**
* @author 许正
* @version 1.0
*/
@SuppressWarnings({"all"})
public class HashMapSource01 {
public static void main(String[] args) {
HashMap map = new HashMap();
map.put("java", 10);//ok
map.put("php", 10);//ok
map.put("java", 20);//替换value
System.out.println("map=" + map);
}
}
package www.xz.map_;
import java.util.HashMap;
import java.util.Objects;
/**
* @author 许正
* @version 1.0
*/
@SuppressWarnings({"all"})
public class HashMapSource02 {
public static void main(String[] args) {
HashMap map = new HashMap();
for (int i = 1; i <=12 ; i++) {
map.put(new A(i),"hello");
}
System.out.println(map);
}
}
class A{
private int num;
public A(int num) {
this.num = num;
}
@Override
public int hashCode() {
return 100;
}
@Override
public String toString() {
return "
A{" +
"num=" + num +
'}';
}
}
存放的元素是键值对:即K-V
hashtable的键和值都不能为null,否则会抛出NullPointerException
hashTable使用方法基本上和HashMap一样
hashTable是线程安全的,hashMap是线程不安全的
简单看下底层结构
//简单说明一下Hashtable的底层
//1.底层有数组Hashtable$Entry[] 初始化大小为11
//2.临界值threshold 8 = 11 * 0.75
//3.扩容:按照自己的扩容机制来进行即可。
//4.执行方法addEntry(hash, key, value, index); 添加K-V封装到Entry
//5.当if (count >=threshold)满足时,就进行扩容
//5.按照int newCapacity = (oldCapacity << 1) + 1;的大小扩容。
debug看一下table表是如何扩容的
package www.xz.map_;
import java.util.Hashtable;
/**
* @author 许正
* @version 1.0
*/
@SuppressWarnings({"all"})
public class HashTableExercise {
public static void main(String[] args) {
Hashtable hashtable = new Hashtable();
hashtable.put("john",100);
// hashtable.put(null,100);
// hashtable.put("john",null);
hashtable.put("lucy",100);
hashtable.put("lic",100);
hashtable.put("lic",80);
hashtable.put("hello1",1);
hashtable.put("hello2",1);
hashtable.put("hello3",1);
hashtable.put("hello4",1);
hashtable.put("hello5",1);
hashtable.put("hello6",1);
System.out.println(hashtable);
}
}
Properties类继承自Hashtable类并且实现了 Map接口,也是使用一种键值对的形
式来保存数据。
他的使用特点和Hashtable类似
Properties 还可以用于从xxx.properties文件中,加载数据到Properties类对象,
并进行读取和修改
说明:工作后xxx.properties 文件通常作为配置文件,这个知识点在IO流举例,有兴
趣可先看文章[点击跳转](https:/ /www.cnblogs.com/ xudong bupt/ p/3758136.html)
package www.xz.map_;
import java.util.Properties;
/**
@author 许正
@version 1.0
*/
@SuppressWarnings({“all”})
public class Properties_ {
public static void main(String[] args) {
Properties properties = new Properties();
//1. Properties 继承Hashtable
//2. 可以通过k-v存放数据,当然key和value不能为null
properties.put(“john”, 100);
properties.put(“lucy”, 100);
properties.put(“lic”, 100);
properties.put(“lic”, 88);//替换
//通过key 获取对应值
System.out.println(properties.get("lic"));
//删除
properties.remove("lic");
System.out.println(properties);
//修改(直接覆盖)
properties.put("john","jack");
System.out.println(properties);
//查找
System.out.println(properties.getProperty("john"));
}
}
在开发中,选择什么集合实现类,主要取决于业务操作特点,然后根据集合实现类特性进行
选择,分析如下:
package www.xz.map_;
import java.util.Comparator;
import java.util.TreeMap;
/**
* @author 许正
* @version 1.0
*/
@SuppressWarnings({"all"})
public class TreeMap_ {
public static void main(String[] args) {
// TreeMap treeMap = new TreeMap();
TreeMap treeMap = new TreeMap(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
//按照首字母倒序
// return ((String)o2).compareTo((String)o1);
//按照字符串长度
return ((String)o1).length()-((String)o2).length();
}
});
treeMap.put("jack", "杰克");
treeMap.put("tom", "汤姆");
treeMap.put("kristina", "克雷丝缇娜");
treeMap.put("smith", "史密斯");
System.out.println(treeMap);
}
}