关于hashmap的一些小纠结与个人理解

1.hashcode()方法JDK中的体现:

public native int hashCode();jdk根据对象的地址或者字符串或者数字算出来的int类型的数值

用法:当元素put进入hashmap中的位置,根据key.hashcode()来锁定插入位置,可能会出现hashcode相同情况(取模法),也就是hash冲突。

作用:使用hashcode为了提高哈希表(例如 java.util.Hashtable 提供的哈希表)的性能,因为插入新的元素进入集合中,为了判断集合中是否有相同的key,则调用equals(),进行每个元素相比较,会很耗时,而使用hashcode()则会使效率更高(实现:每个新的map元素都会有key,则会调用key.hashcode(),而在已有集合中的元素的hashcode值已经存在了此集合中的table<存放集合元素的hashcode值>中。)

2.相同的hashcode值如何存储对象:

hash冲突的体现:hashcode值相同,hashmap使用拉链式的方式处理hash冲突,第一个键值对A进来,通过计算其key的hash得到的index=0,记做:Entry[0] = A。一会后又进来一个键值对B,通过计算其index也等于0,现在怎么办?HashMap会这样做:B.next = A,Entry[0] = B,如果又进来C,index也等于0,那么C.next = B,Entry[0] = C;这样我们发现index=0的地方其实存取了A,B,C三个键值对,他们通过next这个属性链接在一起。所以疑问不用担心。这里也就体现了为什么hashmap不能key值相同,如果key相同最后插入的元素覆盖前面的value。

3.resize()扩容导致hashmap闭环问题.

下大雨

被闹铃叫醒的我,大概看了一下手机,7点40,听见外面哗哗雨好像很大,我听见外面舍友起来了,自己煮了一代排骨牛肉面,外面雨很大我们商量着怎么去上班,心情还是老样子,佳铭穿着拖鞋走了,这天气不穿拖鞋真是不太好出去,我心想一会穿靴子出去吧,稍微防着点水,杨明波起来,我准备走了,杨明波说:“外面水这么大,你游过去吧” 。我:“反正我会游泳”。

​ 这周天天加班,周一和周二和周三都是快11点到的家,感觉很累,不是身体累,是心里累,到家了,喜欢自己到阳台抽根烟,随便想点什么东西,今年我明显的感觉到了来自方方面面的压力,有的时候喜欢自己出去溜达,散散心,也不愿意多说话,和朋友们还是老样子,因为无论怎么嫌弃彼此,还是朋友。感觉社会就是一个大火锅,我们就是要被涮的东西,无论怎么样,都是要在社会中挣扎,扑腾,我厌恶了所有的比较,我现在更加要做自己。现在有点嗓子疼,不舒服,不愿意和不喜欢的人多说一句话,现在慢慢的理解了很多人的做法,以前可能不懂他们为什么这么做,现在慢慢的成长,和社会的接触,慢慢理解了他们的做法,如果换做是我,可能也会这么做,参加工作快一年,慢慢明白了什么是工作,有时候更多的是不愿意多说,心里知道就行了,聊天是门艺术,有的人你就是喜欢跟他多说话,有的人就是不愿意多说一句。回忆总是美好的,现实还是那么现实,生活继续,一些向前。EMMMM

浅谈为什么hashmap效率高

基于hashmap的内部实现数据结构,可以理解为Entry(数组)+node(链表)

查询(读取)快:

public final int hashCode() {

    return Objects.hashCode(key) ^ Objects.hashCode(value);
}

根据hashcode(key)来锁定位置,然后获取value,相当于获取index下标,取得其value,类似于list集合中的实现集合类Arraylist实现方式。

插入快:

Node(int hash, K key, V value, Node<K,V> next) {

    this.hash = hash;
    this.key = key;
    this.value = value;
    this.next = next;
}

源码中参数中带有Node节点下个节点的引用,插入的时候只需要移动一下指针,指向下一个即可.与linkedlist有着异曲同工之妙.

总结:虽然比较来看hashmap效率与hashtable较高,但是多线程情况是不安全的。

DB日期转换小计

需求:

将某Varchar类型字段显示为YYYY-MM-DD HH:MM:SS并根据另一个字段动态显示日期 月份加1操作,最后结

果显示为2018-0x-01 00:00:00

思路:

1.将表中字段类型varchar转换为Date格式,function为to_date

2.通过function为ADD_MONTHS实现月份+1操作

​3.最后通过to_char转化为字符格式

​ 4.通过||连接字符串00:00:00

具体实现:

select indexcalno,to_char(ADD_MONTHS(to_date(indexcalno,’yyyymm’),’1’),’yyyy-mm-dd’)||’ ‘||’00:00:00’ from laagentmonthb;

总结:

要多用function(or方法),理解其参数格式,比较实现同种功能mysql的function(or方法).

关于线程的生命周期

关于线程的生命周期问题

java中线程的生命周期大概可以分为5个过程:

1.new :当通过new关键字创建了Thread类(或者其他子类)的对象

2.Runnable: 如果thread类调用了start()方法时,那么此线程就会由new状态转化为Runnable状态。此时还没有获取到CPU,处于Runnbale状态的线程,在等待线程调度器为其分配CPU时间,也就是等待时间分片轮转到自己这里;第二种情况就是线程处于Runnable状态时并没有运行完自己的run方法,CPU用完了之后回到Runnable状态;还有一种状态就是blocked状态的线程结束了当前的blocked状态之后重新回到runnbale状态。

3.Running: 获取到了CPU的Runnable线程。

4.Blocked: 在Running状态中出现了类似等待,比如调用了sleep(),出现了线程阻塞状态。

5.Dead: 在Running状态执行完run()后,状态就转化为了Dead。

一次编译,到处执行

1.编译过程:我们通过IDE写出来的后缀为.java文件,通过JAVA编译器编译为.class文件(字节码)
2.编译字节码文件:把后缀为.class的字节码文件编译为目标机器代码,执行是由JVM引擎来完成,也就是JAVA的第二次编译。
3.到处执行:JAVA提供了各种不同平台上的虚拟机制,所以也就可以实现“到处”,即JVM for windows或者JVM for unix等
20sd
总结:在由字节码编译为机器语言的时候,真正采用的是“解释”机制,也就是翻译一句,执行一句,不产生真个机器代码的程序,翻译过程如果不出现错误,就一直进行到完毕,否则将在错误处停止执行,但是同一个程序,如果是解释执行的,那么它的运行速度同城比编译为可执行的机器代码的运行速度慢一些。但是,对于JAVA来说,差别并不大,因为JAVA的字节码经过仔细设计,使用的是JIT即时编译方式,编译技术将字节码直接转化为高性能的本地机器码,JIT也就是JVM的一部分,JAVA运行系统在提供JIT的同时仍具有平台独立性,所以“高效而且跨平台”对JAVA来说是兼得的。如果Java程序是“汉语”,那么其字节码就是“国际语言”,只要运行的国际(平台,windows,linux)提供“翻译”,他们就可以把“世界语言”翻译为本地语言。

GC问题

在java中,当你创建一个对象。javaJVM为其分配内存,调用构造函数并跟踪你使用的对象,当你停止使用一个对象(也就是停止对他的有效引用时),JVM通过垃圾回收器将对象标位释放状态。当垃圾回收器要释放一个对象的内存时,它调用该对象的finalize方法,垃圾回收器以独立的低优先级的方式运行,只是当其他线程挂起等待该内存释放的情况出现时,它才开始运行释放对象的内存。在当你(事实上,你可以调用System.gc()方法强制垃圾回收器来释放这些对象的内存)在以上的描述中,有一些重要的事情需要注意:首先,只有当垃圾回收器释放该对象的内存时,才会执行finalize方法,如果在Applet或应用程序退出之前垃圾回收器没有释放内存,垃圾回收器将不会调用finalize方法。其次:除非垃圾回收器认为你的Applet或应用程序需要额外的内存,否则它不会试图释放不在使用的对象的内存。换句话说,这是完全可能的,一个Applet给少量的对象分配内存,没有造成严重的内存需求,于是垃圾回收器没有释放这些内存就退出了。显然,如果你为某个对象定义finalize方法,JVM可能不会调用它,因为垃圾回收器不曾释放过那些对象的内存。调用System.gc()也不会起作用,因为它仅仅是给JVM一个建议而不是命令。System.runFinalizersOnExit()方法并不立即试图启动垃圾回收器,而是当应用程序或Applet退出时,它调用每个对象的finalize方法,finalize方法是与java编程中的垃圾回收器有关系。即:当一个对象变成垃圾对象的时候,如果此对象的内存被回收,那么就可以调用系统中定义的finalize方法来完成。当然,java的内存回收可以由JVM来自动完成。system.gc();java语言建立了垃圾收集机制,用以跟踪正在使用的对象和发现并回收不在使用(引用)的对象。该机制可以有效防范动态内存分配中可能发生的两个危险:
①因内存垃圾过多而引发的内存耗尽
②以及不恰当的内存释放所造成的内存非法引用

触发主GC的条件:

①当应用程序空闲时,即没有应用线程在运行时,GC会被调用,因为GC在优先级最低的线程在运行,并在运行过程中创建新对象,若这时内存空间不足,JVM就会强制的调用GC线程,以便回收内存用于新的分配。若GC一次之后仍不能满足内存分配的要求,JVM会进行两次GC作进一步的尝试,若仍无法满足要求,则JVM将报“out of memory”的错误,java应用将停止。由于是否进行主GC由JVM根据系统环境决定而系统环境在不断的变化当中,所以主GC的运行具有不确定性,无法预计它何时必然出现,但可以确定的是对一个长期运行的应用来说,其主GC是反复进行的。

垃圾收集算法的核心思想是:

对虚拟机可用内存空间,即堆空间中的对象进行识别,如果对象正在被引用,那么称其为存活对象,反之,如果对象不再被引用,则为垃圾对象,可以回收其占据的空间,用于再分配。垃圾收集算法的选择和垃圾收集系统参数的合理调节直接影响着系统的性能,因此需要开发人员有着比较深刻的理解。

堆内存与栈内存:

堆内存实际上指的是优先队列的一种数据结构(自由度大),第一个元素有最高的优先权;栈内存实际上就是满足先进后出的性质的数学或数据结构(自由度小)。

end:大学时写的文章。img