总结了一些新的面试题,包含答案(持续更新中)

Java根底
● 集合类以及集合框架;HashMap与HashTable完成原理,线程平安性,hash抵触及处置算法;ConcurrentHashMap;
- Collection 集合的根接口
+Set 继承类,不能包含重复元素,无序
+List 继承类,可以包含重复元素,按索引访问,有序
- Map 和Colletion互相独立
-Iterator 被所有的集合类实现
+hasNext()是否有下个元素
+next()返回下个元素
+remove()
 在类集中提供了以下四种的常见输出方式:
1) Iterator :迭代输出,是使用最多的输出方式。
2) ListIterator :是Iterator的子接口,专门用于输出List中的内容。
3) foreach 输出:JDK1.5之后提供的新功能,可以输出数组或集合。
4) for循环
- ArrayList和LinkedList
ArrayList和LinkedList 在用法上没有区别,但是在功能上还是有区别的。 LinkedList经常用在增删操作较多而查询操作很少的情况下,ArrayList则相反。
为什么ArrayList查询速度快?
因为ArrayList底层使用的是数组。而LinkList使用的是链表,查询的时候会从头开始查。相反,插入和删除使用LinkList速度比较快,因为 而在LinkedList的中间插入或删除一个元素的开销是固定的。
Map集合
实现类:HashMap、Hashtable、LinkedHashMap和TreeMap
HashMap 
HashMap是最常用的Map,它根据键的HashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度,遍历时, 取得数据的顺序是完全随机 的。因为 键对象不可以重复 ,所以HashMap最多只允许一条记录的键为Null,允许多条记录的值为Null,是非同步的。 如果长度超过75%,长度增加一倍。
Hashtable
Hashtable与HashMap类似,是HashMap的 线程安全 版,它支持线程的同步,即任一时刻只有一个线程能写Hashtable,因此也导致了Hashtale在写入时会比较慢,它继承自Dictionary类,不同的是它不允许记录的键或者值为null,同时效率较低。
ConcurrentHashMap
线程安全,并且锁分离。 ConcurrentHashMap内部使用段(Segment)来表示这些不同的部分,每个段其实就是一个小的hash table,它们有自己的锁。只要多个修改操作发生在不同的段上,它们就可以并发进行。
Hashtable和ConcurrentHashMap有什么分别呢?
它们都可以用于多线程的环境,但是当Hashtable的大小增加到一定的时候,性能会急剧下降,因为迭代时需要被锁定很长的时间。因为ConcurrentHashMap引入了分割(segmentation),不论它变得多么大,仅仅需要锁定map的某个部分,而其它的线程不需要等到迭代完成才能访问map。简而言之,在迭代的过程中,ConcurrentHashMap仅仅锁定map的某个部分,而Hashtable则会锁定整个map。
ConcurrentHashMap能完全替代HashTable吗?
hash table虽然性能上不如ConcurrentHashMap,但并不能完全被取代,两者的迭代器的一致性不同的,hash table的迭代器是强一致性的,而concurrenthashmap是弱一致的。 ConcurrentHashMap的get,clear,iterator 都是弱一致性的。 Doug Lea 也将这个判断留给用户自己决定是否使用ConcurrentHashMap。
LinkedHashMap
LinkedHashMap 保存了记录的插入顺序 ,在用Iteraor遍历LinkedHashMap时,先得到的记录肯定是先插入的,在遍历的时候会比HashMap慢,有HashMap的全部特性。 输出的顺序和输入的相同.
TreeMap
TreeMap实现SortMap接口,能够把它保存的记录 根据键排序 ,默认是按键值的升序排序(自然顺序),也可以指定排序的比较器,当用Iterator遍历TreeMap时,得到的记录是排过序的。不允许key值为空,非同步的; 按自然顺序或自定义顺序遍历键.
Map的遍历有两种:
KeySet()
entrySet()
推荐使用第二种方式,即 entrySet()方法,效率较高
Vector和ArrayList
1,vector是线程同步的,所以它也是线程安全的,而arraylist是线程异步的,是不安全的。如果不考虑到线程的安全因素,一般用arraylist效率比较高。
2,如果集合中的元素的数目大于目前集合数组的长度时,vector增长率为目前数组长度的100%,而arraylist增长率为目前数组长度的50%。如果在集合中使用数据量比较大的数据,用vector有一定的优势。
3,如果查找一个指定位置的数据,vector和arraylist使用的时间是相同的,如果频繁的访问数据,这个时候使用vector和arraylist都可以。而如果移动一个指定位置会导致后面的元素都发生移动,这个时候就应该考虑到使用linklist,因为它移动一个指定位置的数据时其它元素不移动。
ArrayList 和Vector是采用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,都允许直接序号索引元素,但是插入数据要涉及到数组元素移动等内存操作,所以索引数据快,插入数据慢,Vector由于使用了synchronized方法(线程安全)所以性能上比ArrayList要差,LinkedList使用双向链表实现存储,按序号索引数据需要进行向前或向后遍历,但是插入数据时只需要记录本项的前后项即可,所以插入数度较快。
arraylist和linkedlist
1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
2.对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
3.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。 这一点要看实际情况的。若只对单条数据插入或删除,ArrayList的速度反而优于LinkedList。但若是批量随机的插入删除数据,LinkedList的速度大大优于ArrayList. 因为ArrayList每插入一条数据,要移动插入点及之后的所有数据。
HashMap与TreeMap
1、 HashMap通过hashcode对其内容进行快速查找,而TreeMap中所有的元素都保持着某种固定的顺序,如果你需要得到一个有序的结果你就应该使用TreeMap(HashMap中元素的排列顺序是不固定的)。
2、在Map 中插入、删除和定位元素,HashMap是最好的选择。但如果您要按自然顺序或自定义顺序遍历键,那么TreeMap会更好。使用HashMap要求添加的键类明确定义了hashCode()和 equals()的实现。
两个map中的元素一样,但顺序不一样,导致hashCode()不一样。
同样做测试:
在HashMap中,同样的值的map,顺序不同,equals时,false;
而在treeMap中,同样的值的map,顺序不同,equals时,true,说明,treeMap在equals()时是整理了顺序了的。
HashTable与HashMap
1、同步性:Hashtable是线程安全的,也就是说是同步的,而HashMap是线程序不安全的,不是同步的。
2、HashMap允许存在一个为null的key,多个为null的value 。
3、hashtable的key和value都不允许为null。
HashMap和数组谁更快?
HashMap底层是一个数组+链表实现。其基本原理是:定义一个LinkedList的数组,然后将数据存储到这个链表数组内.
中间要通过数组找到链表,然后再去除value。所以应该是数组要快。
网上我也查过有人做了实验,也是同样的结果。
介绍几个排序算法?
冒泡排序
比较相邻的元素。如果第一个比第二个大,就交换他们两个。
对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
针对所有的元素重复以上的步骤,除了最后一个。
持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
快速排序
从后往前比较,用基准值和最后一个值比较,如果比基准值小的交换位置,如果没有继续比较下一个,直到找到第一个比基准值小的值才交换。找到这个值之后,又从前往后开始比较,如果有比基准值大的,交换位置,如果没有继续比较下一个,直到找到第一个比基准值大的值才交换。直到从前往后的比较索引>从后往前比较的索引,结束第一次循环,此时,对于基准值来说,左右两边就是有序的了。
效率最好: 三数取中(median-of-three)+插排+聚集相等元素。能减少迭代次数
线程和进程各自有什么区别和优劣呢?
进程是资源分配的最小单位,线程是程序执行的最小单位。
进程有自己的独立地址空间,每启动一个进程,系统就会为它分配地址空间,建立数据表来维护代码段、堆栈段和数据段,这种操作非常昂贵。而线程是共享进程中的数据的,使用相同的地址空间,因此CPU切换一个线程的花费远比进程要小很多,同时创建一个线程的开销也比进程要小很多。
线程之间的通信更方便,同一进程下的线程共享全局变量、静态变量等数据,而进程之间的通信需要以通信的方式(IPC)进行。不过如何处理好同步与互斥是编写多线程程序的难点。
但是多进程程序更健壮,多线程程序只要有一个线程死掉,整个进程也死掉了,而一个进程死掉并不会对另外一个进程造成影响,因为进程有自己独立的地址空间。
● Java的并发、多线程、 线程模型;
常用的多线程设计模式包括:Future模式、Master-Worker模式、Guarded Suspeionsion模式、不变模式和生产者-消费者模式等。
●  中缀表达式(中缀记法)
中缀表达式是一种通用的算术或逻辑公式表示方法,操作符以中缀形式处于操作数的中间。中缀表达式是人们常用的算术表示方法。
虽然人的大脑很容易理解与分析中缀表达式,但对计算机来说中缀表达式却是很复杂的,因此计算表达式的值时,通常需要先将中缀表达式转换为前缀或后缀表达式,然后再进行求值。对计算机来说,计算前缀或后缀表达式的值非常简单。
缀表达式的计算机求值:
与前缀表达式类似,只是顺序是从左至右:
从左至右扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(次顶元素 op 栈顶元素),并将结果入栈;重复上述过程直到表达式最右端,最后运算得出的值即为表达式的结果。
例如后缀表达式“3 4 + 5 × 6 -”:
(1) 从左至右扫描,将3和4压入堆栈;
(2) 遇到+运算符,因此弹出4和3(4为栈顶元素,3为次顶元素,注意与前缀表达式做比较),计算出3+4的值,得7,再将7入栈;
(3) 将5入栈;
(4) 接下来是×运算符,因此弹出5和7,计算出7×5=35,将35入栈;
(5) 将6入栈;
(6) 最后是-运算符,计算出35-6的值,即29,由此得出最终结果。
将中缀表达式转换为后缀表达式:
与转换为前缀表达式相似,遵循以下步骤:
(1) 初始化两个栈:运算符栈S1和储存中间结果的栈S2;
(2) 从左至右扫描中缀表达式;
(3) 遇到操作数时,将其压入S2;
(4) 遇到运算符时,比较其与S1栈顶运算符的优先级:
(4-1) 如果S1为空,或栈顶运算符为左括号“(”,则直接将此运算符入栈;
(4-2) 否则,若优先级比栈顶运算符的高,也将运算符压入S1(注意转换为前缀表达式时是优先级较高或相同,而这里则不包括相同的情况);
(4-3) 否则,将S1栈顶的运算符弹出并压入到S2中,再次转到(4-1)与S1中新的栈顶运算符相比较;
(5) 遇到括号时:
(5-1) 如果是左括号“(”,则直接压入S1;
(5-2) 如果是右括号“)”,则依次弹出S1栈顶的运算符,并压入S2,直到遇到左括号为止,此时将这一对括号丢弃;
(6) 重复步骤(2)至(5),直到表达式的最右边;
(7) 将S1中剩余的运算符依次弹出并压入S2;
(8) 依次弹出S2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式(转换为前缀表达式时不用逆序)。
一、future 模式
Future 模式采用异步调用,充分利用等待的时间段,执行其他业务逻辑处理,最后再执行返回较慢的Future 数据,从而提高系统的响应速度
Master-Worker模式是常用的并行模式之一,它的核心思想是:系统由两类进程协同工作,即Master进程和Worker进程,Master负责接收和分配任务,Wroker负责处理子任务。当各个Worker进程将子任务处理完成后,将结果返回给Master进程,由Master进程进行汇总,从而得到最终的结果
二、JDK1.6的内置Future实现
多线程的代价:
设计更复杂
上下文切换的开销
增加资源消耗
死锁:
死锁是两个或更多线程阻塞着等待其它处于死锁状态的线程所持有的锁。死锁通常发生在多个线程同时但以不同的顺序请求同一组锁的时候。
例如,如果线程1锁住了A,然后尝试对B进行加锁,同时线程2已经锁住了B,接着尝试对A进行加锁,这时死锁就发生了。线程1永远得不到B,线程2也永远得不到A,并且它们永远也不会知道发生了这样的事情。为了得到彼此的对象(A和B),它们将永远阻塞下去。这种情况就是一个死锁。

数据库的死锁 更加复杂的死锁场景发生在数据库事务中。一个数据库事务可能由多条SQL更新请求组成。当在一个事务中更新一条记录,这条记录就会被锁住避免其他事务的更新请求,直到第一个事务结束。同一个事务中每一个更新请求都可能会锁住一些记录 当多个事务同时需要对一些相同的记录做更新操作时,就很有可能发生死锁 ● 什麼是线程池,如何运用? 答: 线程池就是事前将多个线程对象放到一个容器中,当运用的时分就不必new 线程而是间接去池中拿线程即可 ● 数据分歧性如何保证;Synchronized关键字,类锁,办法锁,重入锁;

对于类锁,则会把整个类锁住,也就说只能有一个对象拥有当前类的锁。当一个对象拥有了类锁之后,另外一个对象还想竞争锁的话则会被阻塞。两个对象A,B,如果A正在访问一个被类锁修饰的方法function,那么B则不能访问。因为类锁只能在同一时刻被一个对象拥有。相对于对象锁,则是不同。还是A,B两个对象,如果A正在访问对象锁修饰的function,那么这个时候B也可以同时访问。对于对象锁,当一个对象拥有锁之后,访问一个加了对象锁的方法,而该方法中又调用了该类中其他加了对象锁的方法,那么这个时候是不会阻塞住的。这是java通过可重入锁机制实现的。可重入锁指的是当一个对象拥有对象锁之后,可以重复获取该锁。因为synchronized块是可重入的,所以当你访问一个对象锁的方法的时候,在该方法中继续访问其他对象锁方法是不会被阻塞的。可重入锁,也叫做递归锁,指的是同一线程 外层函数获得锁之后 ,内层递归函数仍然有获取该锁的代码,但不受影响。

● Java中完成多态的机制是什麼;1 重载:有同样的方法名称不同的参数列表。a(){} a(String b){}...2 重写(也称覆盖):即可以重新编写与父类同名方法形象的称之为重写(覆盖)。● 如何将一个Java对象序列化到文件里;

使用ObjectOutputStream和ObjectInputStream来进行对象的读取; 使用ObjectOutputStream对象的writeObject()方法来进行对象的写入;

使用ObjectInputStream对象的readObject()方法来读取对象

● 说说你对Java反射的了解; 答:Java 中的反射首先是可以获取到Java 中要反射类的字节码, 获取字节码有三种办法

方式一,使用类的class属性:Class<java.util.Date> clz1 = java.util.Date.class;

方式二,通过Class类中的静态方法forName(String className),传入类的全限定名(必须添加完整包名)Class<?> clz2 = Class.forName(“java.util.Date”);

方式三,通过对象的getClass方法来实现,其中,getClass()Object类中的方法,所有的对象都可以调用该方法java.util.Date str = new java.util.Date();

Class<?> clz3 = str.getClass()

;● 在Java中wait和seelp办法的不同;

答:最大的不同是在等候时wait 会释放锁,而sleep 不断持有锁。wait 通常被用于线程间交互,sleep 通常被用于暂停执行。

● ThreadLocal原理,完成及如何保证Local属性;在同步机制中,通过对象的锁机制保证同一时间只有一个线程访问变量。这时该变量是多个线程共享的,使用同步机制要求程序慎密地分析什么时候对变量进行读写,什么时候需要锁定某个对象,什么时候释放对象锁等繁杂的问题,程序设计和编写难度相对较大。  而ThreadLocal则从另一个角度来解决多线程的并发访问。ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的变量封装进ThreadLocal。和锁的区别:一个是锁机制进行时间换空间,一个是存储拷贝进行空间换时间工作中用途:日志记录使用了拦截器,所以需要在拦截器中访问到需要记录的值。我把要记录的值放在ThreadLocal中。。

● String StringBuilder StringBuffer比照;1.如果要操作少量的数据用 = String 字符串常量2.单线程操作字符串缓冲区 下操作大量数据 = StringBuilder 字符串变量3.多线程操作字符串缓冲区 下操作大量数据 = StringBuffer 字符串变量● 你所晓得的设计形式有哪些; 答:Java 中普通以为有23 种设计形式创立型形式,共五种:工厂办法形式、笼统工厂形式、单例形式、建造者形式、原型形式。构造型形式,共七种:适配器形式、装饰器形式、代理形式、外观形式、桥接形式、组合形式、享元形式。行爲型形式,共十一种:战略形式、模板办法形式、察看者形式、迭代子形式、责任链形式、命令形式、备忘录形式、形态形式、拜访者形式、中介者形式、解释器形式。Java如何调用c、c++言语JNI就是一个允许Java语言和其他编程语言(主要是C/C++)通信的接口。C/C++是系统级的编程语言, 可以用来开发任何和系统相关的程序和类库, 但是Java本身编写底层的应用比较难实现, 使用JNI可以调用现有的本地库, 极大地灵活了Java的开发. C/C++的效率是目前最好的语言, 可以使用C/C++来实现一些实时性非常高的部分. C/C++和Java本身都是非常流行的编程语言, 一些大型软件中经常使用语言之间的混合编程。一旦使用JNI, JAVA程序就丧失了JAVA平台的两个优点: 程序不在跨平台。要想跨平台,必须在不同的系统环境中重新编译本地语言部分;程序不再是绝对安全的,本地代码的不当使用可能导致整个陈旭崩溃。一个通用的规则是,你应该让本地方法集中在少数几个类当中,这样就降低了Java语言和C/C++之间的耦合性。使用JNI实现Java与C语言混合编程的基本步骤如下:编写带有native声明的方法的java类使用javac命令编译所有的java类然后使用javah + 类名生成扩展名为.h的头文件使用C/C++实现本地方法

将C/C++编写的文件生成动态链接库

● 接口与回调;回调的原理;写一个回调demo; 有一天小王遇到一个很难的问题,问题是“1 + 1 = ?”,就打电话问小李,小李一下子也不知道,就跟小王说,等我办完手上的事情,就去想想答案,小王也不会傻傻的拿着电话去等小李的答案吧,于是小王就对小李说,我还要去逛街,你知道了答案就打我电话告诉我,于是挂了电话,自己办自己的事情,过了一个小时,小李打了小王的电话,告诉他答案是2。 使用异步线程实现 ● 泛型原理,举例阐明;解析与分派; 泛型是Java 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。 泛型在使用中还有一些规则和限制:  1、泛型的类型参数只能是类类型(包括自定义类),不能是简单类型。 2、同一种泛型可以对应多个版本(因为参数类型是不确定的),不同版本的泛型类实例是不兼容的。 3、泛型的类型参数可以有多个。 4、泛型的参数类型可以使用extends语句,例如。习惯上成为“有界类型”。 5、泛型的参数类型还可以是通配符类型 ● 抽象类与接口的区别;使用场景;抽象类能否可以没无方法和属性(可以); 1) 在抽象类中可以写非抽象的方法,从而避免在子类中重复书写他们,这样可以提高代码的复用性,这是抽象类的优势;接口中只能有抽象的方法。 2) 一个类只能继承一个直接父类,这个父类可以是具体的类也可是抽象类;但是一个类可以实现多个接口。 接口是对动作的抽象,而抽象类是对根源的抽象 抽象类主要是用来抽象类别,接口主要是用来抽象方法功能。当你关注事物的本质的时候,请用抽象类;当你关注一种操作的时候,用接口。 抽象类的功能应该要远多于接口,但是定义抽象类的代价较高。因为高级语言一个类只能继承一个父类,即你在设计这个类的时候必须要抽象出所有这个类的子类所具有的共同属性和方法;但是类(接口)却可以继承多个接口,因此每个接口你只需要将特定的动作方法抽象到这个接口即可。也就是说,接口的设计具有更大的可扩展性,而抽象类的设计必须十分谨慎。 ● 静态属性和静态办法能否可以被承继?能否可以被重写 java中静态属性和和静态方法可以被继承,但是没有被重写(overwrite)而是被隐藏 重写的功能是:“重写”后子类的优先级要高于父类的优先级,但是“隐藏”是没有这个优先级之分的。 ● Java的异常体系; ● 如何控制某个办法允许并发访问线程的个数; Semaphore semaphore = new Semaphore(5,true); semaphore.acquire(); 构造函数创建了一个 Semaphore 对象,并且初始化了 5 个信号。这样的效果是控件 test 方法最多只能有 5 个线程并发访问,对于 5 个线程时就排队等待,走一个来一下; ● 静态代理和动态代理的区别,什麼场景运用;           一般来说,动态代理用的场合比较多,比如spring的事务管理、AOP等都是动态代理。代理模式可以在不更改原始类的情况下实现额外的处理工作,比如日志、参数修改等, 也就是我们常听到的AOP概念 了,用好了代理模式其实是可以为我们做很多事情的。 ● jvm运转时数据区域有哪几局部组成,各自作用 ;

线程共享区:堆 可能出现的异常   实现堆可以是固定大小的,也可以通过设置配置文件设置该为可扩展的。   如果堆上没有内存进行分配,并无法进行扩展时,将会抛出OutOfMemoryError异常。 当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常。 线程独占区:栈 可能出现的异常   如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常。  如果在动态扩展内存的时候无法申请到足够的内存,就会抛出OutOfMemoryError异常。 ● gc算法有哪些 ; gc搜集器有哪些 ; 1、引用计数(reference counting) 2、复制(copying) 3、标记-清扫(Mark-and-sweep) 4、标记-压缩(Mark-Compact) 5、分代(generational collecting) 导致Gc的情况: 1、tenured被写满 2、perm被写满 3、System.gc()的显式调用。 4、上一次GC之后heap的各域分配策略动态变化。 ● 简述class加载各阶段进程 ; class ; loader有哪些模型 ; ● 简述常用的JDK命令行工具 ; ● 简述字节码文件组成 ; ● 讲讲你往常是如何针对详细的SQL做优化 ; ● mysql的存储引擎有哪些,区别 ; ● gc:内存模型; ● gc: 渣滓回收 ; ● 多线程:如何完成一个定时调度和循环调度的工具类。但提交义务处置不过去的时分,回绝机制应该如何处置 ; 线程池默许有哪几种回绝机制 ; ● 多线程: 如何完成一个ThreadLocal ; ● 说说你理解的一个线程平安队列 ; ● Atomic包的完成原理是什麼 ; ● CAS又是怎样保证原子性的 ; ● string剖析1000次循环subString用了多少内存 ;









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值