Map接口是一种双列集合,它的每个元素都包含一个键对象Key和值对象Value,键和值对象之间存在一种对应关系,称为映射。Map中的映射关系是一对一的,一个键对象Key对应唯一一个值对象Value,其中键对象Key和值对象Value可以是任意数据类型,并且键对象Key不允许重复,这样在访问Map集合中的元素时,只要指定了Key,就能找到对应的Value。
HashMap集合是Map接口的一个实现类,它用于存储键值映射关系,该集合的键和值允许为空,但键不能重复,且集合中的元素是无序的。
TreeMap集合是Map接口的另一个实现类,在TreeMap内部是通过二叉树的原理来保证键的唯一性,这与TreeSet集合存储的原理一样,因此TreeMap中所有的键是按照某种顺序排列的。
Map接口还有一个实现类Hashtable,它和HashMap十分相似,其中一个主要区别在于Hashtable是线程安全的。Hashtable类有一个子类Properties。Properties主要用来存储字符串类型的键和值,在实际开发中,经常使用Properties集合类来存取应用的配置项。
方法声明 | 功能描述 |
---|---|
void put(Object key, Object value) | 向Map集合中添加指定键值映射的元素 |
int size() | 返回Map集合键值对映射的个数 |
Object get(Object key) | 返回指定键所映射的值,如果此映射不包含该键的映射关系,则返回null |
boolean containsKey(Object key) | 查看Map集合中是否存在指定的键对象key |
boolean containsValue(Object value) | 查看Map集合中是否存在指定的值对象value |
Object remove(Object key) | 删除并返回Map集合中指定键对象Key的键值映射元素 |
void clear() | 清空整个Map集合中的键值映射元素 |
Set keySet() | 以Set集合的形式返回Map集合中所有的键对象Key |
Collection values() | 以Collection集合的形式返回Map集合中所有的值对象Value |
Set |
将Map集合转换为存储元素类型为Map的Set集合 |
Object getOrDefault(Object key, Object defaultValue) | 返回Map集合指定键所映射的值,如果不存在则返回默认值defaultValue(JDK 8新方法) |
void forEach(BiConsumer action) | 通过传入一个函数式接口对Map集合元素进行遍历(JDK 8新方法) |
Object putIfAbsent(Object key, Object value) | 向Map集合中添加指定键值映射的元素,如果集合中已存在该键值映射元素,则不再添加而是返回已存在的值对象Value(JDK 8新方法) |
boolean remove(Object key, Object value) | 删除Map集合中键值映射同时匹配的元素(JDK 8新方法) |
boolean replace(Object key, Object value) | 将Map集合中指定键对象Key所映射的值修改为value(JDK 8新方法) |
HashMap集合是Map接口的一个实现类,它用于存储键值映射关系,该集合的键和值允许为空,但键不能重复,且集合中的元素是无序的。
HashMap底层是由哈希表结构组成的,其实就是“数组+链表”的组合体,数组是HashMap的主体结构,链表则主要是为了解决哈希值冲突而存在的分支结构。正因为这样特殊的存储结构,HashMap集合对于元素的增、删、改、查操作表现出的效率都比较高。
package net.hw.lesson23;
import java.util.HashMap;
/**
* 功能:创建与操作HashMap集合
* 作者:华卫
* 日期:2020年05月24日
*/
public class Example2301 {
public static void main(String[] args) {
// 创建城市哈希映射
HashMap<String, String> cities = new HashMap<>();
// 给集合添加键值对
cities.put("1", "北京");
cities.put("2", "上海");
cities.put("3", "广州");
cities.put("4", "深圳");
cities.put("5", "泸州");
// 输出整个集合
System.out.println("城市集合:" + cities);
// 查询(按键查询)
String key = "3";
boolean isFound = cities.containsKey(key);
if (isFound) {
System.out.println("键[" + key + "]包含在键集合里。");
} else {
System.out.println("键[" + key + "]不包含在键集合里。");
}
// 查询(按值查询)
String value = "广州";
isFound = cities.containsValue(value);
if (isFound) {
System.out.println("值[" + value + "]包含在值集合里。");
} else {
System.out.println("值[" + value + "]不包含在值集合里。");
}
// 按键取值
key = "3";
System.out.println(key + " : " + cities.get(key));
key = "6";
System.out.println(key + " : " + cities.get(key));
// 获取键集合
System.out.println("键集合:" + cities.keySet());
// 获取值集合
System.out.println("值集合:" + cities.values());
// 按键修改值
cities.put("5", "南京");
System.out.println("键为[5]的值修改为[南京]。");
System.out.println("城市集合:" + cities);
cities.replace("5", "泸州");
System.out.println("键为[5]的值修改为[泸州]。");
System.out.println("城市集合:" + cities);
// 按键值删除元素
key = "3";
boolean isDeleted = cities.remove(key, cities.get(key));
if (isDeleted) {
System.out.println("删除键[" + key + "]的元素后的集合:" + cities);
} else {
System.out.println("键[" + key + "]没有在键集合里。");
}
// 按键删除元素
key = "5";
value = cities.remove(key);
if (value != null) {
System.out.println("删除键[" + key + "]的元素后的集合:" + cities);
} else {
System.out.println("键[" + key + "]没有在键集合里。");
}
}
}
在程序开发中,经常需要取出Map中所有的键与值,那么如何遍历Map中所有的键值对呢?Map集合遍历的方式与单列集合Collection集合遍历的方式基本相同,主要有两种方式可以实现:(1)使用Iterator迭代器遍历集合;(2)使用JDK8的forEach(Consumer action)方法遍历集合。
使用keySet()方法,先将Map集合转换为Iterator接口对象,然后进行遍历。由于Map集合中元素是由键值对组成的,所以使用Iterator接口遍历Map集合时,会有两种将Map集合转换为Iterator接口对象再进行遍历的方法:keySet()方法和entrySet()方法。
需要先将Map集合中所有键对象转换为Set单列集合,接着将包含键对象的Set集合转换为Iterator接口对象,然后遍历Map集合中所有的键,然后根据键获取相应的值。
package net.hw.lesson23;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
/**
* 功能:利用keySet()方法遍历Map集合
* 作者:华卫
* 日期:2020年05月24日
*/
public class Example2302 {
public static void main(String[] args) {
// 创建HashMap对象
HashMap<String, String> cities = new HashMap<>();
// 向集合里添加键值对
cities.put("1", "北京");
cities.put("2", "上海");
cities.put("3", "广州");
cities.put("4", "深圳");
cities.put("5", "泸州");
// 输出整个集合
System.out.println("城市集合:" + cities);
// 获取键集合
Set<String> keySet = cities.keySet();
// 利用增强for循环遍历集合
System.out.println("利用增强for循环遍历集合:");
for (String key : keySet) {
String value = cities.get(key);
System.out.println(key + " : " + value);
}
// 利用迭代器遍历集合
System.out.println("利用迭代器遍历集合:");
// 获取键集合的迭代器
Iterator<String> it = keySet.iterator();
// 遍历迭代器
while (it.hasNext()) {
String key = it.next();
String value = cities.get(key);
System.out.println(key + " : " + value);
}
}
}
使用entrySet()方法,将原有Map集合中的键值对作为一个整体返回为Set集合,接着将包含键值对对象的Set集合转换为Iterator接口对象,然后获取集合中全部键值对映射关系,再从映射关系中取出键和值。
package net.hw.lesson23;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* 功能:利用entrySet()方法遍历Map集合
* 作者:华卫
* 日期:2020年05月24日
*/
public class Example2303 {
public static void main(String[] args) {
// 创建HashMap对象
HashMap<String, String> cities = new HashMap<>();
// 向集合里添加键值对
cities.put("1", "北京");
cities.put("2", "上海");
cities.put("3", "广州");
cities.put("4", "深圳");
cities.put("5", "泸州");
// 输出整个集合
System.out.println("城市集合:" + cities);
// 获取集合的entrySet
Set<Map.Entry<String, String>> entrySet = cities.entrySet();
// 利用增强for循环遍历集合
System.out.println("利用增强for循环遍历集合:");
for (Map.Entry<String, String> entry : entrySet) {
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key + " : " + value);
}
// 利用迭代器遍历集合
System.out.println("利用迭代器遍历集合:");
// 获取条目集合的迭代器
Iterator<Map.Entry<String, String>> it = entrySet.iterator();
// 遍历迭代器
while (it.hasNext()) {
Map.Entry<String, String> entry = it.next();
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key + " : " + value);
}
}
}
在JDK 8中,根据Lambda表达式特性新增了一个forEach(BiConsumer action)方法来遍历Map集合,该方法所需要的参数也是一个函数式接口,因此可以使用Lambda表达式的书写形式来进行集合遍历。
map.forEach((key, value) -> System.out.println(key + " : " + value));
package net.hw.lesson23;
import java.util.HashMap;
/**
* 功能:利用forEach()遍历集合
* 作者:华卫
* 日期:2020年05月24日
*/
public class Example2304 {
public static void main(String[] args) {
// 创建HashMap对象
HashMap<String, String> cities = new HashMap<>();
// 向集合里添加键值对
cities.put("1", "北京");
cities.put("2", "上海");
cities.put("3", "广州");
cities.put("4", "深圳");
cities.put("5", "泸州");
// 输出整个集合
System.out.println("城市集合:" + cities);
// 利用forEach()方法遍历集合(呈现简洁美)
System.out.println("利用forEach()方法遍历集合:");
cities.forEach((key, value) -> System.out.println(key + " : " + value));
}
}
Map集合提供了一个values()方法,返回Map集合所有值的Collection集合,可以通过forEach()来遍历这个值集合。
package net.hw.lesson23;
import java.util.Collection;
import java.util.HashMap;
/**
* 功能:利用forEach遍历值集合
* 作者:华卫
* 日期:2020年05月24日
*/
public class Example2305 {
public static void main(String[] args) {
// 创建HashMap对象
HashMap<String, String> cities = new HashMap<>();
// 向集合里添加键值对
cities.put("1", "北京");
cities.put("2", "上海");
cities.put("3", "广州");
cities.put("4", "深圳");
cities.put("5", "泸州");
// 输出整个集合
System.out.println("城市集合:" + cities);
// 获取值集合
Collection<String> values = cities.values();
// 利用forEach()遍历集合的值对象
System.out.print("利用forEach()遍历集合的值对象:");
values.forEach(city -> System.out.print(city + " "));
}
}
package net.hw.lesson23;
import java.util.HashMap;
import java.util.LinkedHashMap;
/**
* 功能:演示LinkedHashMap集合
* 作者:华卫
* 日期:2020年05月25日
*/
public class Example2306 {
public static void main(String[] args) {
// 声明HashMap变量
HashMap<String, String> cities;
// 创建HashMap对象
cities = new HashMap<>();
// 向集合里添加键值对
cities.put("3", "广州");
cities.put("2", "上海");
cities.put("1", "北京");
cities.put("5", "泸州");
cities.put("4", "深圳");
// 遍历整个集合
System.out.println("遍历HashMap集合:");
cities.forEach((key, value)-> System.out.println(key + " : " + value));
// 创建LinkedHashMap对象
cities = new LinkedHashMap<>();
// 向集合里添加键值对
cities.put("3", "广州");
cities.put("2", "上海");
cities.put("1", "北京");
cities.put("5", "泸州");
cities.put("4", "深圳");
// 遍历整个集合
System.out.println("遍历LinkedHashMap集合:");
cities.forEach((key, value)-> System.out.println(key + " : " + value));
}
}
一般情况下,用的最多的是HashMap,在Map中插入、删除和定位元素,HashMap 是最好的选择。但如果需要输出的顺序和输入的相同,那么用LinkedHashMap可以实现,它还可以按读取顺序来排列。
package net.hw.lesson23;
import java.util.TreeMap;
/**
* 功能:演示TreeMap,按键的自然顺序
* 作者:华卫
* 日期:2020年05月25日
*/
public class Example2307 {
public static void main(String[] args) {
// 创建TreeMap对象
TreeMap<String, String> cities = new TreeMap<>();
// 向集合里添加键值对
cities.put("3", "广州");
cities.put("2", "上海");
cities.put("1", "北京");
cities.put("5", "泸州");
cities.put("4", "深圳");
// 输出整个集合
System.out.println("城市集合:" + cities);
}
}
package net.hw.lesson23;
import java.util.Comparator;
import java.util.TreeMap;
/**
* 功能:演示TreeMap,按键的定制顺序
* 作者:华卫
* 日期:2020年05月25日
*/
public class Example2308 {
public static void main(String[] args) {
// 创建TreeMap对象(传入比较器对象,定制降序)
TreeMap<String, String> cities = new TreeMap<>(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o2.compareTo(o1);
}
});
// 向集合里添加键值对
cities.put("3", "广州");
cities.put("2", "上海");
cities.put("1", "北京");
cities.put("5", "泸州");
cities.put("4", "深圳");
// 输出整个集合
System.out.println("城市集合:" + cities);
}
}
Map接口还有一个实现类Hashtable,它和HashMap十分相似,其中一个主要区别在于Hashtable是线程安全的。Hashtable类有一个子类Properties。Properties主要用来存储字符串类型的键和值,在实际开发中,经常使用Properties集合类来存取应用的配置项。
language=Chinese
foreground-color=red
background-color=yellow
font-size=15px
package net.hw.lesson23;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;
/**
* 功能:利用Properties访问属性配置文件
* 作者:华卫
* 日期:2020年05月25日
*/
public class Example2309 {
public static void main(String[] args) throws IOException {
// 创建Properties对象
Properties pps = new Properties();
// 加载属性配置文件test.properties
pps.load(new FileReader("src/net/hw/lesson23/test.properties"));
// 遍历属性配置文件的键值对信息
pps.forEach((key, value) -> System.out.println(key + " : " + value));
// 创建文件输出流,指定输出文件
FileWriter fw = new FileWriter("src/net/hw/lesson23/test.properties");
// 在属性对象里添加新的键值对信息
pps.setProperty("charset", "UTF-8");
// 将新的键值对信息写入属性配置文件(参数1:文件输出流;参数2:注释信息)
pps.store(fw, "新增charset属性");
// 提示用户,写入新增信息成功
System.out.println("属性配置文件新增charset属性!");
}
}