Java Map

Map是什么?

Map是Java中的一种数据集合类型,它是一种键值对的映射表(一个键key对应一个值value)。Map中的每个元素都包含一个键和一个值,键和值可以是任意类型的对象。Map中的键是唯一的,因此不能有重复的键。
Java中的map类似于Python里的dict。


Map的主要方法

1. put()
向Map中添加键值对。

Map<String, Integer> map = new HashMap<>();
map.put("apple", 1);
map.put("banana", 2);

2. get() 根据获取对应的值。

Map<String, Integer> map = new HashMap<>();
map.put("apple", 1);
map.put("banana", 2);

//通过key “apple”获取它的值
int value = map.get("apple"); // 1

3. containsKey() 判断Map中是否包含指定的

Map<String, Integer> map = new HashMap<>();
map.put("apple", 1);
map.put("banana", 2);

// map里是否包含"apple"和“orange”?
boolean containsApple = map.containsKey("apple"); // true
boolean containsOrange = map.containsKey("orange"); // false

4. containsValue() 判断Map中是否包含指定的

Map<String, Integer> map = new HashMap<>(); map.put("apple", 1); map.put("banana", 2);

// 是否包含值 1 和 3? boolean containsOne = map.containsValue(1); // true boolean containsThree = map.containsValue(3); // false

5. remove()
根据键删除对应的键值对。

Map<String, Integer> map = new HashMap<>();
map.put("apple", 1);
map.put("banana", 2);

map.remove("apple");

6. size()
获取Map中键值对的数量。

Map<String, Integer> map = new HashMap<>();
map.put("apple", 1);
map.put("banana", 2);

int size = map.size(); // 2

7. clear()
清空Map中的所有键值对。

Map<String, Integer> map = new HashMap<>();
map.put("apple", 1);
map.put("banana", 2);

map.clear();

Map的实现类

Java中有多种Map的实现类,常用的有HashMapTreeMapLinkedHashMap。最常用的是HashMap

1. HashMap HashMap是基于哈希表实现的Map,它不保证键值对的顺序。

Map<String, Integer> map = new HashMap<>();
map.put("apple", 1);
map.put("banana", 2);
map.put("orange", 3);

2. TreeMap TreeMap可以对键进行排序

Map<String, Integer> map = new TreeMap<>();
map.put("apple", 1);
map.put("banana", 2);
map.put("orange", 3);

3. LinkedHashMap LinkedHashMap是基于哈希表和链表实现的Map,它保证键值对的顺序与添加顺序一致

Map<String, Integer> map = new LinkedHashMap<>();
map.put("apple", 1);
map.put("banana", 2);
map.put("orange", 3);

Map的使用示例

import java.util.HashMap;
import java.util.Map;

public class MapExample {
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        map.put("apple", 1);
        map.put("banana", 2);
        map.put("orange", 3);

        System.out.println("Map中的键值对数量:" + map.size()); // 3

        int value = map.get("apple"); // 1

        boolean containsApple = map.containsKey("apple"); // true
        boolean containsGrape = map.containsKey("grape"); // false

        System.out.println("Map中是否包含apple:" + containsApple); // true
        System.out.println("Map中是否包含grape:" + containsGrape); // false

        map.remove("banana");

        System.out.println("Map中的键值对数量:" + map.size()); // 2

        map.clear();

注意事项

通常我们遍历和操作Map,最好使用Iterator(同Set),Iterator会在处理过程中维护Map的结构不变。

例. 假设我们有一个HashMap,其中包含一些键值对:

HashMap<String, Integer> map = new HashMap<>();
map.put("apple", 1);
map.put("banana", 2);
map.put("orange", 3);
map.put("grape", 4);
map.put("watermelon", 5);

现在,我们想要删除所有值小于等于3的键值对。我们可以使用Iterator来遍历这个HashMap并删除符合条件的键值对:

Iterator<Map.Entry<String, Integer>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
    Map.Entry<String, Integer> entry = iterator.next();
    if (entry.getValue() <= 3) {
        iterator.remove();
    }
}

在这个例子中,

  • 我们首先使用entrySet()方法获取HashMap中所有的键值对,然后使用iterator()方法获取一个Iterator对象;
  • 接着,我们使用hasNext()方法检查是否还有下一个元素,如果有,我们使用next()方法获取下一个元素,并使用getValue()方法获取值;
  • 如果值小于等于3,我们使用remove()方法删除这个键值对。

完整案例

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class MapExample {
   public static void main(String[] args) {
   	HashMap<String, Integer> map = new HashMap<>();
   	map.put("apple", 1);
   	map.put("banana", 2);
   	map.put("orange", 3);
   	map.put("grape", 4);
   	map.put("watermelon", 5);
   	System.out.println("before: " + map);
   	Iterator<Map.Entry<String, Integer>> iterator = map.entrySet().iterator();
   	while (iterator.hasNext()) {
   	    Map.Entry<String, Integer> entry = iterator.next();
   	    if (entry.getValue() <= 3) {
   	        iterator.remove();
   	    }
   	}
   	System.out.println("after: " + map);
   }
}

运行结果

before: {banana=2, orange=3, apple=1, grape=4, watermelon=5}
after: {grape=4, watermelon=5}


一个完整的例子

  • 如何使用常用的 Java Map 方法来实现一个简单的单词计数器

例子:单词计数器

注意:需要先在project根目录创建一个example.txt文件,并在里面写一些英文(以下方法只能通过空格和逗号句号等分割单词,所以只能统计英文词频) 可以从这里下载example.txt用来测试。

假设我们读取一个文本,我们希望计算文本里每个单词出现的次数。为了完成这个任务,我们可以使用 Java Map 来存储每个单词出现的次数。

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class MapFullExample {

	public static void main(String[] args) {
		
		// 读取project根目录下的example.txt文件,生成一个字符串text
		String text = getStringFromFile("example.txt");
		
		// 在不是alphanumeric characters的位置分割字符串,生成一个由单词组成的数组
		String[] words = text.split("\\W+"); 
		
		// 创建一个词频统计Map,Key是单词,Value是词频
		Map<String, Integer> wordCountMap = new HashMap<>();

		for (String word : words) {
			String lowerCaseWord = word.toLowerCase();  // 先将每个单词转换成小写
		    Integer count = wordCountMap.get(lowerCaseWord); // 从现有Map中获取count数

		    if (count == null) {   // 如果现有Map里不包含这个词,count就是null,此时把原有count设置为0
		        count = 0;
		    }
		    wordCountMap.put(word, count + 1);  // 因为单词又出现了一次,所以count+1,然后保存回Map
		}
		
		// 打印单词和词频
		for (Map.Entry<String, Integer> entry : wordCountMap.entrySet()) {
		    String word = entry.getKey().toLowerCase();
		    Integer count = entry.getValue();

		    System.out.println(word + ": " + count);
		}
	}
	
	// 读取文档的方法,返回包含文档中所有行的一个String
	private static String getStringFromFile(String fileName) {
		
		// 创建StringBuilder对象sb, 用来将文件里读取的多行字符串组成一个字符串
		StringBuilder sb = new StringBuilder();
		
		// 一行一行读取文件,并添加到sb。如果文件不存在,抛出异常
		try (BufferedReader br = new BufferedReader(new FileReader(fileName))) {
		    String line;   // 用来记录读到的每一行
		    while ((line = br.readLine()) != null) {  //如果读取的一行不为空
		        sb.append(line);   // 添加到sb
		    }
		} catch (IOException e) {
		    e.printStackTrace();
		}

		String text = sb.toString();   // 生成一个String
		return text;
	}

}