哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率。在Java的Object类中有一个方法:
1
|
public
native
int
hashCode();
|
根据这个方法的声明可知,该方法返回一个int类型的数值,并且是本地方法,因此在Object类中并没有给出具体的实现。
为何Object类需要这样一个方法?它有什么作用呢?今天我们就来具体探讨一下hashCode方法。
对于包含容器类型的程序设计语言来说,基本上都会涉及到hashCode。在Java中也一样,hashCode方法的主要作用是为了配合基于散列的集合一起正常运行,这样的散列集合包括HashSet、HashMap以及HashTable。
为什么这么说呢?考虑一种情况,当向集合中插入对象时,如何判别在集合中是否已经存在该对象了?(注意:集合中不允许重复的元素存在)
也许大多数人都会想到调用equals方法来逐个进行比较,这个方法确实可行。但是如果集合中已经存在一万条数据或者更多的数据,如果采用equals方法去逐一比较,效率必然是一个问题。此时hashCode方法的作用就体现出来了,当集合要添加新的对象时,先调用这个对象的hashCode方法,得到对应的hashcode值,实际上在HashMap的具体实现中会用一个table保存已经存进去的对象的hashcode值,如果table中没有该hashcode值,它就可以直接存进去,不用再进行任何比较了;如果存在该hashcode值, 就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就散列其它的地址,所以这里存在一个冲突解决的问题,这样一来实际调用equals方法的次数就大大降低了,说通俗一点:Java中的hashCode方法就是根据一定的规则将与对象相关的信息(比如对象的存储地址,对象的字段等)映射成一个数值,这个数值称作为散列值。下面这段代码是java.util.HashMap的中put方法的具体实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
public
V put(K key, V value) {
if
(key ==
null
)
return
putForNullKey(value);
int
hash = hash(key.hashCode());
int
i = indexFor(hash, table.length);
for
(Entry
null
; e = e.next) {
Object k;
if
(e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(
this
);
return
oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);
return
null
;
}
|
put方法是用来向HashMap中添加新的元素,从put方法的具体实现可知,会先调用hashCode方法得到该元素的hashCode值,然后查看table中是否存在该hashCode值,如果存在则调用equals方法重新确定是否存在该元素,如果存在,则更新value值,否则将新的元素添加到HashMap中。从这里可以看出,hashCode方法的存在是为了减少equals方法的调用次数,从而提高程序效率。
1. cookie 和 session 的区别
cookie机制采用的是在客户端保持状态的方案,
而session机制采用的是在服务器端保持状态的方案。
1、cookie数据存放在客户的浏览器上,session数据放在服务器上。
2、cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗
考虑到安全应当使用session。
3、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能
考虑到减轻服务器性能方面,应当使用COOKIE。
4、单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。
5、
将登陆信息等重要信息存放为SESSION
其他信息如果需要保留,可以放在COOKIE中
2. JVM 内存模型
3. SQL注入的原理
4. 悲观锁 和 乐观锁
5. 读程序,输出结果. 关于treemap的
6. linux 基础命令,统计日志中的信息
7. java 分布式集群
8. 一道设计题,具体到数据库的表.大概是淘宝的搜索中,输入手机,会出来很多类型,按品牌按价格区间按手机种类.
还有2道题我记不住了.
面试:
1.介绍你做过的项目,用到的技术,涉及到的模块,然后从项目中问各种技术实现的细节(为了确保你是真的懂了).
2.看你的试卷,喊你讲解做题的思路,以及这样结果的原因.(考的是各位的java基础知识了,这点是绕不过去的,懂了就懂了啊,只有平时多看书)
3.团购6位验证码以及团购成功后,发送到你手机上的条码的实现方式.(第一个问题我说用随机数+时间来验证.第二个问题老实说,我也没答上来,我说用序列,面试官说序列到后期20位以上的时候,用户体验很差的)
4.淘宝上是如何保证库存和订单之间的数据准确性的.(考点是分布式事务,这个问题我也没答上来,最后他问我有什么问题问他的时候,我就反问的这个问题,面试官人挺好的,给我耐心的讲解了一遍淘宝的实现方式以及
epay的实现方式. 淘宝是通过分布式事物,中间用了一个叫协调者角色的程序,当那边点击购买时,会库存减一,保存一条预扣的状态,但是是个预准备状态,然后做成功后,协调者会在另一个数据库生成订单,然后这个订单也是预状态,等两边都准备好以后,通知协调者,又协调者统一完成这2个数据库的事物,从而达到完成一笔交易的目的,若其中一方失败,则将预扣的数字返回到库存从而实现类似回滚的操作.)
5.索引的原理.能否构建时间索引.时间索引构建后会存在什么问题.(索引原理我是回答的堆表索引的构建原理以及查询原理,但是关于时间索引的问题,我也没回答出个所以然来,看面试官的反馈,好像回答得不够好吧)
6.你们数据库的数据量有多大,(回答:我们是电信方面的系统,表上亿的数据很正常).问:如果保证效率?
(我是如此回答的,各位自行结合自身的情况参考.答:后台J OB程序会定期备份,把生产表数据移走,然后备份表也会再备份一次,如此剃度的备份,保证生产库的数据是最小的.然后备份表采用分区和子分区,加上构建战略索引(分析系统的sql,常用
查询字段构建复合索引,以减少每次查询时对表的访问次数)).
7.SQL注入的原理以及如何预防,并举例.(这个相对简单,网上一搜一大片)
8.使用过Memcache么? 用在项目中哪些地方? (答,在门户主机上使用,缓存session,分布式的时候,统一访问这台主机验证用户session是否存在,来维持回话的状态和实现回话同步.又追问:java代码中如何实现访问门户服务器的这个session池子的? 几年前的代码,确实忘记了..于是坦白的说,记不清楚了 )
这些是主要的问题,当你回答一个大问题时中间还有很多比较碎的追问性质的小问题,总体给我的感觉是,氛围很轻松+愉快的,技术层面上还是需要你真正的理解透彻一些关键技术点,才能做到应付各种追问和给出满意的答案吧.如果只是一知半解想去蒙混过关肯定是不行的,毕竟在支付宝的技术大牛面前,多追问几句,也就把你逼到死角了.
还有一点比较重要的感觉就是,他们比较在意你是否了解当下的一些比较热的技术点,比如淘宝的秒杀,是如何保证高并发下的安全性和性能,新浪微博那种大数据量的发送,怎么就保证正确性和时效性的.
列举常见集合框架类型
(1) List、Set、Map。由这三个接口实现出ArrayList、LinkedList、HashSet、TreeSet、HashMap、TreeMap等常用集合框架。
(2) Vector属于重量级组件不推荐使用。
(3) Map类型维护键/值对,Hashtable与HashMap相近但效率略低于HashMap、高于TreeMap、TreeMap优点是可以排序。
(4) Set类型可以装入唯一值,HashSet效率高于TreeSet但TreeSet可以维护内部元素的排序状态。
(5) List类型可按某种特定顺序维护元素。ArrayList允许快速随机访问,但如果添加或删除位于中间的元素时效率很低;LinkedList提供最佳循环访问及快速的中间位置添加删除元素,并有addFirst、addLast、getFirst、getLast、removeFirst、removeLast方法。
18、 面向对象的特征:
(1) 继承:通过子类可以实现继承,子类继承父类的所有状态和行为,同时添加自身的状态和行为。
(2) 封装:将代码及处理数据绑定在一起的一种编程机制,该机制保证程序和数据不受外部干扰。
(3) 多台:包括重载和重写。重载为编译时多态,重写是运行时多态。重载必须是同类中名称相同参数不同(包括个数不同和类型不同),但返回类型不同不构成重载;重写发生于子类对父类的覆盖,子类继承父类方法名相同、参数列表相同、返回类型相同才构成重写。
19、 Java命名规范:
(1) 必须以应为字母、下划线或$开始,其余可以有数据但不允许包含空格,且组合后的名称不能是Java关键字或保留字。
(2) 匈牙利命名法:以m开始为类成员变量,以g开始为全局变量,以v开始为本的局部变量,常量命名一般不以下划线、美元符开始。
(3) 驼峰命名:一般称由多个单词或缩写组成的变量名,并且该变量名每个单词首字母均为大写(一般类名全部首字母大写,方法或属性名第一个字母小写)的称为驼峰命名。
20、 Java语言共包含47个关键字。
21、 设计模式:
一个设计模式描述了一个被证实可行的方案。这些方案非常普遍,是具有完整定义的最常用的模式。一般模式有4个基本要素:模式名称(pattern name)、问题(problem)、解决方案(solution)、效果(consequences)
常见23种模式概述:
(1) 抽象工厂模式(Abstract Factory):提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
(2) 适配器模式(Adapter):将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的类可以一起工作。
(3) 桥梁模式(Bridge):将抽象部分与他的实现部分分离,使他们都可以独立的变化。
(4) 建造模式(Builder):将一个复杂对象的构建与他的标表示分离,使同样的构建过程可以创建不同的表示。
(5) 责任链模式(Chain of Responsibility):为解除请求的发送者和接收者之间耦合,而使多个对象都有几乎处理这个请求。将这些对象连成一条链,并沿着这条链传递给请求,知道有一个对象处理他。
(6) 命令模式(Command):将一个请求封装为一个对象,从而可用不同的请求对客户进行参数化;对请求排列或记录请求日志,以及支持可取消的操作。
(7) 合成模式(Composite):将对象组合成树形结构以表示“部分-整体”的层次结构。它使得客户对单个对象和复合对象的使用具有一致性。
(8) 装饰模式(Decorator):动态地给一个对象添加一些额外的职责。就扩展功能而言,他能生成子类的方式更为灵活。
(9) 门面模式(Facade):为子系统中的一组接口提供一个一致的界面,门面模式定义了一个高层接口,这个接口使得这一子系统更加容器使用。
(10) 工厂方法(Factory Mehtod):定义一个用于创建对象的接口,让子类决定将哪一个类实例化。Factory Method使一个类的实例化延迟到其子类。
(11) 享元模式(Flyweight):运用共享技术以有效地支持大量细粒度的对象。
(12) 解释器模式(Interpreter):给定一个语言,定义他的语法的一种表示,并定义一个解释器,该解释器使用该表示解释语言中的句子。
(13) 迭代子模式(Iterator):提供一种方法顺序访问一个聚合对象中的各个元素,而又不需暴露该对象的内部表示。
(14) 调停者模式(Mediator):用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式的内部表示。
(15) 备忘录模式(Memento):在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到保存的状态。
(16) 观察者模式(Observer):定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于他的对象都得到通知并自动刷新。
(17) 原始模型模式(Prototype):用原型实例指定创建对象的种类,并且通过拷贝这个原型创建新的对象。
(18) 代理模式(Proxy):为其他对象提供一个代理以控制对这个对象的访问。
(19) 单例模式(Singleton):保证一个类仅有一个实例,并提供一个访问他的全局访问点。
(20) 状态模式(State):允许一个对象在其内部状态改变时改变他的行为。对象看起来似乎修改了他所属的类。
(21) 策略模式(Strategy):定义一系列的算法,把他们一个个封装起来,并且使他们可相互替换。本模式使得算法的变化可独立使用他的客户。
(22) 模板模式(Template Mehtod):定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
(23) 访问者模式(Visitor):表示一个作用于某对象结构中的各元素的做。该模式可以实现在不改变各元素的类的前提下定义作用于这些元素的新操作。
22、 简述常用的软件开发文档
(1) 可行性研究报告
(2) 项目开发计划
(3) 软件需求说明书(必有)
(4) 数据要求说明书
(5) 概要设计说明书(必有)
(6) 详细设计说明书(必有)
(7) 数据库设计说明书(必有)
(8) 用户手册(一般会有)
(9) 操作手册(必有)
(10) 模块开发卷宗
(11) 测试计划(必有)
(12) 测试分析报告
进度报告
项目总结报告