希望各位能够留下你们美丽的赞和评论谢谢,或者有好的资源帮帮小编提升实力一起努力,奥里给!!
拒绝垃圾视频:超级好的视频,建议从头开始看:https://www.bilibili.com/video/BV16K4y1x7Gi?p=42
Map集合
集合
一、集合概念
概念:对象的容器,定义了对多个对象进行操作的常用方法。可实现数组的功能。
二、集合和数组的区别
(1)数组长度固定,集合长度不固定
(2)数组可以存储基本类型和引用类型,集合只能引用类型。
三、Map
Map体系结构图
Map父接口
- 特点:存储一对数据,无序、无下标,键不可重复,值可重复。
方法 | 功能 |
---|---|
void clear() | 清空 |
default V compute(K key, BiFunction<? super K,? super V,? extends V> remappingFunction) | 尝试计算指定键的映射及其当前映射的值(如果没有当前映射, null ) |
default V computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction) | 如果指定的键尚未与值相关联(或映射到 null ),则尝试使用给定的映射函数计算其值,并将其输入到此映射中,除非 null |
default V computeIfPresent(K key, BiFunction<? super K,? super V,? extends V> remappingFunction) | 如果指定的密钥的值存在且非空,则尝试计算给定密钥及其当前映射值的新映射 |
boolean containsKey(Object key | 如果此映射包含指定键的映射,则返回 true |
boolean containsValue(Object value) | 如果此地图将一个或多个键映射到指定的值,则返回 true |
Set<Map.Entry<K,V>> entrySet() | 返回此地图中包含的映射的Set视图 |
boolean equals(Object o) | 将指定的对象与此映射进行比较以获得相等性 |
default void forEach(BiConsumer<? super K,? super V> action) | 对此映射中的每个条目执行给定的操作,直到所有条目都被处理或操作引发异常 |
V get(Object key) | 返回到指定键所映射的值,或 null如果此映射包含该键的映射 |
default V getOrDefault(Object key, V defaultValue) | 返回到指定键所映射的值,或 defaultValue如果此映射包含该键的映射 |
int hashCode() | 返回此地图的哈希码值 |
boolean isEmpty() | 如果此地图不包含键值映射,则返回 true |
Set keySet() | 返回此地图中包含的键的Set视图 |
default V merge(K key, V value, BiFunction<? super V,? super V,? extends V> remappingFunction) | 如果指定的键尚未与值相关联或与null相关联,则将其与给定的非空值相关联 |
V put(K key, V value) | 将指定的值与该映射中的指定键相关联(可选操作) |
void putAll(Map<? extends K,? extends V> m) | 将指定地图的所有映射复制到此映射(可选操作) |
default V putIfAbsent(K key, V value) | 如果指定的键尚未与某个值相关联(或映射到 null )将其与给定值相关联并返回 null ,否则返回当前值 |
V remove(Object key) | 如果存在(从可选的操作),从该地图中删除一个键的映射 |
default boolean remove(Object key, Object value) | 仅当指定的密钥当前映射到指定的值时删除该条目 |
default V replace(K key, V value) | 只有当目标映射到某个值时,才能替换指定键的条目 |
default boolean replace(K key, V oldValue, V newValue) | 仅当当前映射到指定的值时,才能替换指定键的条目 |
default void replaceAll(BiFunction<? super K,? super V,? extends V> function) | 将每个条目的值替换为对该条目调用给定函数的结果,直到所有条目都被处理或该函数抛出异常 |
int size() | 返回此地图中键值映射的数量 |
Collection values() | 返回此地图中包含的值的Collection视图 |
Map接口的使用
重点是遍历有两种:
1.entrySet
2.keySet
两个都是返回set集合,keySet返回的是键的集合,entrySet返回的是键值的集合
所以从效率考虑entrySet更高。
图解KeySet和entrySet:
示例代码:
package cn.itcast.study;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* map接口的使用
* 特点:
* 1、存储键值对
* 2、键不能重复、值可以重复
* 3、无序
* @author 11218
*
*/
public class MapDemo1 {
public static void main(String[] args) {
//创建Map
Map<String,String> map = new HashMap<>();
//添加元素
map.put("cn", "中国");
map.put("uk", "英国");
map.put("usa", "美国");
map.put("cn", "zhongguo");//这个不会填加但是会修改键为cn的值
System.out.println("元素个数"+map.size());
System.out.println(map.toString());
//删除
// map.remove("usa");
// System.out.println("元素个数"+map.size());
//遍历(entrySet方法效率高于keySet方法)
System.out.println("===========keySet()=============");
Set<String> keyset = map.keySet();
for (String key : keyset) {
System.out.println(key+"-"+map.get(key));
}
System.out.println("=========使用entrySet()========");
//获得的set是Entry的元素,Entry是键值对映射的
Set<Map.Entry<String, String>> entries = map.entrySet();
for (Map.Entry<String, String> entry : entries) {
System.out.println(entry.getKey()+"========="+entry.getValue());
}
}
}
四、Map集合的实现类
4.1 HashMap(重点)
特点:线程不安全,运行效率快;允许使用null作为key或是value。
4.1.1 HashMap使用(去重和遍历简化)
重点:
1.去除键的重复
2.遍历的简化
示例代码:
Worker重写hashCode和equals
package cn.itcast.study;
public class Worker {
private String name;
private int workNo;
public Worker() {
// TODO Auto-generated constructor stub
}
public Worker(String name, int workNo) {
super();
this.name = name;
this.workNo = workNo;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getWorkNo() {
return workNo;
}
public void setWorkNo(int workNo) {
this.workNo = workNo;
}
@Override
public String toString() {
return "Worker [name=" + name + ", workNo=" + workNo + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + workNo;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Worker other = (Worker) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (workNo != other.workNo)
return false;
return true;
}
}
HashMapDemo1测试去重和简化遍历
package cn.itcast.study;
import java.util.HashMap;
import java.util.Map;
/**
* HashMap集合的使用
* 存储结构:哈希表(数组+链表+红黑树)
* 用key的hashCode和equals作为重复
* @author 11218
*
*/
public class HashMapDemo1 {
public static void main(String[] args) {
//创建集合
HashMap<Worker,String> workers = new HashMap<>();
//添加元素
Worker w1 = new Worker("xcg",1);
Worker w2 = new Worker("xh",2);
Worker w3 = new Worker("xf",9);
workers.put(w1,"北京");
workers.put(w2,"上海");
workers.put(w3,"南京");
// workers.put(new Worker("xcg",1), "可以加");
System.out.println("元素个数:"+workers.size());
System.out.println(workers.toString());
//遍历
System.out.println("======keySet=======");
for (Worker key : workers.keySet()) {
System.out.println(key.toString()+"======="+workers.get(key));
}
// Set<Worker> s = workers.keySet();
// for (Object object : s) {
// Worker w = (Worker) object;
// System.out.println(w.getName()+"编号是"+w.getWorkNo()+"家在"+workers.get(w));
// }
System.out.println("======entrySet=======");
for (Map.Entry<Worker, String> entry : workers.entrySet()) {
System.out.println(entry.getKey().toString()+"========="+entry.getValue());
}
// Set<Map.Entry<Worker, String>> s1 = workers.entrySet();
// for (Entry<Worker, String> entry : s1) {
// System.out.println(entry.getKey().getName()+"编号是"+entry.getKey().getWorkNo()+"家在"+entry.getValue());
// }
//删除
// workers.remove(new Worker("xcg",1));
// System.out.println("元素个数"+workers.size());
//判断
System.out.println(workers.isEmpty());
System.out.println(workers.containsKey(new Worker("xcg",1)));
}
}
4.1.1 HashMap源码解读
属性 | 解释 |
---|---|
DEFAULT_INITIAL_CAPACITY | 最小容量16 |
MAXIMUM_CAPACITY | 最大容量2^30 |
DEFAULT_LOAD_FACTOR | 加载因素0.75(相当于到目前容量的75%就开始扩容) |
TREEIFY_THRESHOLD | 值为:8。这是在jdk1.8以后对其扩展的功能,简单讲就是当数组的长度大于64且链表的大于8的时候会对链表创建查询树 |
UNTREEIFY_THRESHOLD | 值:6。 这是数组长度小于6时就会改变查询树,没必要弄这种树 |
MIN_TREEIFY_CAPACITY | 数组长度最大值:64。这是大于64有效果 |
Node<K,Y> | 表示节点,其中有key和value |
next | 下一个节点 |
Node<K,V>[] table | 链表 |
size | 大小 |
方法 | 功能 |
---|---|
public HashMap() { this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted} | 初始化加载因子0.75并且此时的size为0,table为null (节省空间,到第一个元素加入再有大小) |
public V put(K key, V value) { return putVal(hash(key), key, value, false, true); } | 键值的添加 |
static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); } | 计算位置 |
final Node<K,V>[] resize() | 重新构建数组容量 |
final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) | 赋值,并会测算集合大小 来初始化和扩容 |
总结
(1)HashMap刚创建时,table是null,为了空间节省,当添加第一个元素时,table容量调整为16。
(2)当元素个数大于阈值(16*0.75=12)时,会进行扩容,扩容后大小为原来的2倍,目的是减少调整元素的个数。
(3)jdk1.8当每个链表长度大于8,并且数组元素个数大于64时,会调整为红黑树,目的提高执行效率。
(4)jdk1.8当链表长度小于6时,调整成链表。
(5)jdk1.8以前,链表时头插入,以后是为插入。
4.2 HashTable(了解)和Properties
HashTable:
特点:线程安全,运行效率慢;不允许null作为key或是value。
子类:Properties
Properties:
特点:HashTable子类,要求key和value都是String。通常用于配置文件的读取。
4.3 TreeMap
特点:实现了SortedMap接口(是Map的子接口),可以对key自动排序。
结构:红黑树(切记要实现Comaprable接口否则没有制定比较规则)
Student
package cn.itcast.study;
//学生信息
public class Student implements Comparable<Student> {
private String name;
private int age;
public Student() {
// TODO Auto-generated constructor stub
}
public Student(String name, int age) {
super();
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 obj) {
//判断是不是同一个对象
if(this==obj) {
return false;
}
//判断对象是不是为空
if(obj==null) {
return false;
}
//判断是不是Student类型
if(obj instanceof Student) {
Student s= (Student)obj;
//比较属性
if(this.name.equals(s.getName()) && this.age==s.getAge())
return true;
}
//不满足条件返回false
return false;
}
@Override
public int compareTo(Student o) {
int n1 = this.name.compareTo(o.getName());
int n2 = this.age - o.getAge();
return n1==0?n2:n1;
}
}
TreeMapDemo1
package cn.itcast.study;
import java.util.Map;
import java.util.TreeMap;
/**
* TreeMap的使用
* 存储结构:红黑树
* @author 11218
*
*/
public class TreeMapDemo1 {
public static void main(String[] args) {
//创建集合
TreeMap<Student, String> treeMap = new TreeMap<Student, String>();
//添加元素
Student s1 = new Student("刘德华",20);
Student s2 = new Student("gcd",25);
Student s3 = new Student("wcw",21);
treeMap.put(s1, "中国");
treeMap.put(s2, "美国");
treeMap.put(s3, "英国");
treeMap.put(new Student("刘德华",20), "英国");
System.out.println("元素个数:"+treeMap.size());
System.out.println(treeMap.toString());
//删除
// treeMap.remove(s1);
// treeMap.remove(new Student("刘德华",20));
// System.out.println("元素个数:"+treeMap.size());
//遍历
System.out.println("=========keySet==========");
for (Student s : treeMap.keySet()) {
System.out.println(s.toString()+"====="+treeMap.get(s));
}
System.out.println("=========entryKey==========");
for (Map.Entry<Student, String> entry : treeMap.entrySet()) {
System.out.println(entry.getKey().toString()+"======"+entry.getValue());
}
//判断
System.out.println(treeMap.isEmpty());
System.out.println(treeMap.containsKey(new Student("刘德华",20)));
}
}