Java HashMap示例

https://www.callicoder.com/categories/java/

Java HashMap是基于哈希表的Java Map接口的实现。您可能知道,地图是键值对的集合。它将键映射到值。

集合层次结构中的Java HashMap

以下是有关Java中的HashMaps的几点注意事项-

  • HashMap不能包含重复的键。

  • Java HashMap允许null值和null键。

  • HashMap是一个无序集合。它不保证元素的任何特定顺序。

  • Java HashMap不是线程安全的。您必须显式同步对HashMap的并发修改。

 

创建一个HashMap并向其添加键值对

下面的示例演示如何创建HashMap以及如何向其添加新的键值对。

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

public class CreateHashMapExample {
	public static void main(String[] args) {
		// Creating a HashMap
		Map<String, Integer> numberMapping = new HashMap<>();

		// Adding key-value pairs to a HashMap
		numberMapping.put("One", 1);
		numberMapping.put("Two", 2);
		numberMapping.put("Three", 3);

		// Add a new key-value pair only if the key does not exist in the HashMap, or is
		// mapped to `null`
		numberMapping.putIfAbsent("Four", 4);

		System.out.println(numberMapping);
	}
}
# Output
{One=1, Four=4, Two=2, Three=3}

在HashMap中访问键并修改其关联值

下面的示例显示:

  • 如何检查HashMap是否为空? isEmpty()
  • 如何找到HashMap的大小 size()
  • 如何检查HashMap中是否存在给定密钥? containsKey()
  • 如何检查HashMap中是否存在给定值? containsValue()
  • 如何获取与HashMap中给定键关联的值。 get()
  • 如何在HashMap中修改与给定键关联的值。 put()
import java.util.HashMap;
import java.util.Map;

public class AccessKeysFromHashMapExample {
	public static void main(String[] args) {
		Map<String, String> userCityMapping = new HashMap<>();

		// Check if a HashMap is empty
		System.out.println("is userCityMapping empty? : " + userCityMapping.isEmpty());

		userCityMapping.put("John", "New York");
		userCityMapping.put("Rajeev", "Bengaluru");
		userCityMapping.put("Steve", "London");

		System.out.println("userCityMapping HashMap : " + userCityMapping);

		// Find the size of a HashMap
		System.out.println("We have the city information of " + userCityMapping.size() + " users");

		String userName = "Steve";
		// Check if a key exists in the HashMap
		if (userCityMapping.containsKey(userName)) {
			// Get the value assigned to a given key in the HashMap
			String city = userCityMapping.get(userName);
			System.out.println(userName + " lives in " + city);
		} else {
			System.out.println("City details not found for user " + userName);
		}

		// Check if a value exists in a HashMap
		if (userCityMapping.containsValue("New York")) {
			System.out.println("There is a user in the userCityMapping who lives in New York");
		} else {
			System.out.println("There is no user in the userCityMapping who lives in New York");
		}

		// Modify the value assigned to an existing key
		userCityMapping.put(userName, "California");
		System.out.println(userName + " moved to a new city " + userCityMapping.get(userName)
				+ ", New userCityMapping : " + userCityMapping);

		// The get() method returns `null` if the specified key was not found in the
		// HashMap
		System.out.println("Lisa's city : " + userCityMapping.get("Lisa"));
	}
}
# Output
is userCityMapping empty? : true
userCityMapping HashMap : {Steve=London, John=New York, Rajeev=Bengaluru}
We have the city information of 3 users
Steve lives in London
There is a user in the userCityMapping who lives in New York
Steve moved to a new city California, New userCityMapping : {Steve=California, John=New York, Rajeev=Bengaluru}
Lisa's city : null

 

从HashMap删除密钥

以下示例显示了如何:

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

public class RemoveKeysFromHashMapExample {
	public static void main(String[] args) {
		Map<String, String> husbandWifeMapping = new HashMap<>();
		husbandWifeMapping.put("Jack", "Marie");
		husbandWifeMapping.put("Chris", "Lisa");
		husbandWifeMapping.put("Steve", "Jennifer");

		System.out.println("Husband-Wife Mapping : " + husbandWifeMapping);

		// Remove a key from the HashMap
		// Ex - Unfortunately, Chris got divorced. Let's remove him from the mapping
		String husband = "Chris";
		String wife = husbandWifeMapping.remove(husband);

		System.out.println("Couple (" + husband + " => " + wife + ") got divorced");
		System.out.println("New Mapping : " + husbandWifeMapping);

		// Remove a key from the HashMap only if it is mapped to the given value
		// Ex - Divorce "Jack" only if He is married to "Linda"
		boolean isRemoved = husbandWifeMapping.remove("Jack", "Linda");
		System.out.println("Did Jack get removed from the mapping? : " + isRemoved);

		// remove() returns null if the mapping was not found for the supplied key
		wife = husbandWifeMapping.remove("David");
		if (wife == null) {
			System.out.println("Looks like David is not married to anyone");
		} else {
			System.out.println("Removed David and his wife from the mapping");
		}
	}
}
 
# Output
Husband-Wife Mapping : {Steve=Jennifer, Chris=Lisa, Jack=Marie}
Couple (Chris => Lisa) got divorced
New Mapping : {Steve=Jennifer, Jack=Marie}
Did Jack get removed from the mapping? : false
Looks like David is not married to anyone

从HashMap获取entrySet,keySet和值

Map接口提供了检索条目集(键-值对),键集和值集合的方法。

以下示例显示了如何从HashMap中检索它们-

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class HashMapEntryKeySetValuesExample {
	public static void main(String[] args) {
		Map<String, String> countryISOCodeMapping = new HashMap<>();

		countryISOCodeMapping.put("India", "IN");
		countryISOCodeMapping.put("United States of America", "US");
		countryISOCodeMapping.put("Russia", "RU");
		countryISOCodeMapping.put("Japan", "JP");
		countryISOCodeMapping.put("China", "CN");

		// HashMap's entry set
		Set<Map.Entry<String, String>> countryISOCodeEntries = countryISOCodeMapping.entrySet();
		System.out.println("countryISOCode entries : " + countryISOCodeEntries);

		// HashMap's key set
		Set<String> countries = countryISOCodeMapping.keySet();
		System.out.println("countries : " + countries);

		// HashMap's values
		Collection<String> isoCodes = countryISOCodeMapping.values();
		System.out.println("isoCodes : " + isoCodes);
	}
}
# Output
countryISOCode entries : [United States of America=US, Japan=JP, China=CN, India=IN, Russia=RU]
countries : [United States of America, Japan, China, India, Russia]
isoCodes : [US, JP, CN, IN, RU]

遍历HashMap

以下示例显示了对HashMap进行迭代的不同方法-

  1. 使用Java 8 forEach和lambda表达式遍历HashMap 。

  2. 使用iterator()遍历HashMap的entrySet 。

  3. 使用Java 8 forEach和lambda表达式迭代HashMap的entrySet 。

  4. 使用简单的for-each循环遍历HashMap的entrySet。

  5. 遍历HashMap的keySet。

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

public class IterateOverHashMap {
	public static void main(String[] args) {
		Map<String, Double> employeeSalary = new HashMap<>();
		employeeSalary.put("David", 76000.00);
		employeeSalary.put("John", 120000.00);
		employeeSalary.put("Mark", 95000.00);
		employeeSalary.put("Steven", 134000.00);

		System.out.println("=== Iterating over a HashMap using Java 8 forEach and lambda ===");
		employeeSalary.forEach((employee, salary) -> {
			System.out.println(employee + " => " + salary);
		});

		System.out.println("\n=== Iterating over the HashMap's entrySet using iterator() ===");
		Set<Map.Entry<String, Double>> employeeSalaryEntries = employeeSalary.entrySet();
		Iterator<Map.Entry<String, Double>> employeeSalaryIterator = employeeSalaryEntries.iterator();
		while (employeeSalaryIterator.hasNext()) {
			Map.Entry<String, Double> entry = employeeSalaryIterator.next();
			System.out.println(entry.getKey() + " => " + entry.getValue());
		}

		System.out.println("\n=== Iterating over the HashMap's entrySet using Java 8 forEach and lambda ===");
		employeeSalary.entrySet().forEach(entry -> {
			System.out.println(entry.getKey() + " => " + entry.getValue());
		});

		System.out.println("\n=== Iterating over the HashMap's entrySet using simple for-each loop ===");
		for (Map.Entry<String, Double> entry : employeeSalary.entrySet()) {
			System.out.println(entry.getKey() + " => " + entry.getValue());
		}

		System.out.println("\n=== Iterating over the HashMap's keySet ===");
		employeeSalary.keySet().forEach(employee -> {
			System.out.println(employee + " => " + employeeSalary.get(employee));
		});
	}
}
# Output
=== Iterating over a HashMap using Java 8 forEach and lambda ===
David => 76000.0
John => 120000.0
Mark => 95000.0
Steven => 134000.0

=== Iterating over the HashMap's entrySet using iterator() ===
David => 76000.0
John => 120000.0
Mark => 95000.0
Steven => 134000.0

=== Iterating over the HashMap's entrySet using Java 8 forEach and lambda ===
David => 76000.0
John => 120000.0
Mark => 95000.0
Steven => 134000.0

=== Iterating over the HashMap's entrySet using simple for-each loop ===
David => 76000.0
John => 120000.0
Mark => 95000.0
Steven => 134000.0

=== Iterating over the HashMap's keySet ===
David => 76000.0
John => 120000.0
Mark => 95000.0
Steven => 134000.0
 

Java HashMap与用户定义的对象

查看以下示例,以了解如何创建和使用用户定义对象的HashMap。

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

class Employee {
	private Integer id;
	private String name;
	private String city;

	public Employee(Integer id, String name, String city) {
		this.id = id;
		this.name = name;
		this.city = city;
	}

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getCity() {
		return city;
	}

	public void setCity(String city) {
		this.city = city;
	}

	@Override
	public String toString() {
		return "Employee{" + "name='" + name + '\'' + ", city='" + city + '\'' + '}';
	}
}

public class HashMapUserDefinedObjectExample {
	public static void main(String[] args) {
		Map<Integer, Employee> employeesMap = new HashMap<>();

		employeesMap.put(1001, new Employee(1001, "Rajeev", "Bengaluru"));
		employeesMap.put(1002, new Employee(1002, "David", "New York"));
		employeesMap.put(1003, new Employee(1003, "Jack", "Paris"));

		System.out.println(employeesMap);
	}
}
# Output
{1001=Employee{name='Rajeev', city='Bengaluru'}, 1002=Employee{name='David', city='New York'}, 1003=Employee{name='Jack', city='Paris'}}

同步访问Java HashMap

Java HashMap不是线程安全的。在多线程尝试同时修改HashMap的多线程环境中,它可能变得不确定。

演示HashMap在多线程环境中的不可预测行为的示例

以下示例演示了当多个线程尝试同时修改HashMap时,HashMap如何变得不确定的-

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class UnsafeHashMapExample {
	public static void main(String[] args) throws InterruptedException {
		Map<String, Integer> cricketTeamScore = new HashMap<>();
		cricketTeamScore.put("Australia", 349);
		cricketTeamScore.put("India", 250);

		// Create an ExecutorService with a Thread Pool of size 10
		ExecutorService executorService = Executors.newFixedThreadPool(10);

		// Create a Runnable object that increments the value associated with a given
		// key in the HashMap by one.
		Runnable task = () -> {
			incrementTeamScore(cricketTeamScore, "India");
		};

		// Submit the Runnable object to the executorService 100 times to test
		// concurrent modifications
		for (int i = 0; i < 100; i++) {
			executorService.submit(task);
		}

		executorService.shutdown();
		executorService.awaitTermination(60, TimeUnit.SECONDS);

		System.out.println("Final Score of Team India : " + cricketTeamScore.get("India"));
	}

	// Increment the score of a team by one
	private static void incrementTeamScore(Map<String, Integer> cricketTeamScore, String team) {
		Integer score = cricketTeamScore.get(team);
		cricketTeamScore.put(team, score + 1);
	}
}

上面程序的最终输出应该是350因为初始值为250,我们将其递增了100倍。

但是,由于多个线程尝试同时修改HashMap,因此一个线程所做的更改将被其他线程覆盖,并且输出将变得不确定。

如果您多次运行上述程序,则会发现每次运行它都会产生不同的输出。

# Output
Final Score of Team India : 343

您可以从我的Java并发问题和线程同步教程中了解有关并发问题的更多信息。

演示如何将并发修改同步到HashMap的示例

让我们编写先前程序的线程安全版本。我们可以对程序进行以下两项更改以使其具有线程安全性-

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.*;

public class SynchronizedHashMapExample {
	public static void main(String[] args) throws InterruptedException {
		Map<String, Integer> cricketTeamScore = Collections.synchronizedMap(new HashMap<>());
		cricketTeamScore.put("Australia", 349);
		cricketTeamScore.put("India", 250);

		// Create an ExecutorService with a Thread Pool of size 10
		ExecutorService executorService = Executors.newFixedThreadPool(10);

		// Create a Runnable object that increments the value associated with a given
		// key in the HashMap by one.
		Runnable task = () -> {
			incrementTeamScore(cricketTeamScore, "India");
		};

		// Submit the Runnable object to the executorService 100 times to test
		// concurrent modifications
		for (int i = 0; i < 100; i++) {
			executorService.submit(task);
		}

		executorService.shutdown();
		executorService.awaitTermination(60, TimeUnit.SECONDS);

		System.out.println("Final Score of Team India : " + cricketTeamScore.get("India"));
	}

	// Increment the score of a team by one
	private static void incrementTeamScore(Map<String, Integer> cricketTeamScore, String team) {
		synchronized (cricketTeamScore) {
			Integer score = cricketTeamScore.get(team);
			cricketTeamScore.put(team, score + 1);
		}
	}
}

该程序产生正确的输出-

# Output
Final Score of Team India : 350

您也可以将ConcurrentHashMap用于线程安全,而不是通过Collections.synchronizedMap()方法获取的HashMap 。ConcurrentHashMap在Map上提供线程安全操作。

结论

恭喜大家!在本文中,您学习了什么是HashMap,如何创建HashMap,如何向HashMap中添加新的键值对,如何从HashMap中删除键,如何在HashMap上进行迭代以及如何同步HashMap。 。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值