Map集合
1、Map集合的遍历方式
1.1、遍历Map集合需要用到的方法
public Set keySet() 将Map所有的ksy封装到一个Set的集合
public V get(Object key) 根据key(键)获取Map中对应的value(值)
public Set<Map.Entry<K,V>> entrySet() 获取所有的键值对对象集合
public Collection values() 将Map中所有的value封装到一个Collection体系的集合
1.2、代码实现
public class MapTest {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("1","小明");
map.put("2","小廖");
map.put("3","小邹");
/*第一种遍历:键找值方式遍历Map集合
* 使用的方法:public V get(Object key) 根据key(键)获取Map中对应的value(值)
* public Set<K> keySet() 将Map所有的key封装到一个Set的集合
* */
Set<String> set1 = map.keySet();
for (String key : set1) {
String value=map.get(key);
System.out.println("员工编号:"+key+"员工姓名:"+value);
}
System.out.println("-------------------------------------------");
/*第二种遍历:获取键值对对象集合,迭代器遍历集合获取键值对
使用方法:public Set<Map.Entry<K,V>> entrySet(): 获取所有的键值对对象集合
* */
Set<Map.Entry<String, String>> set2 = map.entrySet();
/*获取迭代器对象*/
Iterator<Map.Entry<String, String>> iterator = set2.iterator();
while(iterator.hasNext()){
Map.Entry<String, String> entry = iterator.next();
String key = entry.getKey();
String value = entry.getValue();
System.out.println("员工编号:"+key+"员工姓名:"+value);
}
System.out.println("---------------------------------------------");
/*第三种遍历:获取键值对对象集合,增强for遍历集合获取键和值
使用方法 public Set<Map.Entry<K,V>> entrySet() :获取所有的键值对对象集合
* */
Set<Map.Entry<String, String>> set3 = map.entrySet();
for (Map.Entry<String, String> entry : set3) {
String key = entry.getKey();
String value = entry.getValue();
System.out.println("员工编号:"+key+"员工姓名:"+value);
}
System.out.println("----------------------------------------------");
/*
* 第四种遍历:Map集合中的value方法拿到所有的值
* 使用的方法:public Collection<V> values() 将Map中所有的value封装到一个Collection体系的集合
*
* */
Collection<String> values = map.values();
for (String value : values) {
System.out.println("员工姓名:"+value);
}
}
}
1.3、Map的实现类有哪些
1、TreeMap:使用二叉树进行存储key-value
2、HashTable:版本比较低,线程安全,效率低,不能使用null作为key和value,对应的HashMap线程不安全,但是效率高
3、LinkedHashMap:底层使用链表来维护key-value的次序
4、Properties:也是以key-value作为键值对存储信息
2、HashMap的特性
2.1、Map集合的特性
- Map是一个双列集合,将键映射到值的对象
- Map集合的数据结构,只针对键有效,跟值没有关系
- 一个映射不能包括重复的键,每个键最多只能映射到一个值
2.2、HahsMap集合的数据结构是什么
哈希表结构:数组+链表
- 通过哈希表结构配合对象的hashCode和equals方法就可以保证键的唯一性
- jdk8版本之后,在哈希表结构中引入了红黑树,当一个数组元素下挂载的链表长度为8时就会从链表转成红黑树,从而提高了查询的效率
- 注意:今后键的位置如果存储的是自定义类型,建议不要忘记重写hashCode和equals方法
2.3、HashMap保存元素的步骤
- 调用对象的hashCode()方法,获得要存储元素的哈希值
- 将哈希值与表的长度(即数组的长度16)进行求余运算得到一个整数值,该值就是新元素要存放的位置
- 如果索引值对应的位置上没有存储任何元素,就可以确保这个键是唯一的,则直接将元素存储到该位置上
- 如果索引值对应的位置上已经存储了元素,则执行第三步 - 遍历该位置上的所有旧元素,依次比较每个旧元素的哈希值和新元素的哈希值是否相同
- 如果有哈希值相同的旧元素,则执行第4步
- 如果没有哈希值相同的旧元素,则执行第五步 - 比较新元素和旧元素的地址是否相同
- 如果地址相同则用新的元素替换旧的元素,停止比较
- 如果地址值不同,则新元素调用equalse方法与旧元素比较内容是否相同
- 如果返回true,用新的元素替换旧的元素,停止比较
- 如果返回false,则继续比较下一个旧元素 - 说明没有重复,则将新元素放到该位置上并让新元素记住之前该位置的元素
源码if(e.hash==hash&&(k=e.key)==key||(key!=null&&key.equals(k)))) 意思就是先判断hash是否相同如果相同就判断地址值是否相同如果也是相同就为true如果不同就使用重写后的equals对比内容(和上面的五步一样)
2.4、 HashMap扩容机制
其底层HashMap实例的默认初始容量(数组)是16,加载因子是0.75就是所在哈希表中的数组如果满了0.75就会扩容比如:16(数组长度)*0.75加载因子等于12,如果存储已经大于12就会扩容就会用数组的长度乘以2,产生一个新的数组,然后还有一个叫再哈希机制,比如原本扩容前的长度是16就是2122(哈希值)%16=1,而新数组长度是32就会变成2122(哈希值) 2122%32=2就会放进不同的下标的数组,也可以通过不同参数的构造方法指导初始化容量和加载因子
3、HashMap key只能唯一的特性的应用场景
3.1、需求记录商品卖出了多少件
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
public class MapDemo2 {
public static void main(String[] args) {
Goods g1 = new Goods("泡面", 5);
Goods g2 = new Goods("火腿肠", 2.5);
Goods g3 = new Goods("茶叶蛋", 1.5);
Goods g4 = new Goods("泡面", 5);
Goods[] goodsArr=new Goods[4];
goodsArr[0]=g1;
goodsArr[1]=g2;
goodsArr[2]=g3;
goodsArr[3]=g4;
Map<Goods, Integer> goodsMap = new HashMap<>();
for (Goods g : goodsArr) {
//判断在集合中g这个商品是否存在如果不存在就说明是第一次出现
if(!goodsMap.containsKey(g)){
//第一次出现保存元素并记录1
goodsMap.put(g,1);
}else{
//如果不是第一次出现就更新该元素的value,每一次出现都+1记录该商品的出现次数
goodsMap.put(g,goodsMap.get(g)+1);
}
}
System.out.println(goodsMap);
}
}
class Goods{
private String brand;
private double price;
public Goods(String brand, double price) {
this.brand = brand;
this.price = price;
}
public Goods() {
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Goods goods = (Goods) o;
return Double.compare(goods.price, price) == 0 &&
Objects.equals(brand, goods.brand);
}
@Override
public int hashCode() {
return Objects.hash(brand, price);
}
@Override
public String toString() {
return "Goods{" +
"brand='" + brand + '\'' +
", price=" + price +
'}';
}
}