• Java 集合之 ​Map 接口


    目录

    1、Map 的基础操作

    2、批量操作 Bulk Operations

    3、集合视图 Collection Views

    4、Map代数 Map Algebra


    Map是一个将键映射到值的对象。map不能包含重复的键,它模拟数学函数的抽象。

    Java平台包含三种通用Map实现:HashMap、TreeMap和LinkedHashMap。它们的行为和性能完全类似于HashSet、TreeSet和LinkedHashSet。

    例如,Map常见的应用场景,按部门对员工进行分组

    1. // Group employees by department
    2. Map<Department, List<Employee>> byDept = employees.stream()
    3. .collect(Collectors.groupingBy(Employee::getDepartment));

    或者按部门计算工资总和

    1. // Compute sum of salaries by department
    2. Map<Department, Integer> totalByDept = employees.stream()
    3. .collect(Collectors.groupingBy(Employee::getDepartment,
    4. Collectors.summingInt(Employee::getSalary)));

    或者通过及格或不及格来分组学生:

    1. // Partition students into passing and failing
    2. Map<Boolean, List<Student>> passingFailing = students.stream()
    3. .collect(Collectors.partitioningBy(s -> s.getGrade()>= PASS_THRESHOLD));

    甚至同时使用多个条件进行分类:

    1. // Cascade Collectors
    2. Map<String, Map<String, List<Person>>> peopleByStateAndCity
    3. = personStream.collect(Collectors.groupingBy(Person::getState,
    4. Collectors.groupingBy(Person::getCity)))

    1、Map 的基础操作

    Map的基本操作(put、get、containsKey、containsValue、size和isEmpty)与Hashtable中的对应操作完全相同。

    下面的程序统计字符串在参数列表中出现的次数。

    1. public class Freq {
    2. public static void main(String[] args) {
    3. args = "java freq if it is to be it is up to me to delegate".split(" ");
    4. Map<String, Integer> m = new TreeMap<>();
    5. // Initialize frequency table from command line
    6. for (String a : args) {
    7. Integer freq = m.get(a);
    8. m.put(a, (freq == null) ? 1 : freq + 1);
    9. }
    10. System.out.println(m.size() + " distinct words:");
    11. System.out.println(m);
    12. }
    13. }

    该程序产生以下输出:

    10 distinct words:
    {delegate=1, java=1, be=1, freq=1, me=1, is=2, it=2, to=3, up=1, if=1}

    如果希望看到按字母顺序排列的结果,可以将Map的实现类型从HashMap更改为TreeMap。同一命令行会生成以下输出:

    10 distinct words:
    {be=1, delegate=1, freq=1, if=1, is=2, it=2, java=1, me=1, to=3, up=1}

    同样,将映射的实现类型更改为LinkedHashMap,就可以使程序按照单词在命令行中首次出现的顺序进行打印。同一命令行会产生以下输出:

    10 distinct words:
    {java=1, freq=1, if=1, it=2, is=2, to=3, be=1, up=1, me=1, delegate=1}

    Map 提供的构造函数支持Map对象作为入参:

    1. // 其中入参m,为另一个map
    2. Map<K, V> copy = new HashMap<K, V>(m);

    简单的示例程序

    1. import java.util.HashMap;
    2. import java.util.Map;
    3. public class Freq {
    4. public static void main(String[] args) {
    5. Map<String, String> m = new HashMap<>();
    6. m.put("A", "a");
    7. m.put("B", "b");
    8. m.put("C", "c");
    9. Map<String, String> copy = new HashMap<>(m);
    10. for (Map.Entry<String, String> entry : copy.entrySet()) {
    11. System.out.println(entry.getKey() + ":" + entry.getValue());
    12. }
    13. }
    14. }

    2、批量操作 Bulk Operations

    clear 从Map中删除所有映射。

    putAll 操作Map是对Collection接口addAll操作的模拟。putAll 操作与Map有参构造函数结合使用,为创建带默认值的map提供了一种简洁的方法。下边是演示代码:

    1. static <K, V> Map<K, V> newAttributeMap(Map<K, V>defaults, Map<K, V> overrides) {
    2. Map<K, V> result = new HashMap<K, V>(defaults);
    3. result.putAll(overrides);
    4. return result;
    5. }

    3、集合视图 Collection Views

     Collection Views 允许通过以下三种方式将Map视为集合:

    • keySet — Map中包含的键的集合(set 集合)。
    • values — Map中包含的值的集合。此集合不是Set,因为多个键可以映射到相同的值。
    • entrySet — Map中包含的键值对的集合。在Map接口中提供了一个嵌套接口 Map.EntryentrySet 集合中的元素类型就是Entry(键值对)

    Collection Views 提供了在Map上迭代的方法。下边例子演示了使用for-each在Map中遍历键的标准用法:

    1. for (KeyType key : m.keySet())
    2. System.out.println(key);

    使用迭代器

    1. // Filter a map based on some
    2. // property of its keys.
    3. for (Iterator<Type> it = m.keySet().iterator(); it.hasNext(); )
    4. if (it.next().isBogus())
    5. it.remove();

    遍历键-值对的标准用法:

    1. for (Map.Entry e : m.entrySet())
    2. System.out.println(e.getKey() + ": " + e.getValue());

    4、Map代数 Map Algebra

    在使用集合时,批量操作 containsAll、removeAll和retainAll等,都是非常有效的工具。

    在Map中如何实现这一操作?比如,想知道Map a是否包含Map b中的所有键值映射。下边代码实现了这一功能

    1. if (m1.entrySet().containsAll(m2.entrySet())) {
    2. ...
    3. }

    同样的,如果想知道两个Map对象是否包含相同键的映射。

    1. if (m1.keySet().equals(m2.keySet())) {
    2. ...
    3. }

    应用场景:如果有一个表示属性-值对的集合的Map,以及两个表示所需属性和允许属性的set。下面的代码将确定属性映射是否符合这些约束,如果不符合,则打印详细的错误消息。

    1. static <K, V> boolean validate(Map<K, V> attrMap, Set<K> requiredAttrs, Set<K> permittedAttrs) {
    2. boolean valid = true;
    3. Set<K> attrs = attrMap.keySet();
    4. if (!attrs.containsAll(requiredAttrs)) { // 检验是否符合约束
    5. Set<K> missing = new HashSet<K>(requiredAttrs); // copy原Map
    6. missing.removeAll(attrs); // 移除掉已经存在的约束
    7. System.out.println("Missing attributes: " + missing); // 打印没有匹配到的约束
    8. valid = false; // 校验失败
    9. }
    10. if (!permittedAttrs.containsAll(attrs)) {
    11. Set<K> illegal = new HashSet<K>(attrs);
    12. illegal.removeAll(permittedAttrs);
    13. System.out.println("Illegal attributes: " + illegal);
    14. valid = false;
    15. }
    16. return valid;
    17. }

    如果想知道两个Map对象共有的所有键

    1. Set<KeyType>commonKeys = new HashSet<KeyType>(m1.keySet());
    2. commonKeys.retainAll(m2.keySet()); // 交集

    如果想删除一个Map与另一个Map共有的键值对或者键。

    1. m1.entrySet().removeAll(m2.entrySet()); // 删除键值对
    2. m1.keySet().removeAll(m2.keySet()); // 删除键

    参考文章:https://docs.oracle.com/javase/tutorial/collections/interfaces/map.html

  • 相关阅读:
    VS Code 远程连接 Jupyter
    DDS数据分发服务
    uni-app 5小时快速入门 3 创建uni-app工程(下)
    在这个基础上再点缀一下让他焕然一新,该怎么点缀,比如让流星有闪烁的光芒
    计算机网络总结笔记
    SAP 公司间销售
    Java的JDK基础
    git常用操作记录
    K-Core, K-Shell & K-Crust傻傻分不清楚
    套接字编程:UDP通信程序编写、套接字接口、字节序转换接口
  • 原文地址:https://blog.csdn.net/swadian2008/article/details/126763832