Java 集合全教程—Map

这篇具有很好参考价值的文章主要介绍了Java 集合全教程—Map。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、概述

Map是将关键点映射到值的对象。映射不能包含重复的关键点:每个关键点最多可以映射到一个值。它对数学函数抽象进行建模。Map接口包括基本操作(如put、get、remove、containsKey、containsValue、size和empty)、批量操作(如putAll和clear)和集合视图(如keySet、entrySet和values)的方法。
Java平台包含三个通用的Map实现:HashMap、TreeMap和LinkedHashMap。它们的行为和性能与HashSet、TreeSet和LinkedHashSet完全类似,如Set Interface部分所述。
本页的其余部分将详细讨论Map界面。但首先,这里有一些使用JDK8聚合操作收集到Maps的更多示例。建模真实世界的对象是面向对象编程中的一项常见任务,因此可以合理地认为,例如,一些程序可能会按部门对员工进行分组:

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

或者按部门计算所有工资的总和:

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

或者也许按及格或不及格的成绩对学生进行分组:

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

您还可以按城市对人员进行分组:

// Classify Person objects by city
Map<String, List<Person>> peopleByCity
         = personStream.collect(Collectors.groupingBy(Person::getCity));

甚至级联两个收集器,按州和城市对人进行分类:

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

同样,这些只是如何使用新的JDK 8 API的几个示例

二、Map接口基本操作

Map的基本操作(put、get、containsKey、containsValue、size和isEmpty)的行为与Hashtable中的对应操作完全相同。下面的程序生成一个在其参数列表中找到的单词的频率表。频率表将每个单词映射到它在参数列表中出现的次数:

import java.util.*;

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

        // Initialize frequency table from command line
        for (String a : args) {
            Integer freq = m.get(a);
            m.put(a, (freq == null) ? 1 : freq + 1);
        }

        System.out.println(m.size() + " distinct words:");
        System.out.println(m);
    }
}

这个程序唯一棘手的地方是put语句的第二个参数。该参数是一个条件表达式,如果该单词以前从未见过,则将频率设置为1,如果该词已经见过,则比其当前值多设置一。尝试使用以下命令运行此程序:

java Freq if it is to be it is up to me to delegate

程序生成以下输出:

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

假设您更喜欢按字母顺序查看频率表。您所要做的就是将Map的实现类型从HashMap更改为TreeMap。进行这四个字符的更改会使程序从同一命令行生成以下输出:

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

类似地,只需将映射的实现类型更改为LinkedHashMap,就可以使程序按照单词第一次出现在命令行上的顺序打印频率表。这样做会产生以下输出:

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

他的灵活性有力地说明了基于接口的框架的威力。
与SetandListinterface一样,Map加强了对equals和hashCode方法的要求,因此可以比较两个Map对象的逻辑相等性,而不考虑它们的实现类型。如果两个Map实例表示相同的键值映射,则它们是相等的。
按照惯例,所有通用Map实现都提供构造函数,这些构造函数接受Map对象并初始化新Map以包含指定Map中的所有键值映射。这个标准的Map转换构造函数与标准的Collection构造函数完全类似:它允许调用方创建所需实现类型的Map,该Map最初包含另一个Map中的所有映射,而不考虑其他Map的实现类型。例如,假设您有一个名为m的Map。下面的一行创建了一个新的HashMap,最初包含与m相同的所有键值映射:

Map<K, V> copy = new HashMap<K, V>(m);

三、Map接口批量操作

clear操作所做的正是您所认为的:它从Map中删除所有映射。putAll操作与Collection接口的addAll操作类似。除了将一个Map转储到另一个Map的明显用途外,它还有第二个更微妙的用途。假设Map用于表示属性值对的集合;putAll操作与Map转换构造函数相结合,提供了一种使用默认值实现属性映射创建的巧妙方法。以下是演示此技术的静态工厂方法:

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

四、集合视图

集合视图方法允许通过以下三种方式将地图视为集合:

  • keySet—贴图中包含的关键点集。
  • values—Map中包含的值的集合。此集合不是集合,因为多个键可以映射到同一个值。
  • entrySet—Map中包含的键值对的集合。Map接口提供了一个名为Map.Entry的小型嵌套接口,即该集合中元素的类型。

“集合”视图提供了对Map进行迭代的唯一方法。此示例说明了使用for each构造对Map中的键进行迭代的标准习惯用法:

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

 并且使用迭代器:

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

迭代值的习惯用法是类似的。以下是对键值对进行迭代的习惯用法:

for (Map.Entry<KeyType, ValType> e : m.entrySet())
    System.out.println(e.getKey() + ": " + e.getValue());

起初,许多人担心这些习惯用法可能很慢,因为每次调用Collection视图操作时,Map都必须创建一个新的Collection实例。请放心:Map没有理由每次被要求获得给定的“集合”视图时都不能始终返回相同的对象。这正是java.util中所有Map实现所做的。
对于所有三个Collection视图,调用Iterator的remove操作会从backing Map中删除关联的条目,假设backing Map从一开始就支持元素删除。前面的过滤习惯用法说明了这一点。
使用entrySet视图,还可以通过在迭代期间调用Map.Entry的setValue方法来更改与键关联的值(同样,假设Map从一开始就支持值修改)。请注意,这些是在迭代过程中修改Map的唯一安全方法;如果在迭代过程中以任何其他方式修改基础Map,则行为是未指定的。
集合视图支持多种形式的元素移除——remove、removeAll、retainAll和clear操作,以及Iterator.remove操作。(再次假设支持Map支持元素移除。)
Collection ”视图在任何情况下都不支持添加元素。这对keySet和values视图没有意义,对entrySet视图也没有必要,因为支持Map的put和putAll方法提供了相同的功能。

五、Collection 视图的奇妙用途:Map代数

当应用于“Collection ”视图时,批量操作(containsAll、removeAll和retanall)是令人惊讶的强大工具。首先,假设您想知道一个Map是否是另一个Map的子映射,也就是说,第一个Map是否包含第二个Map中的所有键值映射。下面的成语起了作用:

if (m1.entrySet().containsAll(m2.entrySet())) {
    ...
}

类似地,假设您想知道两个Map对象是否包含所有相同键的映射:

if (m1.keySet().equals(m2.keySet())) {
    ...
}

假设您有一个表示属性值对集合的Map,以及两个表示必需属性和允许属性的Set。(允许的属性包括必需的属性。)下面的代码段确定属性映射是否符合这些约束,如果不符合,则打印详细的错误消息:

static <K, V> boolean validate(Map<K, V> attrMap, Set<K> requiredAttrs, Set<K>permittedAttrs) {
    boolean valid = true;
    Set<K> attrs = attrMap.keySet();

    if (! attrs.containsAll(requiredAttrs)) {
        Set<K> missing = new HashSet<K>(requiredAttrs);
        missing.removeAll(attrs);
        System.out.println("Missing attributes: " + missing);
        valid = false;
    }
    if (! permittedAttrs.containsAll(attrs)) {
        Set<K> illegal = new HashSet<K>(attrs);
        illegal.removeAll(permittedAttrs);
        System.out.println("Illegal attributes: " + illegal);
        valid = false;
    }
    return valid;
}

📢文章下方有交流学习区!一起学习进步!也可以前往官网,加入官方微信交流群💪💪💪
📢首发CSDN博客,创作不易,如果觉得文章不错,可以点赞👍收藏📁评论📒
📢你的支持和鼓励是我创作的动力❗❗❗ 文章来源地址https://www.toymoban.com/news/detail-475808.html

到了这里,关于Java 集合全教程—Map的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java 集合Map相关面试题

    📕作者简介: 过去日记 ,致力于Java、GoLang,Rust等多种编程语言,热爱技术,喜欢游戏的博主。 📗本文收录于java面试题系列,大家有兴趣的可以看一看 📘相关专栏Rust初阶教程、go语言基础系列、spring教程等,大家有兴趣的可以看一看 📙Java并发编程系列,设计模式系列、

    2024年01月25日
    浏览(30)
  • 【Java】Map集合中常用方法

    Map集合的常用方法 方法名称 作用 V put(Key k,V value) 添加元素 V remove(K key, V value) 根据键值删除对应的值 void clear() 清除所有键值元素 boolean containsKey(Object key) 判断集合中是否包含指定的键 boolean containsValue(Object value) 判断集合中是否包含指定的值 boolean isEmpty() 判断集合是否为空

    2024年02月08日
    浏览(31)
  • Java集合利器 Map & Set

    Map 和 Set 是一种专门用来进行搜索的数据结构,其搜索的效率与其具体的实例化子类有关。它们分别定义了两种不同的数据结构和特点: Map(映射) :Map是一种键值对(key-value)的集合,每个键值对都是一个元素。 Set(集合) :Set是一种不允许重复元素(key)的集合。 通

    2024年02月12日
    浏览(30)
  • 【Go】Go 语言教程--Go 语言Map(集合)(十六)

    往期回顾: Go 语言教程–介绍(一) Go 语言教程–语言结构(二) Go 语言教程–语言结构(三) Go 语言教程–数据类型(四) Go 语言教程–语言变量(五) Go 语言教程–GO语言常量(六) Go 语言教程–GO语言运算符(七) Go 语言教程–GO条件和循环语句(八) Go 语言教程

    2024年02月16日
    浏览(35)
  • Java集合(List、Set、Map)

    Java中的集合是用于存储和组织对象的数据结构。Java提供了许多不同的集合类,包括List、Set和Map等,以满足不同的需求。下面将介绍一些常见的Java集合类及其使用方法。 一、List List是一个有序的集合,它允许元素重复出现,并提供了索引访问元素的功能。List可以通过以下方

    2024年02月16日
    浏览(30)
  • Java笔记(集合、散列表、Map、泛型)

    set:无序不可重复 无序:不保证有序,就是有可能有序,有可能无序 不可重复:不能添加重复数据 HashSet TreeSet:底层是红黑树,会自动排序,意味着里面存储的必须是同类型的元素对象 数字:从小到大排序 字符串:一次比较每一位的ascll码值 日期:自然日期顺序 1.1.TreeS

    2024年02月19日
    浏览(33)
  • Java8 - 将 List 集合转为 Map

    1. 将List转为Map:key=userId, value=name 输出: 2. 将List转为Map:key=userId, value=User对象 输出: 3. 重复的 key 处理 如果出现相同的key,那么会抛出重复key的异常,比如我们将userId为3的修改为2,则会和第二个用户冲突: 抛出异常: Collectors.toMap支持第三个参数,对重复值进行选取:

    2024年02月08日
    浏览(58)
  • Java-集合框架-List,Set,Map,队列

    Java集合框架是一组用于存储和操作数据的类和接口。它提供了不同类型的集合,如List,Set,Map和队列,以满足不同的需求。 List:有序的集合,允许重复的元素。 Set:无序的集合,不允许重复的元素。 Map:键值对的集合,每个元素都包含一个键和一个值。 队列:先进先出(

    2024年02月11日
    浏览(38)
  • Java的集合类:List、Set、Map

    在 Java 中,集合类是一组有序或无序的数据元素的集合。Java 集合类可用于存储和操作各种数据类型的元素,如整数、字符串、对象等。集合类是动态的,可以在运行时根据需要调整其大小。 Java 集合类可以分为三类: List - 有序集合,允许重复元素 Set - 无序集合,不允许重

    2024年02月16日
    浏览(36)
  • Java中Map集合初始化并赋值

    Java中Map集合初始化并赋值的几种方式:

    2024年02月11日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包