代码还是那个代码,但我已经知道了hashmap背后的东西
代码还是那个代码,但我已经知道了hashmap背后的东西
- 数据结构是链表的数组(注:后面的版本为了提升性能,已经是改成链表或者树(节点较多)了)
- 思想上是空间换时间的算法
- 构造函数上有容量和负载因子2个参数以及作用
- 决定性能的是key的hashcode是否够快、结果够分散(不分散就会变成链表的性能了),和扩容的开销(什么时候扩容,和负载因子有关)
然后写代码的时候,如果知道了最终的容量(尤其是数据量大的时候),我都会指定初始化容量,类似如下
List<SomeBean> list = doSomeThing();
Map<Integer, String> map = new HashMap<>((int)(list.size()/0.75));//0.75为默认负载因子
如果工作中某个map使用特别多,性能还需要继续优化,我就会考虑从以下方面优化
- 如果key是自己定义的对象,那么hashcode方法是否够快(最少应该缓存保证只计算一次,而且放入之后不能改变,决定hashcode的字段不能改变)? hash的结果是否够分散?
- 可以考虑调小负载因子,花更多的空间来换时间
学习源代码的时候,特别有意思,你会强烈感觉到一个词:举一反三!触类旁通!学习api使用的时候,如果你只知道使用不知道原理,很难举一反三,感觉的是死记硬背。但学习了原理之后,知识成体系后,很容易举一反三,学的越多就容易,还是以hashmap为例,我举一个hashmap反三个点。
1. 你会知道但凡有数组的数据结构,构造函数都有一个容量的初始化参数(或者说构造函数有初始化容量的可能都是数组的数据结构)。构造函数如下
public ArrayList(int initialCapacity) //LinkedList不是数组就没有
public HashMap(int initialCapacity)
public StringBuffer(int capacity)
你就会知道,数组扩容很耗性能(数据量大容易oom),尽量指定容量。
2. 算法是空间换时间,还有没有其他算法是这种思想的?你最少能找到一个桶排序。
3. 数据库的分库分表,思路和hashmap大同小异
4. 各种分布式的hash一致性算法,第一步都是创建一个最大的数组(Integer.MAX_VALUE),就是避免了hashmap最耗性能的扩容运算。
学习了hashmap之后,你很自然就会去了解其他的map,如TreeMap,LinkedHashmap(超级有用),HashTable,ConcurrentSkipListMap(算法思路很有意思),ConcurrentHashMap等,你会知道set就是用map做的,都不需要学。到了这步,map相关就可以暂告一段落。
在学习中,我发现思想上的东西是最重要的,你理解了思想,一下子就豁然开朗了,在也不需要死记硬背了。如学习CAS的时候,大家都知道这是一种指令级的免锁实现。看代码的时候,我一度疑惑为什么会有个while死循环(原谅我天资驽钝)
public final int getAndUpdate(IntUnaryOperator updateFunction) {
int prev, next;
do {
prev = get();
next = updateFunction.applyAsInt(prev);
} while (!compareAndSet(prev, next));
return prev;
}
后来从思想上理解,才知道乐观锁的概念,就是很乐观,假设你不会出错,但你要是出错了我就重试有办法给你修复,对应的就是悲观锁,就是很悲观,觉得不锁就会出错,如synchronize关键字和reentrantlock。这体现了2种不同截然不同的管理思想。这种思想经常体现在多个系统集成的设计,有些时候如果你用悲观的思想设计,实现起来很麻烦或者无法实现,但如果你用乐观的思想,减少出错条件,然后出错了能解决,代价就会小很多。
说了这么多,我想说的就是,j2ee的基础知识就是你做项目中代码背后的东西。提高自己水平的方法很简单,就是把大部分时间去了解实现原理,了解思想,让自己的知识串起来,形成体系。j2ee的知识特别多,学得人想哭,千万不要一开始把时间花在各种框架、组件的使用上,在我看来那是本末倒置。简单来说:先修内功再练招式。
我觉得重要的、工作会用得到的知识就是一个请求从前台到后台处理的过程需要用到的东西,最少包括以下点:js,html,css,ajax,ajax跨域,跨站脚本,web缓存,web优化,nginx,apache作用,鉴权方式,cookie,session,servlet,filter,基本数据结构,线程池,线程并发,缓存,io等等,知识点非常多。如你前台用jq,你应该了解他的选择器和ajax是如何实现的(其实去了解就会发现不复杂)?而不是只是会用。后台你用springmvc,你要了解他是如何工作,每一个配置是做什么,为什么?
j2ee知识点特别多,每一个都能写很多,我也在不断学习中。具体要写我还真不知道如何下手,我就列举一下我觉得基础的东西(面试的时候问的问题),有简单有难,你觉得偏可能是你没有做过这块的开发或者做得比较浅:
- map有哪些,特点和使用场景?(只知道hashmap,hashtable是不够的。。。)
- 哪些方面会影响hashmap的性能?
- 线程安全的map有哪些,concurrenthashmap是如何实现线程安全的(jdk1.8大不同)?
- 锁有哪几种?
- 公平锁,读写锁等如何实现?
- synchronize能加在哪些地方?什么区别?
- 死锁的形成条件?现在很少死锁了,很少问
- 原子数据对象的原理?
- reentrantlock相关知识,condition如何使用?(很重要的知识点,强烈推荐阅读ArrayBlockingQueue源码,教科书般)
- volatile的相关知识(内存屏障,重排)
- ThreadLocal原理和使用?(超级有用的知识点,工作中使用很多,让代码漂亮很多,后面专门开贴写)
- 多个线程同步等待?(CountDownLatch,CyclicBarrier,Semaphore信号量很多语言都有,实际上使用不是很多,线程池就可以实现大部分等待功能)
- 线程池?(种类,重要的方法,这个一般是使用层面,简单)
- 动态代理?反射?内省?(考察知识面)
- session相关知识?和cookie关系?分布式session实现原理?
- cookie相关知识?有哪些属性?(有些属性很有用,只是我们很少留意而已!)
- nginx,apache 实际项目能做哪些?(鉴权,转发,缓存,反向代理等)和tomcat什么关系?最少了解
- ajax跨域原因?解决方式?(重点知识,做SE避免不了的问题。这里很多知识点。)
- jsonp原理?后台需要改动吗?(jsonp虽然现在落伍了,但还是会问问)
- web优化知识点?(常规知识点)
- 前台缓存相关?(200cache,304,ajax缓存,如何实现缓存)
一列举就根本停不下来了。。。其他的spring框架的东西也很多,还有jvm的东西,系统集成相关,数据库相关,io做得很少也不懂问,后面再慢慢把我的学习过程和偶得写下来。很多东西我也是了解个大概,就是看看你有没有学习过,不断学习是程序员最重要的特征。
我不算高手,只能算一个合格的老程序员。这里只是说了一下自己之前学习的方向和列举了几个学习中的例子,大家见仁见智。帖子也是针对迷茫的初学者有感而发,希望能帮助到大家。
代码还是那个代码,但我已经知道了hashmap背后的东西的更多相关文章
- javascript 转盘抽奖代码和计数器代码
要介绍了javascript圆盘抽奖程序实现原理和完整代码例子,需要的朋友可以参考下 看到网页上有不少大转盘抽奖的应用,心血来潮也想弄个.于是找了点资料自己研究... 效果预览: 一.模拟抽奖的实 ...
- JSBinding+Bridge.Net:框架代码与逻辑代码的关系
在JSB+Bridge工程中你可以同时维护Cs版本和Js版本的游戏. 框架代码:简称framework,表示那些不进行热更的代码.注意,这包括你自己写的代码,也包括引用的Dll,比如UnityEngi ...
- bug__android studio 出现布局文件不提示,且点击代码不能跟踪代码
1,点击布局文件,出现 Cannot find declaration to go to ? 且 点击代码不能跟踪代码? 把 项目的build.gradle 中的 compileSdkVersi ...
- 代码规范、代码复审、PSP
作业三: 代码规范.代码复审.PSP 代码规范 代码规范的重要性 一.规范的代码可以促进团队合作 一个项目大多都是由一个团队来完成,如果没有统一的代码规范,那么每个人的代码必定会风格迥异.且不说会存 ...
- static代码块与{}代码块的比较
第一个例子: public class StaticDemo { { System.out.println("{} 代码块"); } static{ System.out.prin ...
- 程序员的恶性循环:加班->没空学习->老是写同等水平代码->无法提升代码质量->老是出BUG->老是需要修改->加班->...
程序员的恶性循环:加班->没空学习->老是写同等水平代码->无法提升代码质量->老是出BUG->老是需要修改->加班->...
- mvn编写主代码与测试代码
maven编写主代码与测试代码 3.2 编写主代码 项目主代码和测试代码不同,项目的主代码会被打包到最终的构件中(比如jar),而测试代码只在运行测试时用到,不会被打包.默认情况下,Maven假设项目 ...
- 转--Android实用的代码片段 常用代码总结
这篇文章主要介绍了Android实用的代码片段 常用代码总结,需要的朋友可以参考下 1:查看是否有存储卡插入 复制代码 代码如下: String status=Environment.getE ...
- 使用Underscore.js的template将Backbone.js的js代码和html代码分离
这段时间在学习Require.js和Backbone.js的过程中,发现有些项目里的HTML代码都是写在View的js代码里面的,渲染的时候需要对Collection进行循环,再将HTML代码拼接上去 ...
- Java中静态代码块,代码块,构造方法优先级、区别及代码示例
在项目中遇到了代码块的知识点,跑了下测试,写下结论 代码优先级:静态代码块 -> 构造代码块 -> 构造方法 多个代码块优先级,按照“先定义的代码先执行,后定义的代码后执行”原则执行 静态 ...
随机推荐
- AngularJS UI
1, angular ui 自定义弹框 <script type="text/ng-template" id="stackedModal.html"> ...
- Java课后总结2
特殊之处:有两个名称一摸一样的方法square(),但是两种方法的返回值的数据类型以及参数的数据类型都是不同的,一个为int一个为double. 运行结果:The square of integer ...
- 1255. 得分最高的单词集合 (Hard)
问题描述 1255. 得分最高的单词集合 (Hard) 你将会得到一份单词表 words,一个字母表 letters (可能会有重复字母),以及每个字母对应的得分情况表 score. 请你帮忙计算玩家 ...
- Linux 压测及监控工具Nmon
一.带宽 1. 查看网卡的网络 ethtool:查看宽带大小,语法:ethtool 网卡名称,如:ethtool ens192: 2. 实时统计网卡宽带使用率nload A. 安装nload wget ...
- ubuntu 20.04 基于kubeadm部署kubernetes 1.22.4集群及部署集群管理工具
一.环境准备: 集群版本:kubernetes 1.22.4 服务器系统 节点IP 节点类型 服务器-内存/CUP hostname Ubuntu 20.04 192.168.1.101 主节点 2G ...
- Unity多线程使用(线程池)
1.在C#中使用线程池需要以下这个类库using System.Threading 2.开单个线程(unity程序停止前 线程一定要关闭) private Thread tempThread; voi ...
- el-table 如果文字过多展示...
1 <el-table-column label="任务名称" width="120px" align="center" :show- ...
- Promise缺点
1.Promise 不能用try Catch捕获,只能通过.then的第二个参数或者.catch来捕获: let pro try{ pro = new Promise((resolve,reject) ...
- holiday08
第八天 管道 linux允许将 一个命令的输出 可以 通过管道 作为 另一个命令的输入 ls -lh | more 可以理解现实生活中的管子,管子一头塞东西进去,另一头取出来,这里 | 的左右分为两端 ...
- Docker学习——多阶段构建(六)
之前的做法 在 Docker 17.05 版本之前,我们构建 Docker 镜像时,通常会采用两种方式: 全部放入一个 Dockerfile 一种方式是将所有的构建过程编包含在一个 Dockerfil ...