抛出问题

假如有两组数据,这六个人去参加非诚勿扰,需要做一个配对。数据如下:

List<User> usersA = new ArrayList<>();usersA.add(new User("1", "吕布", "10"));usersA.add(new User("2", "刘备", "11"));usersA.add(new User("3", "孙悟空", "12"));List<User> usersB = new ArrayList<>();usersB.add(new User("10", "貂蝉", "1"));usersB.add(new User("11", "孙尚香", "2"));usersB.add(new User("12", "紫霞", "3"));

比如 usersA.add(new User("1", "吕布", "10"));

1是吕布自己的ID,10是配对方的ID。假设现在有个需求,需要返回一个结果集,返回“吕布-貂蝉”这样的数据。首先想到的肯定就是双层for,这简直就是理所当然的事情。

int loopCount = 0;
for(User userA : usersA) {for(User userB : usersB) {loopCount++;          if(userB.getUid().equals(userA.getCoupleId())) {System.out.println( String.format("%s-%s",userA.getUname(),userB.getUname()));}}
}

结果:

吕布-貂蝉
刘备-孙尚香
孙悟空-紫霞
一共循环9次

逻辑清晰,简单易懂,完全没有问题。

优化1

一个最简单的优化思路就是,比如吕布已经找到了貂蝉,那么应该立刻跳出循环才对。因为吕布已经找到貂蝉了,就没必要再去找孙尚香。int loopCount = 0;

int loopCount = 0;
for(User userA : usersA) {for(User userB : usersB) {loopCount++;          if(userB.getUid().equals(userA.getCoupleId())) {System.out.println( String.format("%s-%s",userA.getUname(),userB.getUname()));break;}}
}

加一个break就完事儿了。

吕布-貂蝉
刘备-孙尚香
孙悟空-紫霞
一共循环6次

从9次减少到6次,非常大的提升。

优化2

纳尼,还能优化?肯定的,比如吕布匹配到貂蝉后,下一个循环,刘备还是会匹配到貂蝉,这就不合理,所以不妨把匹配到的对象直接从List删去,就不会出现重复匹配的情况了。

非诚勿扰的规则也是,牵手成功后就直接下场了,不会继续留在舞台上。所以,加一个remove操作就很有必要。

for(User userA : usersA) {for(User userB : usersB) {loopCount++;if(userB.getUid().equals(userA.getCoupleId())) {System.out.println( String.format("%s-%s",userA.getUname(),userB.getUname()));usersB.remove(userB);break;}}}

我靠,直接到3次了,这肯定是最优解了吧?然而,并不是。因为List里面user的顺序是正好的,吕布对貂蝉,刘备对孙尚香,猴子对露娜。

可实际情况,哪有这么巧合的事情??

比如我随便打乱一下顺序,就不同了。

List<User> usersB = new ArrayList<>();usersB.add(new User("12", "紫霞", "3"));usersB.add(new User("10", "貂蝉", "1"));usersB.add(new User("11", "孙尚香", "2"));

这样的结果就是循环5次,那如果数据更多呢?比如第一个数据要匹配到最后一个才对得上,那效率也就太低了。

优化3

虽然用for循环给人感觉是天经地义,但是不妨换个思路,男嘉宾为什么非要一个个去找呢,比如吕布,一眼扫过去看到貂蝉,直接牵走不就完事了吗?

所以,我们可以给女嘉宾建立索引,最简单的办法就是用Map。

int loopCount = 0;Map<String, String> usersMap = new LinkedHashMap<String, String> ();
for (User userB : usersB) {loopCount++;usersMap.put(userB.getUid(), userB.getUname());}
for (User userA : usersA) {loopCount++;System.out.println(String.format("%s-%s", userA.getUname(), usersMap.get(userA.getCoupleId())));}

结果:

吕布-貂蝉
刘备-孙尚香
孙悟空-紫霞
一共循环6次

假如两个列表的长度分别是m和n,那么不管其中的顺序如何,循环的深度永远是固定的m+n。虽然还是比不上上面的最佳情况n次,但是当m和n特别大的时候,效率就立刻突显出来了。

当然了,因为用了Map,牺牲了一点点内存,算是空间换时间吧。

实际应用场景

项目中的实际应用有很多,比如数据字典,很多项目会在SpringContext启动的时候,就把字典表加载到内存。当出现表字段需要做转换的时候,直接查表,效率非常可观。(和left join比起来)

比如,我有一个xml:

<grid id="grid0" class="com.service.UserService" method="getList" parameters="" resulttype="com.answer.entity.User"> <column id="uid">用户编号</column> <column id="uname">用户名称</column> <column id="role"  datadic="role">角色</column> </grid> 

这是自定义的标签,可以通过反射,xml解析的方式做一个小型的解析框架。用到了jsoup,做一个测试类:

public class JspTest {public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {Map<String, Map<String, Object>> datadics = new HashedMap();Map<String, Object> roleDict = new HashedMap();roleDict.put("1", "射手");roleDict.put("2", "法师");datadics.put("role", roleDict);File file = new File("D:\\eclipse-mars\\workspace2\\answer\\WebContent\\table.xml");Document doc = Jsoup.parse(file, "UTF-8");Elements grids = doc.getElementsByTag("grid");List<String> colums = new ArrayList<String>();List<List<Object>> rows = new ArrayList<List<Object>>();for (Iterator<Element> iterator = grids.iterator(); iterator.hasNext(); ) {Element grid = (Element) iterator.next();String className = grid.attr("class");String method = grid.attr("method");String resultType = grid.attr("resultType");Class<?> clazz = Class.forName(className);Class resultClass = Class.forName(resultType);Method method2 = clazz.getMethod(method);List result = (List) method2.invoke(clazz.newInstance());Elements columns = grid.getElementsByTag("column");int index = 0;for (int i = 0; i < result.size(); i++) {Element e = (Element) columns.get(i);String colName = e.text();colums.add(colName);List row = new ArrayList<>();rows.add(row);Object object = result.get(index++);for (int j = 0; j < columns.size(); j++) {String id = columns.get(j).attr("id");String DATADIC = columns.get(j).attr("DATADIC");Map<String, Object> map = datadics.get(DATADIC);Object fieldValue = null;fieldValue = ReflectUtil.getFieldValue(object, id);if (map != null) {fieldValue = map.get(String.valueOf(fieldValue));}rows.get(i).add(fieldValue);}}}StringBuffer sb = new StringBuffer("\n");for (Iterator iterator = colums.iterator(); iterator.hasNext(); ) {String column = (String) iterator.next();sb.append("");}sb.append("\n");for (Iterator iterator = rows.iterator(); iterator.hasNext(); ) {List<Object> row = (List<Object>) iterator.next();sb.append("");for (Iterator iterator2 = row.iterator(); iterator2.hasNext(); ) {Object string = iterator2.next();sb.append("");}sb.append("");sb.append("\n");}sb.append("");sb.append(column);sb.append("");sb.append(string);sb.append("");grids.get(0).replaceWith(Jsoup.parse(sb.toString()).body());System.out.println(doc);FileUtil.writeString(doc.toString(), new File("D:\\eclipse - mars\\workspace2\\answer\\WebContent\\table.html "), " GBK ");}
}

最终生成一个html,效果如下:

用户编号

用户名称

角色

001

鲁班七号

射手

002

后裔

射手

001

张良

法师

其中,角色已经默认用字典转化了,很多框架内部应该是做了类似的事情。当然,主要是一些老的框架,毕竟现在还在用jsp标签的系统已经不多了。

从非诚勿扰看数据索引,优化代码小妙招相关推荐

  1. 关于MySQL索引知识与小妙招 — 学到了!

    一.索引基本知识 1.1 索引的优点 大大减少了服务器需要扫描的数据量,加快数据库的检索速度 帮助服务器避免排序和临时表 将随机io变成顺序io 1.2 索引的用处 速查找匹配WHERE子句的行 从c ...

  2. mysql 主表某一列 小于某一个表的两列之和_关于MySQL索引知识与小妙招

    1.1 索引的优点 大大减少了服务器需要扫描的数据量,加快数据库的检索速度 帮助服务器避免排序和临时表 将随机io变成顺序io 1.2 索引的用处 速查找匹配WHERE子句的行 从considerat ...

  3. 使用pickle模块序列化数据,优化代码

    使用pickle模块序列化数据,优化代码 pickle是Python标准库中的一个二进制序列化和反序列化库. 可以以二进制的形式将数据持久化保存到磁盘文件中.可以将数据和代码分离,提高代码可读性和优雅 ...

  4. method=post 怎么让查看源代码看不到_网站文档不能复制怎么办?教你3个小妙招,1分钟轻松化解...

    不知道大家平常在查找资料时,碰到网页资料不能下载时,是怎么样进行处理的.那么笔者今天就来分享我查找不能复制文档时,所用的3个小妙招,帮助轻松化解,一起来看看吧. 1.保存网页 当我们遇到一个不能直接复 ...

  5. 计算机配置文章,看电脑配置的“两个”小妙招!

    原标题:看电脑配置的"两个"小妙招! 我们常说电脑配高配置低还是怎么怎么样,对于很多使用电脑的人来说他们并不知道这是指什么,也不明确配置高低是如何看的.今天小编就跟大家科普一下电脑 ...

  6. 手机浏览器源代码_网页内容无法复制,下面几个小妙招也许能帮到你,快快收藏吧|插件|源代码|代码...

    很多时候想偷懒考些文字做做模板,但是发现居然无法复制,是不是很讨厌,那么笔者就来分享3个小妙招,来帮大家解决这个小问题吧! 方法一:OCR识别 PC及手机都有OCR识别软件,有免费也有付费,部分手机还 ...

  7. 手机节省流量的小妙招,2种方法都能够节省不少,看完记得分享哦

    手机节省流量的小妙招,2种方法都能够节省不少,看完记得分享哦 我们在使用手机时,是不是会遇到手机流量不够用的情况,没有流量无法上网的日子,真的还是很难受的,那么今天小酱就和大家分享两种节省流量的小妙招 ...

  8. 意想不到的前端三个小妙招

    大厂面试题分享 面试题库 前端面试题库 (面试必备) 推荐:★★★★★ 地址:前端面试题库 整理下本人在工作中撸代码遇到的一些刚看时一脸懵逼,实则很简单就能解决的小妙招,希望对大家有所帮助哟~ 伪元素 ...

  9. 弘辽科技:新手小白不能错过的引入手淘流量小妙招!

    原标题<弘辽科技:新手小白不能错过的引入手淘流量小妙招!> 随着物质水平的提高,人们越来越喜欢在手机上网购,这非常的快捷方便,所以网店商家们都希望自己的店铺引入更多的手淘流量,提升自己店铺 ...

最新文章

  1. Tomcat 集群中 实现session 共享的三种方法
  2. webRTC开启摄像头
  3. js实现页面跳转重定向的几种方式
  4. 微服务跨数据库联合查询_MySQL数据库联合查询
  5. 胃癌2019csco指南_2019 CSCO胃癌诊疗指南精华来了!
  6. MyBatis自学(1):MyBatis概述
  7. 被字句15个_文旅部重新认定国级非遗保护单位,潮州15项花落谁家?这些非遗你都认得吗?...
  8. mysql线程挣用问题_MySQL 并发线程的理解
  9. WPF快速入门系列(9)——WPF任务管理工具实现
  10. cad墙线打断lisp_autocad 2010怎么打断墙线?
  11. 数据仓库与数据挖掘的个人总结
  12. 云课堂智慧职教自动签到
  13. 屏幕录制大师转换方法
  14. NAT穿透技术简介和实现方案分析
  15. 使用CentOS7搭建Nat64服务器实现IPv6网段访问IPv4地址
  16. 什么是 A 轮融资?有 B轮 C轮么?
  17. Charles一键设置Breakpoint(断点)
  18. 医院HIS系统运维工作见闻
  19. Fedora 安装VBoxGuestAdditions
  20. usaco training 4.4.1 Shuttle Puzzle 题解

热门文章

  1. **懒得给孩子讲故事怎么办**
  2. 考研从机械到计算机难吗,考研机械真的不行吗?
  3. 功能测试VS性能测试
  4. 免费公共DNS的IP地址
  5. 美国某超市销售数据分析
  6. sencha app watch php,Sencha Touch构建移动端App
  7. css3 calc的使用
  8. Arduino零基础入门
  9. AtCoder Beginner Contest 182----E. Akari
  10. 关于苹果手机iFiles文件管理使用方法