Map接口
1.Map接口
Map接口存储键值映射的数据
1.1HashMap
HashMap:无序,键和值可以为null,键不能重复,线程不安全
数据结构
hashMap数据结构
数据结构
HashMap数据结构
回顾我们之前学过的两种数据结构:
ArrayList基于数组的,因为有下标,所以查询、修改快,增删慢
LinkedList基于链表的,因为没有下标,所以查询、修改慢,增删快
以上两个数据结构是刚好互补的,如果能将两个数据结构结合在一起,完美~
这只是理想状态,实际情况不会这么完美,另外结合在一起比较浪费空间
HashMap就是将两种数据结构结合在了一起
JDK7 数组 + 单向链表
JDK8 数组 + 单向链表 + 红黑树
HashMap数据的存放过程:
HashMap中一个元素是一个Node(节点),一个节点包含四个部分:Key值,value值,根据key计算出来的hash值,下一个元素的引用next
当我们调用put方法往HashMap中存储数据,会先根据key的hash值找到当前元素应该存放在数组中的位置,
如果此位置没有元素,则直接存放,
如果此位置有元素,那么向下延伸为单向链表
如果链表的长度大于8并且元素的总个数超过64 那么单向链表转换为红黑树
在我们使用过程中,我们会删除元素,如果链表的长度小于6,将红黑树再次转换为链表
HashMap中两个重要的数值:
16 表示数组的长度为初始长度16
0.75 表示数组的使用率达到75% 就扩容 扩容两倍 resize() 方法
常用方法
package com.qfedu.test6;
import java.util.HashMap;
/**
* Map接口
* HashMap常用方法
* @author WHD
*
*/
public class Test1 {
public static void main(String[] args) {
HashMap<String,String> map = new HashMap<String,String>();
map.put("CN", "中国");
map.put("US", "美国");
map.put("JP", "小日本");
map.put("KR", "棒子");
map.put("ID","阿三");
System.out.println(map.size());
System.out.println(map.remove("JP")); // 删除
System.out.println(map.size()); // 长度
map.put("CN", "中华人民共和国"); // 存放
System.out.println(map.get("CN")); // 获取
map.replace("US", "美国佬");
System.out.println(map.get("US"));
map.clear();
System.out.println( map.isEmpty());
}
}
遍历
package com.qfedu.test7;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
/**
* HashMap 遍历方式
* 1.获取所有的键
* 2.获取所有的值
* 3.获取所有的键的迭代器
* 4.获取所有的值的迭代器
* 5.获取所有的元素Entry数组
* 6.获取所有的元素的迭代器
* @author WHD
*
*/
public class Test1 {
public static void main(String[] args) {
HashMap<String,String> map = new HashMap<String,String>();
map.put("CN", "中国");
map.put("US", "美国");
map.put("JP", "小日本");
map.put("KR", "棒子");
map.put("ID","阿三");
// 1.获取所有的键
Set<String> keySet = map.keySet();
for(String key : keySet) {
System.out.println(key + "\t" + map.get(key) );
}
System.out.println("=====================================");
// 2. 获取所有的值
Collection<String> values = map.values();
for(String v : values) {
System.out.println(v);
}
System.out.println("=====================================");
// 3.获取键的迭代器
Iterator<String> iterator = map.keySet().iterator();
while(iterator.hasNext()) {
String key = iterator.next();
System.out.println(key + "\t" + map.get(key));
}
System.out.println("=====================================");
// 4.获取所有的值的迭代器
Iterator<String> iterator2 = map.values().iterator();
while(iterator2.hasNext()) {
System.out.println(iterator2.next());
}
System.out.println("=====================================");
// 5.获取所有的键值对组合
Set<Entry<String, String>> entrySet = map.entrySet();
for(Entry<String,String> entry : entrySet) {
System.out.println(entry.getKey() + entry.getValue());
}
System.out.println("=====================================");
// 6.所有键值对组合的迭代器
Iterator<Entry<String, String>> iterator3 = map.entrySet().iterator();
while(iterator3.hasNext()) {
Entry<String, String> next = iterator3.next();
System.out.println(next.getKey() + next.getValue());
}
}
}
2.2Hashtable
Hashtable JDK1.0 提供与HashMap相同的API 并且不允许null作为键或者值 线程安全
初始长度为11 负载因子0.75 扩容 rehash() 两倍+1
HashMap与Hashtable的区别?
HashMap线程不安全 Hashtable线程安全
HashMap允许null键和值 Hashtable不允许
HashMapJDK1.2 Hashtable JDK1.0
package com.qfedu.test2;
import java.util.Collection;
import java.util.Hashtable;
import java.util.Map.Entry;
import java.util.Set;
/**
* Hashtable JDK1.0 提供与HashMap相同的API 并且不允许null作为键或者值 线程安全
* 初始长度为11 负载因子0.75 扩容 rehash() 两倍+1
* @author WHD
*
*/
public class TestHashtable {
public static void main(String[] args) {
Hashtable<Integer,String> table = new Hashtable<Integer,String>();
table.put(1, "a");
table.put(2, "b");
table.put(3, "c");
table.put(4, "d");
// table.put(null, null);
System.out.println(table.remove(1));
System.out.println(table.size());
table.replace(2, "hello");
System.out.println(table.get(2));
//table.clear();
System.out.println(table.isEmpty());
// 遍历方式与HashMap一致
Set<Integer> keySet = table.keySet();
for (Integer key : keySet) {
System.out.println(table.get(key) + "\t" + key);
}
Collection<String> values = table.values();
for (String v : values) {
System.out.println(v);
}
Set<Entry<Integer, String>> entrySet = table.entrySet();
for (Entry<Integer, String> entry : entrySet) {
System.out.println(entry.getKey() + entry.getValue());
}
}
}
2.3LinkedHashMap
LinkedHashMap是基于双向链表的有序的Map集合,顺序为插入顺序
package com.qfedu.test3;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map.Entry;
import java.util.Set;
/**
* LinkedHashMap是有序的Map集合 顺序为插入顺序
* @author WHD
*
*/
public class TestLinkedHashMap {
public static void main(String[] args) {
LinkedHashMap<String,String> map = new LinkedHashMap<String,String>();
map.put("a", "A");
map.put("b", "B");
map.put("c", "C");
map.put("d", "D");
System.out.println(map.remove("a"));
map.replace("b", "hello");
System.out.println(map.get("b"));
System.out.println(map.size());
// map.clear();
System.out.println(map.isEmpty());
// 遍历方式与之前Map集合一致
Set<String> keySet = map.keySet();
for (String key : keySet) {
System.out.println(key + "---" + map.get(key));
}
Collection<String> values = map.values();
for (String v : values) {
System.out.println(v);
}
Set<Entry<String, String>> entrySet = map.entrySet();
for (Entry<String, String> entry : entrySet) {
System.out.println(entry.getKey() + "===" + entry.getValue());
}
}
}
2.3TreeMap
基于树的Map集合,有序是按照键的比较顺序
使用自定义的类型作为Map键,必须实现Comparable接口 重写compareTo方法
指定比较规则 否则运行报错 不能添加数据
package com.qfedu.test3;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
/**
* 基于树的Map集合 有序是按照键的比较顺序
* 使用自定义的类型作为TreeMap键 必须实现Comparable接口 重写compareTo方法
* 指定比较规则 否则运行报错 不能添加数据
* @author WHD
*
*/
public class TestTreeMap {
public static void main(String[] args) {
TreeMap<Integer,String> map = new TreeMap<Integer,String>();
map.put(1, "abc");
map.put(20, "hello");
map.put(17, "hhh");
map.put(5, "666");
// 其他方法 增删改查 是否为空 与之前map集合一致
// 遍历方式与之前也一致
Set<Integer> keySet = map.keySet();
for (Integer key : keySet) {
System.out.println(map.get(key) + "===" + key);
}
System.out.println("============================================");
TreeMap<Student,String> map1 = new TreeMap<Student,String>();
Student stu1 = new Student("赵四", 25);
Student stu2 = new Student("广坤", 21);
Student stu3 = new Student("大拿", 22);
map1.put(stu1, "abc");
map1.put(stu2, "abc");
map1.put(stu3, "abc");
Set<Entry<Student, String>> entrySet = map1.entrySet();
for (Entry<Student, String> entry : entrySet) {
System.out.println(entry.getKey());
System.out.println(entry.getValue());
}
}
}
package com.qfedu.test3;
public class Student implements Comparable<Student>{
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
@Override
public int compareTo(Student stu) {
if(this.getAge() > stu.getAge()) {
return 1;
}else if(this.getAge() < stu.getAge() ) {
return -1;
}
return 0;
}
}
2.4Properties
Properties类用于存放成对的字符串数据 实际开发中用于读取配置文件
所以此类不要使用从父类Hashtable继承来的put或者putAll方法
而应该使用setProperty()
package com.qfedu.test6;
import java.util.Properties;
/**
* Properties类用于存放成对的字符串数据 实际开发中用于读取配置文件
* 所以此类不要使用从父类Hashtable继承来的put或者putAll方法
* 而应该使用setProperty()
* @author WHD
*
*/
public class TestProperties {
public static void main(String[] args) {
System.out.println(System.getProperty("java.version"));
System.getProperties().list(System.out);
Properties p = new Properties();
// p.put(1, "abc");
p.setProperty("a", "A");
p.setProperty("b", "B");
System.out.println(p.get("a"));
p.list(System.out);
}
}