java数据结构链表例子-java 链表数据结构
链接:zhuanlan.zhihu.com/p/28615617
这几天很多人请我回答各种j2ee开发初级问题,都没有强调java初学者要先夯实基础知识,那么java的基础知识是什么? 那么如何掌握java的基础知识呢? 这个问题确实值得深思。
做j2ee开发已经十几年了。 作为经历过的人,我的心路历程大概和大家差不多。 最初几年coding,一直觉得java很简单,开发实现各种功能很容易,代码一点也不难写(主要是写的代码都是一些功能业务逻辑)。 但与此同时,我心里也明白,自己的水平真的不高。 在过去的 3 或 4 年里,我只学到了这么多。 其他人可以在几个月内学会它。 我的竞争力在哪里? 这种矛盾的心理困扰了我很久,很苦恼! 总有一种报国无路、发力无处的感觉。
这期间热衷于使用各种框架和各种API。 今天学了某个API、组件、框架后,常常觉得自己学到了一些东西。 不止一次看过设计模式,但感觉不多。 我一方面努力学习,另一方面又心里不安,因为比如我会API你不会,我告诉你你就知道了,那我比你有什么优势呢? 遇险*2
经过长时间的恐慌之后,我决定要改变。 改的方向是阅读以前看jdk是怎么实现的java相关的源码。 只看基本数据结构,再看多线程相关,学习前台等等。 我写的代码还是那些代码,代码还是那么简单,但我努力去了解代码背后的真相,这是我最初努力的方向。 于是我不再把时间花在追求各种新框架、新API的使用上,而是每天花时间研究实现原理。 就这样过了大半年,我终于不迷茫了,不再觉得自己只懂api的使用,感觉自己没有那么肤浅,说自己是也不为过完全重生。 那段时间是我成长最快的一段时间,也是最充实的一段时间。
话不多说,拿代码举例说明,大家会有更好的感受。
比如学习了hashmap的源码,知道了工作原理后,使用hashmap
MapString > map = new HashMap<>();
代码还是一样,但是我已经知道hashmap背后的内容了
1.数据结构是链表数组(注意:后面版本为了提高性能,改为链表或者树(更多节点)) 2.思想是空间交换算法time 3. constructor有capacity and load factor有2个参数和它的function 4. 决定性能的是key的hashcode是否足够快,结果是否足够分散(如果不分散,就会变成链表的性能),以及扩容的代价(什么时候扩容,跟负载因子有关)那么写代码的时候,如果知道最终的容量(尤其是数据量大的时候),我会指定初始容量,类似下面
List
list = doSomeThing();
Mapmap = new HashMap<>((int)(list.size()/0.75));//0.75为默认负载因子 如果工作中对某个地图使用较多,性能需要优化,我会考虑从以下几个方面进行优化
1.如果key是自己定义的对象,hashcode方法够快吗(至少要缓存起来保证只计算一次,放进去之后不能再改变,所以hashcode字段不能被改变)? 散列的结果是否足够分散?
2.可以考虑降低负载率,用更多的空间来换取时间
在学习源码的时候,特别有趣,你会强烈感受到一个词:举一反三! 触类旁通! 在学习如何使用api的时候,如果只知道如何使用而不知道原理,很难从一个实例中推断出其他情况,有一种死记硬背的感觉。 但是把原理和知识学成一个系统之后,就很容易举一反三,越学越容易。 我以hashmap为例,对于hashmap我给出三点。 1、你会知道,对于任何一个带有数组的数据结构,其构造函数都有一个容量初始化参数(或者说带有初始化容量的构造函数可能是一个数组数据结构)。构造函数如下
public ArrayList(int initialCapacity) //LinkedList不是数组就没有
public HashMap(int initialCapacity)
public StringBuffer(int capacity)你会知道数组扩容是很耗性能的(大数据量容易OO),尽量指定capacity。 2. 该算法以空间换取时间。 这个想法还有其他算法吗? 您至少可以找到桶排序。 3.数据库分表的思路和hashmap类似。 4.对于各种分布式hash一致性算法,第一步是创建最大数组(Integer.MAX_VALUE),这样就避免了最耗性能的hashmap扩容。 手术。 学了hashmap之后,自然而然会去了解其他的map,比如TreeMap、LinkedHashmap(超级好用)、HashTable、ConcurrentSkipListMap(算法思想很有意思)、ConcurrentHashMap等,你就会知道set是用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。 这体现了两种不同的管理理念。 这种思路往往体现在多系统集成的设计中。 有的时候,如果用悲观的思维去设计,实现起来会很麻烦,或者无法实现,但是如果用乐观的思维,就可以减少出错的条件,进而可以解决错误。 会小很多。
说了这么多,我想说的是j2ee的基础知识就是你项目中代码背后的东西。 提高水平的方法很简单,就是把大部分时间花在理解实现原理上,理解思路上java数据结构链表例子,把自己的知识串联起来形成一个系统。 J2ee的学问真多,看得人想哭。 不要一开始就花时间在各种框架和组件的使用上。 在我看来,这是本末倒置。 简单来说就是:先练内功,再练招式。 我觉得工作中能用到的重要知识就是前台到后台处理一个请求的过程中需要用到的知识,至少包括以下几点:js、html、css、ajax、ajax跨域、跨站脚本、网页缓存、网页优化、nginx、apache函数、认证方式、cookie、session、servlet、filter、基础数据结构、线程池、线程并发、缓存、io等,知识点很多. 如果你在前台使用jq,你应该明白他的selector和ajax是怎么实现的(其实你理解了就会发现并不复杂)? 而不仅仅是能够使用它。 如果你在后台使用springmvc,你需要了解它是如何工作的,每个配置是做什么的,为什么?
j2ee的知识点很多,每一个都可以写很多,自己也在不断的学习中。 具体来说,我实在是不知如何下手,就把我认为基本的东西(面试时问的问题)列出来吧。 有些很简单,有些很困难。 你怎么看可能是因为你没有做好这个开发或者没有做好。 比较浅:
1、map有什么特点和使用场景? (只知道hashmap和hashtable是不够的。)
2、哪些方面会影响hashmap的性能?
3、线程安全的maps有哪些,concurrenthashmap是如何实现线程安全的(jdk1.8差别很大)?
4、锁具有哪些种类?
5、如何实现公平锁、读写锁等?
6、synchronize在哪里可以加? 有什么不同?
7、死锁形成的条件是什么?死锁现在很少见,很少有人问
8、原子数据对象的原理是什么?
9. Reentrantlock相关知识,如何使用condition? (很重要的知识点,强烈推荐阅读ArrayBlockingQueue的源码,像教科书一样)
10.关于volatile的知识(内存屏障,重排)
11、ThreadLocal的原理及使用? (超级有用的知识点,工作中用的很多,让代码更漂亮,后面会专门贴出来)
12. 多个线程同步等待? (CountDownLatch、CyclicBarrier、Semaphore信号量很多语言都有,其实用的不多java数据结构链表例子,线程池可以实现大部分的等待功能)
13、线程池? (类型,重要方法,这个一般是使用级别,简单)
14.动态代理? 反射? 内省? (调查知识)
15. Session相关知识? 与cookies的关系? 分布式会话实现原理?
16 Cookie相关知识? 有什么特点? (有些属性很有用,只是我们很少关注!)
17、nginx、apache实际项目可以做什么? (认证、转发、缓存、反向代理等)和tomcat有什么关系?最不明白
18 Ajax跨域的原因? 解决方案? (重点知识,做SE不能回避的问题,这里有很多知识点。)
19 jsonp原理? 是否需要修改后台? (虽然现在jsonp已经过时了,但还是会问)
20.网站优化知识点? (常识点)
21. Front buffer相关? (200cache、304、ajax缓存,如何实现缓存)
一列出来就停不下来了。 . . spring框架还有很多,还有jvm,系统集成相关的,数据库相关的,IO做的很少不知道怎么问,以后慢慢写下自己的学习过程和偶尔的收获。 我也明白了很多东西,就看你有没有研究过。 持续学习是程序员最重要的特征。 我不是高手,只能算是一个合格的老程序员。 这里我只是说说我之前学习的方向,列举几个我学习中的例子。 每个人都有不同的看法。 帖子也是为迷茫的初学者发的,希望对大家有所帮助。 最后总结一下:新手应该关注代码背后的实现,注重内功修炼,了解实现的原理和思路,形成自己完整的技术体系。 快点。 最后再举几个在各个项目组和开发者聊天时都会说的例子:“少林功夫,有功夫,有拳法。马步功夫,石锁功夫,就是功夫,蛇拳和猴拳是拳击,你练不好,蛇拳和猴拳都能打人,你得先专心练。体操。同样,我们要分清编程里面的那些是技巧,那些是拳头。代码背后的实现和思想是技巧,各种框架和api的使用才是拳头。初学者应该把大部分时间花在练习技巧上。功力到了拳法,自然就到位了,别本末倒置。 谢谢大家阅读!我开了一个专栏记录作者的学习路径和编程习惯,每周至少一次,欢迎关注作者专栏:本文作者,小风晴,知乎链接:。