首页 > 其他分享 >如何决定使用 HashMap 还是 TreeMap?

如何决定使用 HashMap 还是 TreeMap?

时间:2023-05-08 11:07:39浏览次数:38  
标签:map String 映射 映像 TreeMap 如何 HashMap

@[toc]

:如何决定使用 HashMap 还是 TreeMap?

介绍

TreeMap<k,v>的Key值是要求实现java.lang.Comparable,所以迭代的时候TreeMap默认是按照Key值升序排序的;TreeMap的实现是基于红黑树结构。适用于按自然顺序或自定义顺序遍历键(key)。

HashMap<k,v>的Key值实现散列hashCode(),分布是散列的、均匀的,不支持排序;数据结构主要是桶(数组),链表或红黑树。适用于在Map中插入、删除和定位元素。

结论

如果你需要得到一个有序的结果时就应该使用TreeMap(因为HashMap中元素的排列顺序是不固定的)。除此之外,由于HashMap有更好的性能,所以大多不需要排序的时候我们会使用HashMap。

拓展

1、HashMap 和 TreeMap 的实现

HashMap:基于哈希表实现。使用HashMap要求添加的键类明确定义了hashCode()和equals()[可以重写hashCode()和equals()],为了优化HashMap空间的使用,您可以调优初始容量和负载因子。

  • HashMap(): 构建一个空的哈希映像
  • HashMap(Map m): 构建一个哈希映像,并且添加映像m的所有映射
  • HashMap(int initialCapacity): 构建一个拥有特定容量的空的哈希映像
  • HashMap(int initialCapacity, float loadFactor): 构建一个拥有特定容量和加载因子的空的哈希映像

TreeMap:基于红黑树实现。TreeMap没有调优选项,因为该树总处于平衡状态。

  • TreeMap():构建一个空的映像树
  • TreeMap(Map m): 构建一个映像树,并且添加映像m中所有元素
  • TreeMap(Comparator c): 构建一个映像树,并且使用特定的比较器对关键字进行排序
  • TreeMap(SortedMap s): 构建一个映像树,添加映像树s中所有映射,并且使用与有序映像s相同的比较器排序

2、HashMap 和 TreeMap 都是非线程安全

HashMap继承AbstractMap抽象类,TreeMap继承自SortedMap接口。

AbstractMap抽象类:覆盖了equals()和hashCode()方法以确保两个相等映射返回相同的哈希码。如果两个映射大小相等、包含同样的键且每个键在这两个映射中对应的值都相同,则这两个映射相等。映射的哈希码是映射元素哈希码的总和,其中每个元素是Map.Entry接口的一个实现。因此,不论映射内部顺序如何,两个相等映射会报告相同的哈希码。

SortedMap接口:它用来保持键的有序顺序。SortedMap接口为映像的视图(子集),包括两个端点提供了访问方法。除了排序是作用于映射的键以外,处理SortedMap和处理SortedSet一样。添加到SortedMap实现类的元素必须实现Comparable接口,否则您必须给它的构造函数提供一个Comparator接口的实现。TreeMap类是它的唯一一个实现。

3、TreeMap中默认是按照升序进行排序的,如何让他降序

通过自定义的比较器来实现

定义一个比较器类,实现Comparator接口,重写compare方法,有两个参数,这两个参数通过调用compareTo进行比较,而compareTo默认规则是:

> - 如果参数字符串等于此字符串,则返回 0 值; > - 如果此字符串小于字符串参数,则返回一个小于 0 的值; > - 如果此字符串大于字符串参数,则返回一个大于 0 的值。

自定义比较器时,在返回时多添加了个负号,就将比较的结果以相反的形式返回,代码如下:

static class MyComparator implements Comparator{
    @Override
    public int compare(Object o1, Object o2) {
        // TODO Auto-generated method stub
        String param1 = (String)o1;
        String param2 = (String)o2;
        return -param1.compareTo(param2);
    }   
}

之后,通过MyComparator类初始化一个比较器实例,将其作为参数传进TreeMap的构造方法中:

MyComparator comparator = new MyComparator();

Map<string,string> map = new TreeMap<string,string>(comparator);

这样,我们就可以使用自定义的比较器实现降序了

public class MapTest {

    public static void main(String[] args) {
        //初始化自定义比较器
        MyComparator comparator = new MyComparator();
        //初始化一个map集合
        Map<string,string> map = new TreeMap<string,string>(comparator);
        //存入数据
        map.put("a", "a");
        map.put("b", "b");
        map.put("f", "f");
        map.put("d", "d");
        map.put("c", "c");
        map.put("g", "g");
        //遍历输出
        Iterator iterator = map.keySet().iterator();
        while(iterator.hasNext()){
            String key = (String)iterator.next();
            System.out.println(map.get(key));
        }
    }

    static class MyComparator implements Comparator{

        @Override
        public int compare(Object o1, Object o2) {
            // TODO Auto-generated method stub
            String param1 = (String)o1;
            String param2 = (String)o2;
            return -param1.compareTo(param2);
        }

    }

}

如何决定使用 HashMap 还是 TreeMap?_java


</string,string></string,string></string,string></string,string></k,v></k,v>

标签:map,String,映射,映像,TreeMap,如何,HashMap
From: https://blog.51cto.com/wangshiyu/6253134

相关文章

  • 在JS中如何判断两个对象是否相等
    在JavaScript中,判断两个对象是否相等有多种方法,取决于你对相等的定义以及对象属性的类型。以下是几种常见的方法: 1.严格相等运算符(===)使用===运算符可以比较两个对象是否引用同一个对象。如果两个变量引用了同一个对象,则它们是相等的,否则它们是不相等的。例如:const......
  • 列表的批量操作组件封装 + 权限 ,如何更优雅的实现呢?Vue3
    这个组件解决的问题?在以往的项目当中,我从未想过要对批量/列表数据的操作按钮做什么变动,直到最近的一次开发,让我突然觉得可以将操作按钮也做成一个公共组件,在做前端开发时,更加专注于js代码逻辑。如何使用?全局(main.js中)引用操作组件BatchOperation.vue创建页面操作按钮act......
  • 百万级数据excel导出功能如何实现
    百万级数据excel导出功能如何实现? 前言最近我做过一个MySQL百万级别数据的excel导出功能,已经正常上线使用了。这个功能挺有意思的,里面需要注意的细节还真不少,现在拿出来跟大家分享一下,希望对你会有所帮助。原始需求:用户在UI界面上点击全部导出按钮,就能导出所有商品数据。......
  • 如何在Linux中查找一个文件
    《Linux就该这么学》-必读的Linux系统与红帽RHCE认证免费自学书籍免费电子版下载地址:https://www.linuxprobe.com/book导读对于新手而言,在Linux中使用命令行可能会非常不方便。没有图形界面,很难在不同文件夹间浏览,找到需要的文件。本篇教程中,我会展示如何在Linux中查找特......
  • prompt learning如何计算损失的
    在promptlearning中,对于一个类别的多个候选词,损失函数通常会计算所有词的logit和,并与真实标签作比较。以情感分类为例:假设正面类别有两个候选词:“positive”和“optimistic”。负面类别有两个候选词:“negative”和“pessimistic”。然后模型会计算四个词的logit:logit_p......
  • 如何利用Requestly提升前端开发与测试的效率,让你事半功倍?
    痛点前端测试在进行前端页面开发或者测试的时候,我们会遇到这一类场景:在开发阶段,前端想通过调用真实的接口返回响应在开发或者生产阶段需要验证前端页面的一些异常场景或者临界值时在测试阶段,想直接通过修改接口响应来验证前端页面是否正常想验证后端服务响应比较慢的......
  • Spring中@Bean注解的作用以及如何使用
    Spring中@Bean注解的作用以及如何使用一、Bean是啥1、Java面向对象,对象有方法和属性,那么就需要对象实例来调用方法和属性(即实例化); 2、凡是有方法或属性的类都需要实例化,这样才能具象化去使用这些方法和属性; 3、规律:凡是子类及带有方法或属性的类都要加上注册Bean到SpringIo......
  • 知乎问题:如何说服技术老大用 Redis ?
    这个问题很微妙,可能这位同学内心深处,觉得Redis是所有应用缓存的标配。缓存的世界很广阔,对于应用系统来讲,我们经常将缓存划分为本地缓存和分布式缓存。本地缓存:应用中的缓存组件,缓存组件和应用在同一进程中,缓存的读写非常快,没有网络开销。但各应用或集群的各节点都需要维护自......
  • 如何自制定制化的杜邦线免费教程 All In One
    如何自制定制化的杜邦线免费教程AllInOne自制杜邦线准备工具和材料工具:剥线钳,压线钳材料:导线若干,杜邦端子和胶壳自制杜邦线母头杜邦母头端子杜邦胶壳单排(具体胶壳排数,要看自己的需求,新手推荐可以随意组合的单排)自制杜邦线公头杜邦公头端子杜邦胶壳单排(具体胶壳......
  • 如何从develop分支拉取代码,开发页面和合并提交
    我以04官网为例子,在我开发页面的时候,第一步是先切到生产分支,然后不要用vscode自带的操作,改用gitpull拉取最新代码,,此时生产的页面是这样的  我再从develop拉出一个测试分支Jenkins,以及预发布分支release,此时我的需求是这个"开发分支"改成"本地分支",页面文字统一改......