JavaEE学习日志持续更新----> 必看!JavaEE学习路线(文章总汇)
Java学习日志(七)
Map集合
java.util.Map<k,v>接口:
Map集合和HashMap集合的特点
Map集合的特点:
- Map集合是一个双列集合,一个元素由两个值组成(key,value)
- Map集合中key是不允许重复的,value可以重复
- Map集合中key的数据类型和value的数据类型可以相同,也可以不同
- Map集合中key和value是一一对应的
HashMap集合:
java.util.HashMap<k,v>集合 implements Map<k,v>接口
HashMap集合的特点:
- HashMap底层使用的是哈希表结构
jdk1.8之前:数组+单向链表
jdk1.8之后:数组+单向链表/数组+红黑树 - 是一个无序的集合,存储的元素和取出的元素顺序有可能不一致
Map集合常用方法
public V put(K key, V value)
把指定的键与指定的值添加到Map集合中。
public V remove(Object key)
:把指定的键所对应的键值对元素在Map集合中删除,返回 被删除元素的值。
public V get(Object key)
根据指定的键,在Map集合中获取对应的值。
public boolean containKey(Object key)
判断该集合中是否有此键。
boolean containsValue(Object value)
如果此映射将一个或多个键映射到指定值,则返回 true 。
代码演示:
示例1:V put(K key, V value)
将指定的值与此映射中的指定键相关联(可选操作)。
key不重复,v返回null
可以重复,会使用新的value替换之前的value,返回被替换的value。
private static void show01() {
//创建Map集合对象
Map<String,String> map = new HashMap<>();
//使用put方法往Map集合中添加元素
String v1 = map.put("杨过", "小龙女");
System.out.println("v1:"+v1);//v1:null
String v2 = map.put("郭靖", "黄蓉");
System.out.println("v2:"+v2);//v2:null
String v3 = map.put("尹志平", "小龙女");
System.out.println("v3:"+v3);//v3:null
String v4 = map.put("杨过", "大雕");
System.out.println("v4:"+v4);//v4:小龙女
System.out.println(map);//{杨过=大雕, 尹志平=小龙女, 郭靖=黄蓉}
}
示例2:public V remove(Object key)
根据指定的key,删除对应的键值对
如果key存在,返回删除的value
如果key不存在,返回null
private static void show02() {
Map<String,Integer> map = new HashMap<>();
map.put("a",1);
map.put("b",2);
map.put("d",4);
map.put("c",3);
System.out.println(map);//{a=1, b=2, c=3, d=4} 自然排序
Integer v1 = map.remove("c");//可用int接收
System.out.println("v1:"+v1);//v1:3
Integer v2 = map.remove("w");//不可用int接收,空指针异常
System.out.println("v2:"+v2);//v2:null
System.out.println(map);//{a=1, b=2, d=4}
}
示例3: public V get(Object key)
根据指定的键,在Map集合中获取对应的值。
key不存在,返回null
private static void show03() {
Map<String,Integer> map = new HashMap<>();
map.put("a",1);
map.put("b",2);
map.put("d",4);
map.put("c",3);
Integer v1 = map.get("a");
System.out.println("v1:"+v1);//v1:1
Integer v2 = map.get("q");
System.out.println("v2:"+v2);//v2:null
}
示例4:public boolean containKey(Object key)
:判断该集合中是否有此键。
boolean containsValue(Object value)
如果此映射将一个或多个键映射到指定值,则返回 true 。
包含:返回true 不包含返回:false
private static void show04() {
Map<String,Integer> map = new HashMap<>();
map.put("a",1);
map.put("b",2);
map.put("d",4);
map.put("c",3);
boolean b1 = map.containsKey("d");
System.out.println("b1:"+b1);//b1:true
boolean b2 = map.containsKey("e");
System.out.println("b2:"+b2);//b2:false
System.out.println(map.containsValue(4));//true
System.out.println(map.containsValue(5));//false
}
Map集合的遍历方式
Map集合的遍历方式
- 通过键找值的方式
- 通过键值对的方式(使用Entry对象)
第一种:通过键找值的方式:
Map集合中的方法:
public Set<K> keySet()
获取Map集合中所有的键,存储到Set集合中。
实现步骤:
1.使用Map集合中的方法keySet,把所有的key取出来存储到一个Set集合中
2.遍历Set集合,获取Map集合的每一个key
3.使用Map集合中的方法get(key),通过key找到value
public class Demo02 {
public static void main(String[] args) {
HashMap<String,Double> map = new HashMap<>();
map.put("aaa",1.65);
map.put("bbb",1.68);
map.put("ccc",1.8);
map.put("ddd",1.9);
//1.使用Map集合中的方法keySet,把所有的key取出来存储到一个Set集合中
Set<String> set = map.keySet();
//2.遍历Set集合,获取Map集合的每一个key
Iterator<String> it = set.iterator();
//迭代器遍历
while(it.hasNext()){
String k = it.next();
Double value = map.get(k);
System.out.println(k+"="+value);
}
System.out.println("-----------");
//增强for遍历
for (String k : set) {// for(String Key : map.keySet())
Double value = map.get(k);
System.out.println(k+"="+value);
}
}
}
第二种:通过键值对的方式(使用Entry对象):
Entry对象:是Map集合的内部接口,当Map集合对象创建的时候,就会自动创建Entry对象,用来记录键与值的映射关系(每一个键值对)
Map集合中的方法:
public Set<Map.Entry<K,V>> entrySet()
获取到Map集合中所有的键值对对象的集合(Set集合)。
Entry对象的方法:
K getKey()
返回与此条目对应的键。
V getValue()
返回与此条目对应的值。
实现步骤:
- 使用Map集合中的方法entrySet,把所有的Entry对象取出来,存储到一个Set集合中
- 遍历set集合,获取每一个Entry对象
- 使用Entry对象中的方法getKey和getValue方法获取键与值
public class Demo03 {
public static void main(String[] args) {
HashMap<String,Double> map = new HashMap<>();
map.put("aaa",1.65);
map.put("bbb",1.68);
map.put("ccc",1.8);
map.put("ddd",1.9);
//1.使用Map集合中的方法entrySet,把所有的Entry对象取出来,存储到一个Set集合中
Set<Map.Entry<String, Double>> set = map.entrySet();
//2.遍历set集合,获取每一个Entry对象
//使用迭代器遍历
Iterator<Map.Entry<String, Double>> it = set.iterator();
while(it.hasNext()){
Map.Entry<String, Double> entry = it.next();
//3.使用Entry对象中的方法getKey和getValue方法获取键与值
String key = entry.getKey();
Double value = entry.getValue();
System.out.println(key+"="+value);
}
System.out.println("-----------------");
//增强for遍历
for (Map.Entry<String, Double> entry : set) {
String key = entry.getKey();
Double value = entry.getValue();
System.out.println(key+"="+value);
}
}
}
LinkedHashMap集合
java.util.LinkedHashMap<k,v>集合 extends HashMap<k,v>集合
Map接口的哈希表和链表实现,具有可预测的迭代顺序。
LinkedHashMap集合特点
- LinkedHashMap集合底层是哈希表+单向链表 —>双向链表
- LinkedHashMap集合里存储的元素是有序的
public class Demo04 {
public static void main(String[] args) {
HashMap<String,String> map = new HashMap<>();
map.put("aaa","111");
map.put("ccc","222");
map.put("ddd","333");
map.put("bbb","444");
map.put("aaa","555");
//key不允许重复,value可以重复,无序的集合
System.out.println(map);//{aaa=555, ccc=222, bbb=444, ddd=333}
LinkedHashMap<String,String> map2 = new LinkedHashMap<>();
map2.put("aaa","111");
map2.put("ccc","222");
map2.put("ddd","333");
map2.put("bbb","444");
map2.put("aaa","555");
//key不允许重复,value可以重复,有序的集合
System.out.println(map2);//{aaa=555, ccc=222, ddd=333, bbb=444}
}
}
Hashtable集合
java.util.Hashtable<k,v>集合 implements Map<k,v>
Hashtable是一个最早期的双列集合,在jdk1.0版本就存在了
底层:哈希表
Hashtable与HashMap的区别(面试题):
- Hashtable是一个线程安全的集合,是一个单线程的集合,效率低
HashMap是一个线程不安全的集合,是一个多线程的集合,效率高 - Hashtable不允许存储null键null值,会抛出异常—>没有对null进行处理
HashMap允许存储null键null值—>对null进行了处理,把null变为"null"
Hashtable效率低,所以被HashMap取代,但Hashtable子类Properties依旧在用(唯一跟IO流结合的集合)
public class Demo05 {
public static void main(String[] args) {
HashMap<String,String> map = new HashMap<>();
map.put(null,"a");//map.put("null","a"); null会变成"null"
map.put("b",null);
map.put(null,null);
System.out.println(map);//{null=null, b=null}
Hashtable<String,String> table = new Hashtable<>();
table.put(null,"a");//NullPointerException 没有对null进行处理
table.put("b",null);//NullPointerException
table.put(null,null);//NullPointerException
}
}