点击查看:java集合(List、Set、Map)博客目录
9.1 、 概述
9.2 、 Map常用子类
-
将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。
-
java.util.Map< k , v >集合
-
Map集合的特点:
- Map集合是一个双列集合,一个元素包含两个值(1个key,一个value)
- Map集合中的元素,key和value的数据类型可以相同,也可以不同
- Map集合中的元素,key是不允许重复的,value是可以重复的
- Map集合中的元素,key和value是一 一对应。
-
java.util.HashMap<k,v>集合 implement Map<k,v>接口
-
HashMap< k , v >集合的特点:
- HashMap集合底层是哈希表:查询速度特别快
- JDK1.8 之前:数组+单向链表
- JDK1.8 之后:数组+单向链表/红黑树(链表的长度超过8)
- hashMap 集合是一个无序的集合,存储元素和取出元素的顺序有可能不一致。
- HashMap集合底层是哈希表:查询速度特别快
-
java.util.LinkedHashMap< k , v >集合 extends HashMap< k , v >集合。
-
LinkedListMap的特点:
- LinkedHashMap集合底层是 哈希表+链表
- LinkedHashMap集合是一个有序集合,存储元素和取出元素的顺序是一致的。
9.3 、 Map接口中的常用方法
import java.util.*;
public class Main{
public static void main(String args[]){
show01();
show02();
show03();
show04();
}
/**public V put(K key ,V value); 把指定的键与指定的值添加到Map集合中。
* 返回值V :
* 存储键值对的时候,key不重复,返回值V是null
* 存储键值对的时候,key重复,会使新的value替换map中重复的value
* ,返回被替换的(旧的)value值 */
public static void show01(){
// 创建Map集合对象,多态
Map<String,String> map = new HashMap<>();
Stirng v1 = map.put("123","abc");
System.out.println("v1 : "+v1);
//输出: "v1 : null"
Stirng v2 = map.put("123","def");
System.out.println("v2 : "+v2);
//输出: "v2 : abc"
System.out.println(map);
// 输出:"{123=def}"
map.put("11","aa");
map.put("22","bb");
map.put("33","cc");
System.out.println(map);
// 输出: "{11=aa,22=bb,123=def,33=cc}"
}
/** public V remove(Object key) ; 把指定的键 所对应的的键值对元素
* 在Map集合中删除,返回被删除的元素的值。
* 返回值 V:
* key存在,v返回被删除的值。
* key不存在,v返回null。 */
public static void show02(){
Map<String,Integer> map = new HashMap<>();
map.put("袁睿昕",180);
map.put("闫津铭",181);
map.put("李天一",179);
Integer v1 = map.remove("袁睿昕");
System.out.println(v1);
// 输出:180
System.out.println(map);
// 输出: {闫津铭=181,李天一=179}
Integer v2 = map.remove("袁牛牛"); // 若把Integer改为int,为自动拆箱,为null时报空指针异常。
System.out.println(v2);
// 输出:null
}
/** public V get(Object key) 根据指定的键,在Map集合中获取对应的值
* 返回值:
* key存在,返回对应的value值。
* key不存在返回null; */
public static void show03(){
Map<String,Integer> map = new HashMap<>();
map.put("袁睿昕",180);
map.put("闫津铭",181);
map.put("李天一",179);
Integer v1 = map.get("袁睿昕");
System.out.println(v1);
// 输出: 180
Integer v2 = map.get("袁牛牛");
System.out.println(v2);
// 输出:null
}
/** public boolean containsKey(Object key);
根据指定的键,在Map集合中获取对应的值。
返回值: 包含返回 true;
不包含,返回 false; */
public static void show04(){
Map<String,Integer> map = new HashMap<>();
map.put("袁睿昕",180);
map.put("闫津铭",181);
map.put("李天一",179);
boolean b1 = map.containsKey("袁睿昕");
System.out.println(b1);
// 输出: true
boolean b2 = map.containsKey("袁牛牛");
System.out.println(v1);
// 输出:false
}
}
9.4 、 遍历Map集合-键找值方式
键找值方式:即通过元素中的键,获取键所对应的的值。
分析步骤:
1. 获取Map中所有的键,由于键是唯一的,所以返回一个Set集合存储所有的键。方法提示:keySet();
2. 遍历键的Set集合,得到每一个键
3. 根据键,获取键所对应的值。方法提示: get(K key)
代码演示:
public class MapDemo{
public static void main(Stirng [] args){
//创建Map集合对象
HashMap<Stirng,Sitrng> map = new HashMap<Stirng,String>();
//添加元素到集合
map.put("袁睿昕","乌龟");
map.put("闫津铭","老狗");
map.put("李天一","砖家");
// 获取所有的键 获取键集
Set<String> keyset = map.keySet();
// 遍历键集 得到每一个键,for-each遍历
for(String key : keyset){
// 通过get(key) ,获取value
String value = map.get(key);
System.out.println(key+"="+value);
}
for(String key : map.KeySet()){
// 通过get(key) ,获取value
System.out.println(key+"="+map.get(key));
}
// Iterator 遍历
Iterator<Stirng> it = keyset.iterator();
while(it.hasNext()){
String key = it.next();
String value = map.get(key);
System.out.println(key+"="+value);
}
}
}
9.5 、 遍历Map集合-Entery键值对
Entry键值对遍历Map集合实现步骤:
1. 使用Map集合的方法entrySet(),把Map集合中多个Entry对象取出来,存储到一个Set集合中
2. 使用Set集合,获取每一个Entry对象
3. 使用Entry对象中的方法getkey()和getvalue()获取键与值。
public class MapDemo{
public static void main(Stirng [] args){
//创建Map集合对象
HashMap<Stirng,Sitrng> map = new HashMap<Stirng,String>();
//添加元素到集合
map.put("袁睿昕","乌龟");
map.put("闫津铭","老狗");
map.put("李天一","砖家");
// 1.使用Map集合的方法entrySet(),把Map集合中多个Entry对象取出来,存储到一个Set集合中
Set<Map.Entry<String,String>> set = map.entrySet();
// 2. 使用Set集合,获取每一个Entry对象
Iterator<Map.Entry<Stirng,Stirng>> it = set.itrator();
while(it.hasNext){
Map.Entry<Stirng,Stirng> entry = it,next();
// 3. 使用Entry对象中的方法getkey()和getvalue()获取键与值。
String key = entry.getkey();
String value = entry.value();
System.out.println(key+"="+value);
}
// 使用for-each遍历
for( Map.Entry<Stirng,Stirng> entry : set){
String key = entry.getkey();
String value = entry.value();
System.out.println(key+"="+value);
}
}
}
9.6 、HashMap存储自定义类型键值
Map集合保证Key唯一:
作为key的元素,必须重写hashCode和equals方法,保证key唯一。
import java.util.*;
class Person{
private String name;
private int age;
public Person(){
}
public Person(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;
}
@Override
public String toString(){
return "person{"+"name='"+name+'\''+",age="+age+'}';
}
}
/** HashMap存储自定义类型键值
* key: Stirng类型
* String类重写hashCode方法和equals方法,可以保证key唯一
* value:person类型
* value可以重复(同名同年龄的人视为同一人)
*/
public class HashMapSavePerson{
public static void main(String args[]){
show01();
show02();
}
public static void show01(){
// 创建hashMap集合
HashMap<String,Person> map = new HashMap<>();
// 往集合中添加元素
map.put("济南",new Person("袁睿昕",20));
map.put("北京",new Person("张三",21));
map.put("上海",new Person("李四",22));
map.put("广州",new Person("王五",23));
map.put("济南",new Person("闫津铭",19));
// 使用keySet加增强For遍历Map集合
Set<String> set = map.keySet();
for(String key:set){
Person value = map.get(key);
System.out.println(key + "-->"+value);
}
输出: 北京-->Person{name='张三',age='21'}
上海-->Person{name='李四',age='22'}
广州-->Person{name='王五',age='23'}
济南-->Person{name='闫津铭',age='19'}
}
/** HashMap存储自定义类型键值
* key: Person类型
* Person类重写hashCode方法和equals方法,可以保证key唯一
* value:Stirng类型
* 可以重复
*/
public static void show02(){
// 创建hashMap集合
HashMap<Person,String> map = new HashMap<>();
// 往集合中添加元素
map.put(new Person("秦始皇",500),"中国");
map.put(new Person("普京",70),"俄罗斯");
map.put(new Person("女王",75),"英国");
map.put(new Person("秦始皇",500),"秦国");
// 使用EntrySet和增强for
Set<Map.Entry<Person,String>> set = map.entrySet();
for(Map.Entry<Person,String> entry : set){
Person key = entry.getKey();
String value = entry.getValue();
System.out.ptrontln(key+"-->"+value);
}
输出:person{name='女王',age=75}-->英国
person{name='秦始皇',age=500}-->中国
person{name='普京',age=70}-->俄罗斯
person{name='秦始皇',age=500}-->秦国
}
}
若在Person类中 重写equals和hashCode方法,则,key为Person时 也不能重复
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
输出:
person{name='普京',age=70}-->俄罗斯
person{name='女王',age=75}-->英国
person{name='秦始皇',age=500}-->秦国
9.7 、LinkedHashMap
我们知道HashMap保证成对元素唯一,并且查询速度很快,可是成对元素存放进去是没有顺序的,LinkedHashMap保证有序。
在HashMap下面有一个子类LinkedHashMap,它是链表和哈希表组合的一个数据存储结构。
import java.util.*;
public class Main{
public static void main(String args[]){
LinkedHashMap <Stirng,String>map = new LinkedHashMap<String,String>();
map.put("袁睿昕","乌龟");
map.put("闫津铭","老狗");
map.put("李天一","砖家");
Set<Map.Entry<String,String>> set = map.entrySet();
for( Map.Entry<Stirng,Stirng> entry : set){
String key = entry.getkey();
String value = entry.value();
System.out.println(key+" "+value);
}
}
}
输出结果:
袁睿昕 乌龟
闫津铭 老狗
李天一 砖家
9.8 、HashTable
java.util.HashTable<k,v> 集合 implement Map<k,v>接口
hashtable : 底层也是一个hash表,是一个线程安全的集合,是单线程集合,速度慢。
HashMap 是一个线程不安全的集合,是多线程集合速度快
HashMap 集合(之前学的集合):可以存储null值,null键 hashTable集合,不能存储null值,null键。
hashtable和vector集合一样,在jdk1.2之后被更先进的集合(HashMap)取代了。
HashTable的子类properties依然活跃在历史的舞台
propertiesj集合是唯一一个和IO流相结合的集合
public static void main(Stirng[] args){
public static void main(String args[]){
HashMap<String,String> map = new HashMap<>();
map.put(null,"a");
map.put("b",null);
map.put(null,null);
System.out.println(map);
}
}
输出:{null=a,b=null,null=null}