1.解决hash冲突的方法
分离链接法( 链地址法 拉链法)
未冲突的情况下,直接将值存储在数组中,数组的每一个位置都是一个 链表的头节点,一旦发生冲突(即原有的位置已经有值了)立刻将以由冲突的链表尾节点指向现有值。
开放定址法(探测散列表)
开放地址法一般会有一个探测算法,当前位置被占用时,根据探测算法计算寻找下一个空的位置。 以最简单的线性探测算法为例:当位置被占用时,继续往下走,直到找到下一个没被占用的位置,然后将值放在该位置中。
再哈希法
当发生冲突的时候,建立另外一个大约两倍大的表,并且使用相关的新散列函数,然后扫描原始散列表并计算每个 散列表的新值并将其插入到新表中。
建立公共溢出区
这种方法的基本思想是:将哈希表分为基本表和溢出表两部分,凡是和基本表发生冲突的元素,一律填入溢出表
参考 以及 数据结构与算法分析java语言描述2 map的key是不重复的,这是怎么做的?
首先将传入的key值用hash方法转化为int类型的hash值, 根据indexof算法通过hash值和table的大小得到这个 区域的位置下标,得到这个区域下标后再for循环遍历这个区域来找到 相应的元素,如果hash值和key都相等,那么进行覆盖原元素操作 如果遍历结束没找到就添加元素。
参考3 Java中Hashtable与HashMap的区别
1 hashtable没有遵循驼峰命名法。
2 Hashtable继承了Dictionary抽象类, HashMap实现了map接口
3 HashMap可以使用null作为key,不过建议还是尽量避免这样使用。HashMap以null作为key时,总是存储在table数组的第一个节点上。而Hashtable则不允许null作为key
4 HashMap的初始容量为16,Hashtable初始容量为11,两者的填充因子默认都是0.75。HashMap扩容时是当前容量翻倍即:capacity 2,Hashtable扩容时是容量翻倍+1即:capacity (2+1)
5 hashtable计算hash是直接使用key的hashcode对table数组的长度直接进行取模HashMap计算hash对key的hashcode进行了二次hash,以获得更好的散列值,然后对table数组长度取模
6 底层实现 在JDK1.6,JDK1.7中,HashMap采用位桶+链表实现,即使用链表处理冲突,同一hash值的链表都存储在一个链表里。但是当位于一个桶中的元素较多,即hash值相等的元素较多时,通过key值依次查找的效率较低。而JDK1.8中,HashMap采用位桶+链表+红黑树实现,当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找时间。在jdk1.8版本后,java对HashMap做了改进,在链表长度大于8的时候,将后面的数据存在红黑树中,以加快检索速度。
7 安全性:Hashtable是线程安全,HashMap是非线程安全
4 http与https的区别
1 http需要用到ca(Certificate Authority,证书颁发机构)申请证书,一般免费的证书较少,所以需要一定费用
2 http是超文本传输协议,信息是明文传输,https则是在http的基础上增加了具有安全性的ssl加密传输协议。
3 http与https使用完全不同的连接方式,用的端口不一样,前者是80,后者是443
5 http的连接很简单,是无状态的,https协议是由ssl+http协议构建的可进行加密传输。身份认证的网络协议 (无状态的意思是其数据包的发送,传输和接收都是相互独立的,无连接的意思是指通信双方都不长久的维持对方的任何信息)
参考5 tcp/ip协议内容以及主要协议
应用层:TELNET、FTP、TFTP、SMTP、SNMP、HTTP、BOOTP、DHCP、DNS
传输层:TCP、UDP、SPX
网络层:IP、IPX、ICMP、RIP、OSPF(Open Shortest Path First开放式最短路径优先)
数据链路层:SDLC、HDLC、PPP、STP(Spanning Tree Protocol)、帧中继
物理层:EIA/TIA RS-232、EIA/TIA RS-449、V.35、RJ-45
参考6 java进程和线程的区别
根本区别:进程是操作系统资源分配的基本单位,而线程是处理器任务调度和执行的基本单位
资源开销:每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小。
内存分配:同一进程的线程共享本进程的地址空间和资源,而进程之间的地址空间和资源是相互独立的
影响关系:一个进程崩溃后,在保护模式下不会对其他进程产生影响,但是一个线程崩溃整个进程都死掉。所以多进程要比多线程健壮。
执行过程:每个独立的进程有程序运行的入口、顺序执行序列和程序出口。但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制,两者均可并发执行
同类的多个线程共享进程的堆和方法区资源,但每个线程有自己的程序计数器、虚拟机栈和本地方法栈,所以系统在产生一个线程,或是在各个线程之间作切换工作时,负担要比进程小得多,也正因为如此,线程也被称为轻量级进程。
参考7 java局部变量和成员变量的作用域区别
成员变量:(1)定义在类里,方法之外的变量。
(2)成员变量可以不显式初始化,它们可以由系统设定默认值;
(3)成员变量在所在类被实例化后,存在堆内存中
局部变量:(1)定义在方法体内部的变量。
(2)局部变量没有默认值,所以必须设定初始赋值。
(3)局部变量在所在方法调用时,存在栈内存空间中。
8 什么是孤儿进程,僵尸进程
我们知道在unix/linux中,正常情况下,子进程是通过父进程创建的,子进程在创建新的进程。子进程的结束和父进程的运行是一个异步过程,即父进程永远无法预测子进程 到底什么时候结束。 当一个 进程完成它的工作终止之后,它的父进程需要调用wait()或者waitpid()系统调用取得子进程的终止状态。
孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。
僵尸进程:一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵死进程。
参考9 tcp协议、udp协议?
传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议
用户数据报协议(UDP,User Datagram Protocol)。UDP 为应用程序提供了一种无需建立连接就可以发送封装的 IP 数据包的方法
传输层有两个主要协议,互为补充。无连接的是 UDP,它除了给应用程序发送数据包功能并允许它们在所需的层次上架构自己的协议之外,几乎没有做什么特别的事情。面向连接的是 TCP,该协议几乎做了所有的事情
参考10 说一下集合的大致框架?
主要分为Collection和Map两大类,Collection分为List和Set两大分支
List集合是一个有序的队列,每一个元素都有他的索引。第一个元素的索引值为0。List的实现类有LinkedList、ArrayList、Vector、Stack。
Set集合是一个不允许有重复元素的集合。Set的实现类有HashSet、TreeSet。HashSet依赖于HashMap,实际上是通过HashMap实现的;TreeSet依赖于TreeMap,实际是通过TreeMap实现的
Map:是双列集合的顶层父类接口,是一个映射接口,即key-Value键值对。允许使用键来查找对应的值,Map中的每一个元素包含"key"和"key对应的value"。
11 JVM内存模型
方法区:主要存放类的信息、静态变量、常量、编译后的方法代码.
堆:唯一用途就是用来存放对象实例,根据对象的存活周期划分为新生代和老年代OldGen,两者的默认占比为1:2(即新生代:老年代),其中新生代又可以细化为Eden+From Survivor+To Survivor,默认占比为8:1:1。
虚拟机栈:描述了Java方法执行的内存模型,每个方法执行时都会创建一个栈帧Stack Frame,线程每调用一个方法就对应着 JVM Stack 中 Stack Frame 的入栈,方法执行完毕或者异常终止对应着出栈(销毁)。
本地方法栈:与虚拟机栈类似,只是虚拟机服务的对象不同而已,虚拟机栈服务的是Java方法,而本地方法栈服务的是本地方法即native方法。
程序计数器:用于记录每条线程当前所执行到的字节码行号,以便线程切换后能恢复到正确的执行位置。因此每条线程都有独立的程序计数器,且各线程间互不影响。
参考1 参考212 使用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变?
使用final关键字修饰一个变量时,是指引用变量不能变,引用变量所指向的对象中的内容还是可以改变的。
被final修饰的变量其实就相当于定义了一个常量,无法被修改的变量,
如果final修饰的是一个基本数据类型的变量,那么这个变量的值就定了,
不能变了,而如果修饰的是一个引用变量,那么该变量存的是一个内存地址,
该地址就不能变了,但是该内存地址所指向的那个对象还是可以变的,就像你记住了人家的门牌号,
但你不能管人家家里人员数量
参考13 简要描述如何安装配置apache的一个开源hadoop
1使用root账户登录
2 修改IP
3 修改host主机名
4 配置SSH免密码登录
5 关闭防火墙
6 安装JDK
6 解压hadoop安装包
7 配置hadoop的核心文件 hadoop-env.sh,core-site.xml , mapred-site.xml , hdfs-site.xml
8 配置hadoop环境变量
9 格式化 hadoop namenode-format
10 启动节点start-all.sh
参考14 正常工作的Hadoop集群中Hadoop都分别需要启动哪些进程,它们的作用分别是什么
1)NameNode它是hadoop中的主服务器,管理文件系统名称空间和对集群中存储的文件的访问,保存有metadate。
2)SecondaryNameNode它不是namenode的冗余守护进程,而是提供周期检查点和清理任务。帮助NN合并editslog,减少NN启动时间。
3)DataNode它负责管理连接到节点的存储(一个集群中可以有多个节点)。每个存储数据的节点运行一个datanode守护进程。
4)ResourceManager(JobTracker)JobTracker负责调度DataNode上的工作。每个DataNode有一个TaskTracker,它们执行实际工作。
5)NodeManager(TaskTracker)执行任务
6)DFSZKFailoverController高可用时它负责监控NN的状态,并及时的把状态信息写入ZK。它通过一个独立线程周期性的调用NN上的一个特定接口来获取NN的健康状态。FC也有选择谁作为Active NN的权利,因为最多只有两个节点,目前选择策略还比较简单(先到先得,轮换)。
7)JournalNode 高可用情况下存放namenode的editlog文件.
参考15 jvm虚拟垃圾回收算法中的引用计数算法与可达性分析算法
引用计数算法:给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时刻计数器为0的对象就是不可能再被使用的。 但是,主流的java虚拟机中没有选用引用计数法来管理内存,其中最主要的原因是他很难解决对象之间互相循环引用的问题。
可达性分析算法: 这个算法的基本思路是通过一系列的称为“GC Roots”的对象作为起始点,从这些起点开始向下搜索,搜索所走过的路径称为引用链(Referrnce Chain),当一个对象到GC Roots之间没有任何引用链相连时,证明此对象是不可用的。 在java中,可以作为GC Roots的对象包括下面几种:
1.虚拟机栈(栈帧中的本地变量表)中引用的对象。
2.方法区中类静态属性引用的对象。
3.方法区中常量引用的对象。
4.本地方法栈中Native方法引用的对象
参考 以及 深入理解jvm虚拟机