草庐IT

【Java】Map介绍和使用

爱躺平的威威 2023-09-03 原文

目录

【1】Map使用场景

【2】概念

【3】Map 的常用方法

【4】关于Map.Entry的说明

1、Map.Entry的作用

2、Map.Entry中的常用方法

3、使用Map.Entry遍历Map集合 

【5】简单介绍 TreeMap和HashMap

1、TreeMap

2、HashMap

3、TreeMap和HashMap的区别 


【1】Map使用场景

        Map是一种专门用来进行搜索的容器或者数据结构,其搜索的效率与其具体的实例化子类有关。对于静态类型的查找来说,一般直接遍历或者用二分查找【不会对区间进行插入和删除操作】

     而在现实生活中的查找比如:

  1. 根据姓名查询考试成绩
  2. 通讯录,即根据姓名查询联系方式
  3. 不重复集合,即需要先搜索关键字是否已经在集合中     

  以上等可能在查找时进行一些插入和删除的操作,即动态查找,就需要用Map进行一系列操作。

注:Map最重要的特性就是去重!

        当我们平常在做题时,遇到删除重复数据,或者找每个数据重复的此时等..都可以用Map来解决

【2】概念

Map是一个接口类,该类没有继承自Collection,该类中存储的是<K,V>结构的键值对,并且K一定是唯一的,不能重复

<K,V>使用的是 key-value模型:

key-value 模型中 key 和 value 是一个整体,就类似于 我们一提起齐天大圣,就想起孙悟空。key-value模型就是类似于这样的一组组合。【key 和 value 互相修饰】 

Map使用时一些注意点:
  1. Map是一个接口,不能直接实例化对象,如果要实例化只能实例化其实现类TreeMap或者HashMap。
  2. Map 中存放键值对的 Key 是唯一的, value 是可以重复的
  3. Map 中的 Key 可以全部分离出来,存储到 Set 来进行访问 ( 因为 Key 不能重复 )
  4. Map 中的 value 可以全部分离出来,存储在 Collection 的任何一个子集合中 (value 可能有重复 )
  5. Map 中键值对的 Key 不能直接修改, value 可以修改,如果要修改 key ,只能先将该 key 删除掉,然后再来进行重新插入。

 【3】Map 的常用方法

方法解释
V get(Object key)返回 key 对应的 value
V getOrDefault(Object key, V defaultValue)返回 key 对应的 value,key 不存在,返回默认值
V put(K key, V value)设置 key 对应的 value
V remove(Object key)删除 key 对应的映射关系
Set<K> keySet()返回所有 key 的不重复集合
Collection<V> values()返回所有 value 的可重复集合
Set<Map.Entry<K, V>> entrySet()返回所有的 key-value 映射关系
boolean containsKey(Object key)判断是否包含 key
boolean containsValue(Object value)判断是否包含 value

 Map是接口类,不能实例化对象,所以只能实例化其实现类TreeMap或者HashMap

以下以TreeMap为例

1、put方法 设置 key 对应的 value【放置元素】

    public static void main(String[] args) {
        Map<String,Integer> map = new TreeMap<>();

        map.put("abc",10);
        map.put("hello",20);
        map.put("hhf",23);
        System.out.println(map);//Map类重写了toString方法
        map.put("abc",20);//修改"abc"对应的value值
        System.out.println(map);
    }

2、get方法 返回 key 对应的值,key不存在则返回null 

    public static void main(String[] args) {
        Map<String,Integer> map = new TreeMap<>();

        map.put("abc",10);
        System.out.println(map.get("abc"));//10
        System.out.println(map.get("key"));//null
    }

3、getOrDefault 方法 返回 key 对应的 value,key 不存在,返回默认值

    public static void main(String[] args) {
        Map<String,Integer> map = new TreeMap<>();

        map.put("abc",10);
        System.out.println(map.getOrDefault("abc", 19));//找到key值,则返回对应的value,输出10
        System.out.println(map.getOrDefault("hello",20));//未找到key值,则返回默认值,输出20
    }

4、remove 删除 key 对应的映射关系

    public static void main(String[] args) {
        Map<String,Integer> map = new TreeMap<>();

        map.put("abc",10);
        map.put("hello",20);
        map.put("hhf",23);
        System.out.println(map);
        map.remove("abc");
        System.out.println(map);
    }

5、Set<K> keySet()  返回所有 key 的不重复集合,不包含value

    public static void main(String[] args) {
        Map<String,Integer> map = new TreeMap<>();

        map.put("abc",10);
        map.put("hello",20);
        map.put("hhf",23);
        map.put("world",20);

        Set<String> set = map.keySet();
        System.out.println(set);

    }

 

'<V>'中V为 key的包装类型

set 中使用的模型是 key模型。

 6、Collection<V> values() 返回所有 value 的可重复集合

    public static void main(String[] args) {
        Map<String,Integer> map = new TreeMap<>();

        map.put("abc",10);
        map.put("hello",20);
        map.put("hhf",23);
        map.put("world",20);
        Collection<Integer> list = map.values();
        System.out.println(list);

    }

 '<V>'中V为 value 的包装类型

7、Set<Map.Entry<K, V>> entrySet() 返回所有的 key-value 映射关系【重要】

entrySet方法能把TreeMap中的键值对打包,放入Set集合中。

    public static void main(String[] args) {
        Map<String,Integer> map = new TreeMap<>();
        map.put("abc",10);
        map.put("hello",20);
        map.put("hhf",23);

       Set<Map.Entry<String,Integer>> entrySet = map.entrySet();

    }

 上述代码中,map调用entrySet方法,把其内部的值全部打包为  Map.Entry<String,Integer> 类型,然后存储在 entrySet 变量中。

8、boolean containsKey(Object key) 判断是否包含 key

    public static void main(String[] args) {
        Map<String,Integer> map = new TreeMap<>();
        map.put("abc",10);
        map.put("hello",20);
        map.put("hhf",23);

        System.out.println(map.containsKey("hello"));// true
        System.out.println(map.containsKey("world"));// fasle

    }

9、boolean containsValue(Object value) 判断是否包含 value

    public static void main(String[] args) {
        Map<String,Integer> map = new TreeMap<>();
        map.put("abc",10);
        map.put("hello",20);
        map.put("hhf",23);

        System.out.println(map.containsValue(20));// true
        System.out.println(map.containsValue(50));// false
    }

【4】关于Map.Entry<K, V>的说明

         Map.Entry<K, V> 是Map内部实现的用来存放<key, value>键值对映射关系的内部类 

Entry是Map接口里面的接口

 所以 TreeMap类实现Map接口时,也会具体实现Entry接口,HashMap内部也是如此

1、Map.Entry的作用

        Map.Entry是为了更方便的输出Map键值对。一般情况下,要输出Map中的key 和 value  是先得到key的集合keySet(),然后再迭代(循环)由每个key得到每个value。values()方法是获取集合中的所有值,不包含键,没有对应关系。而Entry可以一次性获得这两个值。

2、Map.Entry中的常用方法

方法解释
K getKey()返回 entry 中的 key
V getValue()返回 entry 中的 value
V setValue(V value)将键值对中的value替换为指定value/2、

这些方法都会结合着for循环进行操作,具体使用往下看 

3、使用Map.Entry遍历Map集合 

    public static void main(String[] args) {
        Map<String,Integer> map = new TreeMap<>();
        map.put("abc",10);
        map.put("hello",20);
        map.put("hhf",23);

        Set<Map.Entry<String,Integer>> entrySet = map.entrySet();
        for(Map.Entry<String,Integer> entry : entrySet){
            System.out.println("key: "+entry.getKey()+" value: "+entry.getValue());
        }
    }

【5】简单介绍 TreeMapHashMap

1、TreeMap

TreeMap底层是一颗搜索树。而搜索树的插入是需要比较大小的,而TreeMap通过key来比较大小!所以key一定是编译器可以自动比较大小的。

    public static void main(String[] args) {
        Map<Integer,Integer> map1 = new TreeMap<>();
        Map<String,Integer> map2 = new TreeMap<>();
        map1.put(2,5);
        map1.put(1,9);
        map1.put(10,4);
        
        map2.put("hello",2);
        map2.put("world",20);
        map2.put("weiwei",35);

        System.out.println(map1);
        System.out.println(map2);
    }

当我们实现TreeMap类后,往里面传入自定义类就会报错!

 所以,要想放入自定义类型,就要满足一下两个条件之一

        1.自定义类型要实现Comparable ,重写compareTo

class People implements Comparable{
    public int age;
    public int money;

    @Override
    public int compareTo(Object o) {
        return 0;
    }
}

public class Test3 {
    public static void main(String[] args) {
       Map<People,Integer> map = new TreeMap<>();
        map.put(new People(),10);
        System.out.println(map);
    }
}

 

        2.实例化对象时传入一个比较器

class People implements{
    public int age;
    public int money;

}

public class Test3 {
    public static void main(String[] args) {
       Map<People,Integer> map = new TreeMap<>(new Comparator<People>() {
           @Override
           public int compare(People o1, People o2) {
               return 0;
           }
       });
        map.put(new People(),10);
        System.out.println(map);
    }
}

 以上两种方法,其实都是在告诉集合,自定义类型如何比较大小

同时不能放null,否则就会报错

如果两次put的key值一样,那么val值就会被替换掉

2、HashMap

         HashMap底层是一颗红黑树,存储的无序的,所以自定义类型和null都能直接存储,不会报错。 

3、TreeMap和HashMap的区别 

 TreeMap 和 HashMap 底层实现逻辑不同,所以插入时间、删除时间、插入方法等都不相同

具体如下:

Map底层结构TreeMapHashMap
底层结构红黑树哈希桶
插入/删除/查找时间
复杂度
O(1)
是否有序关于Key有序无序
线程安全不安全不安全
插入/删除/查找区别需要进行元素比较通过哈希函数计算哈希地址
比较与覆写key必须能够比较,否则会抛出
ClassCastException异常
自定义类型需要覆写equals和
hashCode方法
应用场景需要Key有序场景下Key是否有序不关心,需要更高的
时间性能

有关【Java】Map介绍和使用的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  4. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  5. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  6. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  7. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  8. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  9. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  10. ruby - 在 64 位 Snow Leopard 上使用 rvm、postgres 9.0、ruby 1.9.2-p136 安装 pg gem 时出现问题 - 2

    我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po

随机推荐