1 Map
- 将键映射到值的对象。Map不能包含重复的键; 每个键可以映射到最多一个值,一个值可以被多个键所映射
构造方式:
public interface Map<K,V>
1.1.Map接口的基本使用
-
-
put(K Key,V value) 将指定的值与该映射中指定的键相关联(可选操作)
-
-
-
V
get(Object key)
返回到指定键所映射的值,或null
如果此映射包含该键的映射。
-
-
-
boolean
containsKey(Object key)
如果此映射包含指定键的映射,则返回true
。boolean
containsValue(Object value)
如果此地图将一个或多个键映射到指定的值,则返回true
。
-
-
-
Set<Map.Entry<K,V>>
entrySet()
返回此地图中包含的映射的Set
视图。
-
-
-
default V
replace(K key, V value)
只有当目标映射到某个值时,才能替换指定键的条目。
-
-
-
int
size()
返回此地图中键值映射的数量。Collection<V>
values()
返回此地图中包含的值的Collection
视图。
-
代码示例:
public class MapDemo1 {
public static void main(String[] args) {
//创建Map集合
Map<String ,String > map = new HashMap<>();
//存储键值对
map.put("lanqiao001","张昌昌");//lanqiao001是键,张昌昌是是值
map.put("lanqiao002","王国栋");
map.put("lanqiao003","曲睿");
//判断是否包含某一个键
boolean b = map.containsKey("lanqiao001");//contains是包含的意思
System.out.println(b);
// 获取map中键值对的个数
System.out.println(map.size());
// 获取所有的键集
Set<String> keySet = map.keySet();
System.out.println("--------------键集----------------");
for(String str : keySet){
System.out.println(str);
}
//获取所有的值集
Collection<String> values = map.values();
System.out.println("---------------值集--------------");
for(String str : values){
System.out.println(str);
}
//输出集合中的元素
System.out.println(map);
}
}
1.2Map集合的遍历方式
遍历方式一:
public static void main(String[] args) {
//创建Map集合
Map<String ,String > map = new HashMap<>();
//存储键值对
map.put("lanqiao001","张昌昌");
map.put("lanqiao002","王国栋");
map.put("lanqiao003","曲睿");
//获取键集
Set<String> keySet = map.keySet();
for(String key :keySet){
//根据键获取值
String value = map.get(key);
System.out.println(key+"---"+value);
}
}
运行结果
遍历方式二:
public static void main(String[] args) {
//创建Map集合
Map<String ,String > map = new HashMap<>();
//存储键值对
map.put("lanqiao001","张昌昌");
map.put("lanqiao002","王国栋");
map.put("lanqiao003","曲睿");
//获取键值对集合
Set<Map.Entry<String,String>> entrySet = map.entrySet();
for(Map.Entry<String,String> entry : entrySet){
//entry代表一对键值对 分别获取键和值
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key +"---" + value);
}
}
运行结果
1.3 HashMap(非常常用)
HashMap是Map接口使用频率最高的实现类
允许使用null键和null值 ,null只能有一个 与hashSet一样 不保证映射的顺序
所有的key构成的集合是set集合 是无序 不可以重复 如果key是一个自定义对象 那么此时类必须重写hashcode和equals方法
所有的value构成的集合是Coollection 无序的 是可以重复的
一个key和一个value构成一个entry
所有的entry构成的集合是Set 无序的 是不可重复的
HashMap中判断key是否唯一的标准和Hash判断元素是否唯一的方式是一样。
1.4 HashMap的存储结构
HashMap是基于Hash表实现的
jdk7及以前的版本:HashMap是数组 +链表的结构
jdk8及以后的版本 HashMap 数组 + 链表 + 红黑树实现的
HashMap中重要的常量:
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // 表示Map的默认容量是2的4次方 16
/**
* The maximum capacity, used if a higher value is implicitly specified
* by either of the constructors with arguments.
* MUST be a power of two <= 1<<30.
*/
static final int MAXIMUM_CAPACITY = 1 << 30;//最大容量 2的30次方
/**
* The load factor used when none specified in constructor.
*/
static final float DEFAULT_LOAD_FACTOR = 0.75f;// 默认加载因子 0.75
/**
* The bin count threshold for using a tree rather than list for a
* bin. Bins are converted to trees when adding an element to a
* bin with at least this many nodes. The value must be greater
* than 2 and should be at least 8 to mesh with assumptions in
* tree removal about conversion back to plain bins upon
* shrinkage.
*/
static final int TREEIFY_THRESHOLD = 8;//链表转换为红黑树的最大长度
static final int UNTREEIFY_THRESHOLD = 6;// 红黑树的节点数<=6 则转化为链表
Map中的键和值 都可以是任意类型 可以使jdk提供的类型 也可以是自定义类型
public static void main(String[] args) {
//创建Map集合
Map<Student, String> map = new HashMap<>();
Student stu1 = new Student("张三",18);
Student stu2 = new Student("李四",21);
Student stu3 = new Student("王五",20);
Student stu4 = new Student("赵六",22);
System.out.println(stu1.hashCode());//此处是为了验证stu的哈希码是否相同
System.out.println(stu2.hashCode());//此处输出时一定要重写Student类
System.out.println(stu3.hashCode());
// 以学生对象作为key 使用String作为值
map.put(stu1,"北京");
map.put(stu2,"郑州");
map.put(stu3,"天津");
map.put(stu4,"南京");
Set<Map.Entry<Student,String>> entrySet = map.entrySet();
Iterator<Map.Entry<Student,String>> iter = entrySet.iterator();
while(iter.hasNext()){
Map.Entry<Student,String> entry = iter.next();
Student key = entry.getKey();
String value = entry.getValue();
System.out.println(key+"---"+value);
}
System.out.println("---------------------");
Set<Student> keySet= map.keySet();
for(Student key : keySet){
String value = map.get(key);
System.out.println(key+"---"+value);
}
}
运行结果
使用自定义类作为键的时候 必须重写hashCode和Equeals方法
例子: ArrayList中 存储HahshMap 并遍历
public class MapDemo2 {
public static void main(String[] args) {
List<Map<String,String>> list = new ArrayList<>();
//创建Map
Map<String,String> map1 = new HashMap<>();
map1.put("郭靖","黄蓉");
map1.put("杨过","小龙女");
list.add(map1);
Map<String ,String> map2=new HashMap<>();
map2.put("孙策","大乔");
map2.put("周瑜","小乔");
list.add(map2);
for(Map<String,String> map : list){
Set<Map.Entry<String,String>> entrySet = map.entrySet();
for(Map.Entry<String,String> entry : entrySet){
System.out.println(entry.getKey()+"----"+entry.getValue());
}
}
}
}
运行结果
1.5 HashTable
HashMap
类大致相当于Hashtable
,除了它是不同步的,并允许null
HashTable : 是同步的 不允许null
1.6 TreeMap
基于红黑树实现 可以实现对元素的自然排序和定制排序 次实现不是同步的
自然排序
public class Student implements Comparable<Student> {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = 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;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age && Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
@Override
public int compareTo(Student stu) {
//比较规则: 按照年龄排序 年龄相同则按照姓名排序
int ageRes = this.getAge() - stu.getAge();
int nameRes = this.getName().compareTo(stu.getName());
return ageRes == 0 ?nameRes:ageRes;
}
}
public static void main(String[] args) {
Student stu1 = new Student("张三",23);
Student stu2 = new Student("李四",20);
Student stu3 = new Student("王五",18);
Student stu4 = new Student("赵六",22);
Map<Student,String> map = new TreeMap<>();
map.put(stu1,"北京");
map.put(stu2,"郑州");
map.put(stu3,"天津");
map.put(stu4,"南京");
Set<Student> keySet= map.keySet();
for(Student key : keySet){
String value = map.get(key);
System.out.println(key+"---"+value);
}
}
对于存入TreeMap中的键 如果是自定义类型 则必须实现Comparable并实现compareTo方法
定制排序
public class MapDemo3 {
public static void main(String[] args) {
Student stu1 = new Student("张三",23);
Student stu2 = new Student("李四",20);
Student stu3 = new Student("王五",18);
Student stu4 = new Student("赵六",22);
Map<Student,String> map = new TreeMap<>(new Comparator<Student>() {
@Override
public int compare(Student stu1, Student stu2) {
//比较规则: 按照年龄排序 年龄相同则按照姓名排序
int ageRes = stu1.getAge() - stu2.getAge();
int nameRes = stu1.getName().compareTo(stu2.getName());
return ageRes == 0 ?nameRes:ageRes;
}
});
map.put(stu1,"北京");
map.put(stu2,"郑州");
map.put(stu3,"天津");
map.put(stu4,"南京");
Set<Student> keySet= map.keySet();
for(Student key : keySet){
String value = map.get(key);
System.out.println(key+"---"+value);
}
}
}
需要在创建TreeMap对象的时候 传入一个比较器对象