文档章节

Java 容器 & 泛型:五、HashMap 和 TreeMap的自白

泥瓦匠BYSocket
 泥瓦匠BYSocket
发布于 2015/05/05 12:43
字数 1316
阅读 1674
收藏 100

Writer:BYSocket(泥沙砖瓦浆木匠)

微博:BYSocket

豆瓣:BYSocket

Java 容器的文章这次应该是最后一篇了:Java 容器 系列。 今天泥瓦匠聊下 Maps。

一、Map回顾

    Map,又称映射表,是将键映射到值的对象。有四种实现Map接口并且经常使用的Map集合为:HashMap,TreeMap,Hashtable 和 LinkedHashMap.

泥瓦匠记忆宫殿:

    1、一个映射不包含重复的键

    2、每个键最多只能映射到一个值。

MapClassHierarchy-600x354

二、HashMap

    HashMap是基于哈希表的Map接口的实现。其对键进行散列,散列函数只能作用于键。下面模拟下,公司员工和找员工的例子:

import java.util.HashMap;
import java.util.Map;
 
class Employee
{}
 
public class HaspMap01
{
    public static void main(String[] args)
    {
        Map<String, Employee> employees = new HashMap<String, Employee>();
        employees.put("1206010035", new Employee());
        System.out.println(employees);
         
        String number = "1206010035";
        System.out.println(employees.get(number));
    }
}

?Run一下,大家可以见到结果:put方法,可以将键值映射添加进表。get方法则返回指定键所映射的值。从他们 hashCode 可以看出是同一个对象。

    HaspMap的键必须唯一,同样其同一个键不能存放两个值,如果对同一个键两次调用put方法,第二个值会取代第一个值。同样是允许使用 null 值和 null 键。下面泥瓦匠用一个简单的例子解释下:

package javaBasic.collection.map;
 
import java.util.HashMap;
import java.util.Map;
 
 
public class HaspMap02
{
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public static void main(String[] args)
    {
        Map map = new HashMap<String, String>();
        map.put(null, "null01");
        map.put(null, "null02");
        System.out.println(map);
        System.out.println(map.get(null));
    }
}

 

结果如下:

{null=null02}
null02

 

由此可见,第一个值被第二个值所替换了。

下面有三点是HashMap重要之处:

1、HashMap的构造函数

   HaspMap构造函数涉及两个参数:初始容量和加载因子。初试容量是哈希表创建时的其中桶的含量。加载因子是哈希表在其容量自动增加之前可以达到多满的一种尺度。这两个参数都是影响HashMap的性能。默认构造一个具有默认初始容量 (16) 和默认加载因子 (0.75)。默认加载因子 (.75) 在时间和空间成本上是一种折衷的考虑。

2、和上次总结的Set都差不多,这个HashMap线程是不安全不同步的。如果想防止意外发生,则设置成同步即可:

Map m = Collections.synchronizedMap(new HashMap(...));

 

3、不同步的话,意味着存在快速失败导致的并发修改异常。

下面看一个复杂例子:

package javaBasic.collection.map;
 
import java.util.HashMap;
import java.util.Map.Entry;
 
class A
{
    public boolean equals(Object obj)
    {
        return true;
    }
}
 
class B
{
    public int hashCode()
    {
        return 1;
    }
}
 
class C
{
    public int hashCode()
    {
        return 2;
    }
 
    public boolean equals(Object obj)
    {
        return true;
    }
}
 
public class HashMap03
{
    public static void main(String[] args)
    {
        HashMap<A, Integer> hashMapA = new HashMap<A, Integer>();
        hashMapA.put(new A(), 10);
        hashMapA.put(new A(), 5);
         
        System.out.println("HashMapA Elements:");
        System.out.print("\t" + hashMapA + "\n");
         
        // loop HashMapA
        for(Entry<A, Integer> entryA : hashMapA.entrySet())
        {
            System.out.println(entryA.getKey().toString()+"-"+entryA.getValue());
        }
         
        HashMap<B, Integer> hashMapB = new HashMap<B, Integer>();
        hashMapB.put(new B(), 10);
        hashMapB.put(new B(), 5);
         
        System.out.println("HashMapB Elements:");
        System.out.print("\t" + hashMapB + "\n");
         
        // loop HashMapB
        for(Entry<B, Integer> entryB : hashMapB.entrySet())
        {
            System.out.println(entryB.getKey().toString()+"-"+entryB.getValue());
        }
         
        HashMap<C, Integer> hashMapC = new HashMap<C, Integer>();
        hashMapC.put(new C(), 10);
        hashMapC.put(new C(), 5);
         
        System.out.println("HashMapC Elements:");
        System.out.print("\t" + hashMapC + "\n");
         
        // loop HashMap
        for(Entry<C, Integer> entryC : hashMapC.entrySet())
        {
            System.out.println(entryC.getKey().toString()+"-"+entryC.getValue());
        }
    }
}

 

运行一下,可以看到以下结果:


由此可见,其中和 Java 容器 & 泛型:三、HashSet,TreeSet 和 LinkedHashSet比较 中涉及的知识点一致:

集合判断两个元素相等不单单是equals方法,并且必须hashCode()方法返回值也要相等。


三、TreeMap

    TreeMap使v用树结构实现(红黑树),集合中的元素进行排序,但是添加、删除和包含的算法复杂度为O(log(n))。其实Map特性基本都是一致的,比如看下面的简单例子:

 public class TreeMap01
{  
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public static void main(String[] args)
    {
        Map map = new TreeMap();
        map.put("1", "1");
        map.put("4", "4");
        map.put("2", "2");
        map.put("2", "3");
        System.out.println(map);
    }
}

 

结果如下:

{1=1, 2=3, 4=4}

 

从中我们可以看出

1、TreeMap实现了SortedMap,顾名思义,其表示为有排序的集合。

2、同样其同一个键不能存放两个值,如果对同一个键两次调用put方法,第二个值会取代第一个值。

四、总结

HashMap与TreeMap
      1、HashMap通过hashcode对其内容进行快速查找,而TreeMap中所有的元素都保持着某种固定的顺序,如果你需要得到一个有序的结果你就应该使用TreeMap(HashMap中元素的排列顺序是不固定的)。HashMap中元素的排列顺序是不固定的)。
      2、  HashMap通过hashcode对其内容进行快速查找,而TreeMap中所有的元素都保持着某种固定的顺序,如果你需要得到一个有序的结果你就应该使用TreeMap(HashMap中元素的排列顺序是不固定的)。集合框架”提供两种常规的Map实现:HashMap和TreeMap (TreeMap实现SortedMap接口)。
      3、在Map 中插入、删除和定位元素,HashMap 是最好的选择。但如果您要按自然顺序或自定义顺序遍历键,那么TreeMap会更好。使用HashMap要求添加的键类明确定义了hashCode()和 equals()的实现。 这个TreeMap没有调优选项,因为该树总处于平衡状态。

Writer:BYSocket(泥沙砖瓦浆木匠)

微博:BYSocket

豆瓣:BYSocket

© 著作权归作者所有

泥瓦匠BYSocket

泥瓦匠BYSocket

粉丝 945
博文 169
码字总数 219665
作品 4
杭州
程序员
私信 提问
泥沙砖瓦浆木匠/java-core-learning-example

感谢赞助的ta们 Java 核心系列教程,关于Java核心技术学习积累的例子,是初学者及核心技术巩固的最佳实践。 包括基础语法,OOP,字符串,集合,IO,反射,线程,网络等。 未完成模块:阿里J...

泥沙砖瓦浆木匠
04/02
0
0
再谈Java数据结构—分析底层实现与应用注意事项

在回顾js数据结构,写《再谈js对象数据结构底层实现原理-object array map set》系列的时候,在来整理下java的数据结构。 java把内存分两种:一种是栈内存,另一种是堆内存 基本类型在栈区分...

zhoulujun
05/17
31
0
【目录导航】JAVA零基础进阶之路

【JAVA零基础入门系列】(已完结)导航目录 Day1 开发环境搭建 Day2 Java集成开发环境IDEA Day3 Java基本数据类型 Day4 变量与常量 Day5 Java中的运算符 Day6 Java字符串 Day7 Java输入与输出...

MFrank
2018/06/21
0
0
Java 容器 & 泛型:一、认识容器

Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket 容器是Java语言学习中重要的一部分。泥瓦匠我的感觉是刚开始挺难学的,但等你熟悉它,接触多了,也就“顺理成章”地知道...

泥沙砖瓦浆木匠
2015/03/13
516
2
Java容器详解(以Array Arrays ArrayList为例)

//先记录一个想法……java实在是太臃肿了,纯面向对象也有不少弊端…… //能不能把java精简一下啊! 先上结论:   Array:认真看api索引的话,Array有两个。一个是sql中的接口,一个是类,...

群星纪元
04/01
16
0

没有更多内容

加载失败,请刷新页面

加载更多

只需一步,在Spring Boot中统一Restful API返回值格式与统一处理异常

统一返回值 在前后端分离大行其道的今天,有一个统一的返回值格式不仅能使我们的接口看起来更漂亮,而且还可以使前端可以统一处理很多东西,避免很多问题的产生。 比较通用的返回值格式如下:...

晓月寒丶
昨天
59
0
区块链应用到供应链上的好处和实际案例

区块链可以解决供应链中的很多问题,例如记录以及追踪产品。那么使用区块链应用到各产品供应链上到底有什么好处?猎头悬赏平台解优人才网小编给大家做个简单的分享: 使用区块链的最突出的优...

猎头悬赏平台
昨天
28
0
全世界到底有多少软件开发人员?

埃文斯数据公司(Evans Data Corporation) 2019 最新的统计数据(原文)显示,2018 年全球共有 2300 万软件开发人员,预计到 2019 年底这个数字将达到 2640万,到 2023 年达到 2770万。 而来自...

红薯
昨天
65
0
Go 语言基础—— 通道(channel)

通过通信来共享内存(Java是通过共享内存来通信的) 定义 func service() string {time.Sleep(time.Millisecond * 50)return "Done"}func AsyncService() chan string {retCh := mak......

刘一草
昨天
58
0
Apache Flink 零基础入门(一):基础概念解析

Apache Flink 的定义、架构及原理 Apache Flink 是一个分布式大数据处理引擎,可对有限数据流和无限数据流进行有状态或无状态的计算,能够部署在各种集群环境,对各种规模大小的数据进行快速...

Vincent-Duan
昨天
60
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部