在我的上一篇文章中,讲到了我自己初步认识 HashMap 的一个经验分享:HashMap 浅析 —— LeetCode Two Sum 刷题总结。作为一个 CRUD 工程师,平时很少接触到基础组件的涉及,那么是不是很难有机会用到 HashMap 呢?

今天,就举一个常见的查询例子,来看看我们如何使用 HashMap 来提高代码的效率。

已知一个 Student 类:

public class Student {

private Long id;

private String name;

public Student(Long id, String name) {

this.id = id;

this.name = name;

}

// ---Getters And Setters---

}

和一个 Score 类:

public class Score {

private Long studentId;

private String mathScore;

private String englishScore;

public Score(Long studentId, String mathScore, String englishScore) {

this.studentId = studentId;

this.mathScore = mathScore;

this.englishScore = englishScore;

}

// ---Getters And Setters---

}

我们需要把 Student 和 Score 合并到一起,即类 Report:

public class Report {

private Long studentId;

private String studentName;

private String mathScore;

private String englishScore;

public Report(Long studentId, String studentName, String mathScore, String englishScore) {

this.studentId = studentId;

this.studentName = studentName;

this.mathScore = mathScore;

this.englishScore = englishScore;

}

}

看类的属性我们就明白了,这里其实相当于在 Student 和 Score 之间做一个 Join,得到 Report。这是我们在编程中常见的场景(例如查询了订单中心,用户中心,支付中心,合并各个中心返回的结果形成一个表单,因为各个中心是独立的微服务,无法使用 SQL JOIN)。

现有两个 List:List 和 List:

List students = Arrays.asList(

new Student(1L, "Angle"),

new Student(2L, "Baby")

);

List scores = Arrays.asList(

new Score(1L, "90", "87"),

new Score(2L, "92", "78")

);

在学会使用 HashMap 之前,我可能会做一次双重循环:

List reports = new ArrayList<>();

for (Student student : students) {

for (Score score : scores) {

if (!student.getId().equals(score.getStudentId())) {

continue;

}

reports.add(

new Report(student.getId(), student.getName(), score.getMathScore(), score.getEnglishScore())

);

break;

}

}

时间复杂度最差的情况下是O(n * m)。

但是使用 HashMap 来改善程序,就能得到不错的效果:

Map map = new HashMap<>();

for (Student student : students) {

map.put(student.getId(), student);

}

List reports = new ArrayList<>();

for (Score score : scores) {

Student student = map.get(score.getStudentId());

if(student == null){ // 避免 NPE

continue;

}

reports.add(

new Report(student.getId(), student.getName(), score.getMathScore(), score.getEnglishScore())

);

}

双重循环,变成了两次循环,时间复杂度是O(n + m)。

显然要比前面的方法效果要好一些。笔者写了测试代码分别测试两个方法的效率,在 10w 数据下,执行时间如下:

差距好像挺大。想了解为什么 HashMap 能够得到如此好的效果,可以看我的这篇文章:HashMap 浅析 —— LeetCode Two Sum 刷题总结。如果读者有更好的解法欢迎留言交流,笔者水平有限,在算法上研究不多。

10w 数据的测试源码见下方,各位读者可以自行试验下效果:

package com.xiangyu.demo.hashmap;

import com.xiangyu.java.hashmap.Report;

import com.xiangyu.java.hashmap.Score;

import com.xiangyu.java.hashmap.Student;

import org.junit.Before;

import org.junit.Test;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

public class HashMapTest {

private List students = new ArrayList<>();

private List scores = new ArrayList<>();

@Before

public void before() {

// 每个list 里放 10w 数据

for (long i = 0; i < 100000; i++) {

students.add(new Student(i, "test"));

scores.add(new Score(i, "95", "95"));

}

}

@Test

public void TestHashMap() {

Map map = new HashMap<>();

for (Student student : students) {

map.put(student.getId(), student);

}

List reports = new ArrayList<>();

for (Score score : scores) {

Student student = map.get(score.getStudentId());

if (student == null) {

continue;

}

reports.add(

new Report(student.getId(), student.getName(), score.getMathScore(), score.getEnglishScore())

);

}

System.out.println(reports.size());

}

@Test

public void testFor2() {

List reports = new ArrayList<>();

for (Student student : students) {

for (Score score : scores) {

if (!student.getId().equals(score.getStudentId())) {

continue;

}

reports.add(

new Report(student.getId(), student.getName(), score.getMathScore(), score.getEnglishScore())

);

break;

}

}

System.out.println(reports.size());

}

}

java map join_HashMap 常见应用:实现 SQL JOIN相关推荐

  1. 第87节:Java中的Bootstrap基础与SQL入门

    第87节:Java中的Bootstrap基础与SQL入门 前言复习 什么是JQ? : write less do more 写更少的代码,做更多的事 找出所有兄弟: $("div" ...

  2. Java开发面试常见的技术问题整理

    Java开发面试常见的技术问题整理 介绍 对jvm的了解? jvm类加载机制 jvm运行时数据区||Jvm体系结构五大块 jvm自带的加载器 jvm的双亲委派模式 什么是GC jvm的垃圾回收算法 怎 ...

  3. java map set_java中Map、Set、List的简单使用教程(快速入门)

    Map.Set.List List的常用方法 1.创建 List list = new ArrayList<>(); List list = new LinkedList<>( ...

  4. 有关于Java Map,应该掌握的8个问题

    点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达 今日推荐:一个线程池 bug 引发的 GC 思考!个人原创+1博客:点击前往,查看更多 前言 最近几天看了几篇有关于Jav ...

  5. Mysql: SQL JOIN 子句详解

    SQL JOIN 子句用于把来自两个或多个表的行结合起来,基于这些表之间的共同字段. 最常见的 JOIN 类型:SQL INNER JOIN(简单的 JOIN).SQL LEFT JOIN.SQL  ...

  6. Java Map中那些巧妙的设计

    简介: 他山之石可以攻玉,这些巧妙的设计思想非常有借鉴价值,可谓是最佳实践.然而,大多数有关Java Map原理的科普类文章都是专注于"点",并没有连成"线", ...

  7. ​Java Map中那些巧妙的设计

    最近拜读了一些Java Map的相关源码,不得不惊叹于JDK开发者们的鬼斧神工.他山之石可以攻玉,这些巧妙的设计思想非常有借鉴价值,可谓是最佳实践.然而,大多数有关Java Map原理的科普类文章都是 ...

  8. Spark SQL join的三种实现方式

    引言 join是SQL中的常用操作,良好的表结构能够将数据分散到不同的表中,使其符合某种规范(mysql三大范式),可以最大程度的减少数据冗余,更新容错等,而建立表和表之间关系的最佳方式就是join操 ...

  9. java 查询sql_Java 中如何使用 SQL 查询文本

    [摘要] 使用 SQL 查询语言,你只能查询位于数据库里面的数据,但是当你面对的数据是一些 Excel 表格或者 Txt 文本格式时,有什么办法能直接对着文件进行 Select 查询呢?去乾学院看个究 ...

最新文章

  1. 手机网页H5 自适应不同分辨率的屏幕 必学标签meta之viewport
  2. JAVA基础 (二)反射 深入解析反射机制
  3. android+关闭selinux权限问题,快速解决Android中的selinux权限问题【转】
  4. php7和python3性能对比-ava、Python和PHP三者的区别
  5. C#文件夹权限操作工具类
  6. trie树java_【数据结构】Trie树的应用:查询IP地址的ISP(Java实现)
  7. Android 沉浸式状态栏 实现方式一
  8. python 获取内存使用率_Python获取CPU使用率、内存使用率、网络使用状态 | 学步园...
  9. python多进程和多线程使用场景_Python36 多线程、多进程的使用场景
  10. Java基础--成员变量和局部变量(区别、重名问题)
  11. Android 系统(124)---Android 如何快速写满存储空间
  12. 容器技术Docker K8s 27 容器服务ACK基础与进阶-监控管理
  13. pdf复制到word有空格间隙和换行问题解决办法
  14. 基于Pytorch实现人脸关键点检测模型MTCNN
  15. 10 个错过即损失的智能合约开发者工具
  16. 网页源代码保护(禁止右键、复制、另存为、查看源文件)
  17. 手把手教你做小米商城-商品展示页面
  18. 这个世界的本源不是物质,而是物质背后的基本秩序-柏拉图
  19. php 关于php时区时间错误问题 date 当前时间 时差(转载)
  20. Linux红帽认证工程师(RHCE)考试笔记(Ansible学习笔记)

热门文章

  1. 远程仓库---从远程库克隆
  2. centos升级内核
  3. Multi-Range Read (MRR)原理
  4. 听腾讯 TEG 大佬谈腾讯万亿级 Elasticsearch 技术解密
  5. PAT1049 数列的片段和 (20 分)
  6. 由于不当的执行顺序导致的死锁
  7. Scala教程之:函数式的Scala
  8. 【进程的同步和互斥,看懂这张图就够了!】
  9. python不定长参数详解
  10. 中学计算机老师的英语,中学计算机老师的路在何方?