面试题整理(2)

1.什么是迭代器?

Iterator接口提供了很多对集合进行迭代的方法。每一个集合类都包含了可以返回迭代器实例的迭代方法。

迭代器可以在迭代过程中删除底层集合的元素,但是不可以直接调用集合的remove(Object obj)删除,可以通过迭代器的remove()方法删除。

2.ArrayList和LinkedList有什么区别?

ArrayList是基于索引的数据接口,它的底层是数组。它可以以O(1)时间复杂度对元素进行随机访问。与此对应,LinkedList是以元素列表的形式存储它的数据,每一个元素都和它的前一个和后一个元素链接在一起,在这种情况下,查找某个元素的时间复杂度是O(n)。

相对于ArrayList,LinkedList的插入,添加,删除操作速度更快,因为当元素被添加到集合任意位置的时候,不需要像数组那样重新计算大小或者是更新索引。

LinkedList比ArrayList更占内存,因为LinkedList为每一个节点存储了两个引用,一个指向前一个元素,一个指向下一个元素。

3.HashSet和TreeSet有什么区别?

HashSet是由一个hash表来实现的,因此,它的元素的无序的。add(),remove(),contain()方法的时间复杂度是O(1)。

TreeSet是由一个树形的结构来实现的,它里面的元素是有序的。add(),remove(),contains()方法的时间复杂度是O(logn)。

4.数组(Array)和列表(ArrayList)有什么区别?什么时候应该使用Array而不是ArrayList?

Array可以包含基本类型和对象类型,ArrayList只能包含对象类型;

Array的大小是固定的,ArrayList的大小是动态变化的;

ArrayList提供了更多的方法和特性,如:addAll(),removeAll(),iterator()等;

对于基本数据类型,集合使用自动装箱来减少编码工作量。但是,当处理固定大小的基本数据类型的时候,这种方式相对比较慢。

5.Java中的两种异常类型是什么?他们有什么区别?

Java中有两种异常:受检查的(checked)异常和不受检查的(unchecked)异常。不受检查的异常不需要在方法或者是构造函数上声明,就算方法或者是构造函数的执行可能会抛出这样的异常,并且不受检查的异常可以传播到方法或者是构造函数的外面。相反,受检查的异常必须要用throws语句在方法或者是构造函数上声明。

6.Java中Exception和Error有什么区别?

Exception和Error都是Throwable的子类。Exception用于用户程序可以捕获的异常情况。Error定义了不期望被用户程序捕获的异常。

7.throw和throws有什么区别?

throws是用来声明一个方法可能抛出的所有异常信息,throws是将异常声明但是不处理,而是将异常往上传,谁调用我就交给谁处理。而throw则是指抛出的一个具体的异常类型。

throw:就是自己进行异常处理,处理的时候有两种方式,要么自己捕获异常(也就是try catch进行捕捉),要么声明抛出一个异常。throw一旦进入被执行,程序立即会转入异常处理阶段,后面的语句就不再执行,而且所在的方法不再返回有意义的值.

8.请说出ArrayList,Vector, LinkedList的存储性能和特性

ArrayList 和 Vector 都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector 由于使用了 synchronized 方法(线程安全),通常性能上较 ArrayList 差,而LinkedList 使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。

9.Set和List的区别

List:列表。
          特点:

     1,有序(存储元素的顺序和取出元素的顺序一致)

     2,该集合中的元素都有索引,所以可以通过索引(角标)来访问元素。 
     3,它可以存储重复元素。 

 常见子类对象:记住:具体的子类对象,我们要学习应该是该对象的特有的数据结构,以及相关的特点。
        |--Vector:jdk1.0就存在了。底层是数组结构的。可变长度数组,
              原理:一旦原数组长度不够,会创建新数组,将原数组的元素复制到新数组中,并将新元素添加到新数组中。
             Vector是同步的。
        |--ArrayList:底层是数组结构,也是支持长度可变数组的。是不同步的。替代了Vector.因为效率高。 查询效率很高。 但是增删的效率很低。
        |--LinkedList:底层是链接列表结构,简称链表结构。是不同步的。这个中结构的好处:对元素的增删非常效率很高。 查询的效率很低。
      Set:集:中的方法和Collection一致,只要重点注意它的子类对象即可。取出元素只能使用迭代器。
       特点:
       1,不包含重复元素。(最大的特点)
       2,这个集合存入元素的顺序和取出元素的顺序不一定一致。(具体的容器对象数据结构不同,顺序也有不同)
       |--HashSet:底层数据结构是哈希表,不保证顺序,是不同步的。
           哈希表:提供数组的查询效率而出现的。
          将要存储的元素先通过哈希算法算出一个哈希值来标识存储的位置,代表着元素。要找元素时,先将该元素通过哈希算法算出哈希值,在通过哈希值到哈希表中去查找。
           特点:
            1,不关系元素的顺序。
            2,提高了查询效率。
             3,不可能出现重复元素,因为哈希值都不同。即使相同,会再次判断两个元素的equals,内容是否相同。
            如果内容也相同,不存,如果内容不同,存储。所以哈希表要保证元素的唯一性,必须要依赖于两个方法。
            1,hashCode 2,equals                
       |--TreeSet:可以给Set集合中的元素进行指定顺序的排序。非同步的。 
            默认情况下,是通过元素的自然顺序排的序。
           它保证元素唯一性的依据是看比较方法的返回结果是否是0.是0.就视为元素相同。不存。
         TreeSet排序的方式一:让元素自身具备比较性,需要实现Comparable接口,覆盖compareTo方法。这种比较方式成为自然顺序排序。如果元素自身不具备比较性或者具备的比较性(自然顺序)不是所需要的。
            这时只能用第二种方式 。
            TreeSet排序的方式二:让容器自身具备比较性。容器一初始化就具备了比较功能。因为容器时在对象构造时完成的。通过查阅,有一个构造方法TreeSet(Comparator).在容器初始化时可以指定一个比较器。 需要实现Comparator接口,覆盖compare方法即可。所以这种方式成为比较器排序。 当存入的的对象有重复时,用List,没有重复元素时,用Set

 10."=="操作符与equals的区别

对于值类型:“==”比较数值是否相等,值类型没有equals方法

对于引用类型:如果该类型没有重载equals方法,则“==”和“equals”方法返回的结果一致,即比较两个变量引用的地址是否相等。如果重载了equals方法,则equals方法的行为需要看重载方法的具体定义,“==”依然比较的是两个变量的引用地址,如果“==”返回true则equals应该也会返回true(正确实现了equals),反之则不一定

11.多线程的优缺点是什么?

优点:

(1)多线程技术使程序的响应速度更快 ,因为用户界面可以在进行其它工作的同时一直处于活动状态;

(2)当前没有进行处理的任务时可以将处理器时间让给其它任务;

(3)占用大量处理时间的任务可以定期将处理器时间让给其它任务;

(4)可以随时停止任务;

(5)可以分别设置各个任务的优先级以优化性能。

是否需要创建多个线程取决于各种因素。在以下情况下,最适合采用多线程处理:

(1)耗时或大量占用处理器的任务阻塞用户界面操作;

(2)各个任务必须等待外部资源 (如远程文件或 Internet连接)。

同样的 ,多线程也存在许多缺点 ,在考虑多线程时需要进行充分的考虑。多线程的主要缺点包括:

(1)等候使用共享资源时造成程序的运行速度变慢。这些共享资源主要是独占性的资源 ,如打印机等。

(2)对线程进行管理要求额外的 CPU开销。线程的使用会给系统带来上下文切换的额外负担。当这种负担超过一定程度时,多线程的特点主要表现在其缺点上,比如用独立的线程来更新数组内每个元素。

(3)线程的死锁。即较长时间的等待或资源竞争以及死锁等多线程症状。

(4)对公有变量的同时读或写。当多个线程需要对公有变量进行写操作时,后一个线程往往会修改掉前一个线程存放的数据,从而使前一个线程的参数被修改;另外 ,当公用变量的读写操作是非原子性时,在不同的机器上,中断时间的不确定性,会导致数据在一个线程内的操作产生错误,从而产生莫名其妙的错误,而这种错误是程序员无法预知的。

12.IO流按照流向分 按照处理内容分?字节流都有哪些方法?

[ 输入流---输出流 ]

按照流的流向,可以将流分为输入流和输出流。

输入流:从其中读取数据

输出流:向其种写入数据

注意:划分输入/输出流是从程序运行时的所在的内存的角度来划分的。

输入流常用的基础类:InputStream和Reader

输出流常用的基础类:OutputStream和Writer

注意:这些都是抽象类,无法直接实例化。

[ 字节流---字符流 ]

字节流和字符流的内的方法几乎一样,区别仅仅是其操作的数据单元大小不同,

字节流的数据操作单元: 8位的字节

字符流的数据操作单元: 16位的字节

字节流常用的基础类:InputStream和OutputStream

字符流常用的基础类:Reader和Writer

14.java里final finally finalize区别?

final用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可以被继承;

finally是异常处理语句的一部分,表示总是会被执行

finalize是Object类的一个方法,在垃圾收集器执行的时候回调用被回收对象的此方法,可以覆盖此方法提供垃圾收集是的其他资源回收,列如关闭文件等。

final—修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承。因此一个类不能既被声明为 abstract的,又被声明为final的。将变量或方法声明为final,可以保证它们在使用中不被改变。被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取,不可修改。被声明为final的方法也同样只能使用,不能重载。
       finally—在异常处理时提供 finally 块来执行任何清除操作。如果抛出一个异常,那么相匹配的 catch 子句就会执行,然后控制就会进入 finally 块(如果有的话)。
       finalize—方法名。Java 技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在 Object 类中定义的,因此所有的类都继承了它。子类覆盖 finalize() 方法以整理系统资源或者执行其他清理工作。finalize() 方法是在垃圾收集器删除对象之前对这个对象调用的。

15.正则符号的总结

正则的功能:

字符串的匹配、切割、替换

正则的符号:

. 表示任意的字符

() 对已经存在的正则进行分组 同一正则引入组 \编号 ,不同 $编号

[] 某个字符串位置上可以出现的字符列表

{}当前某个正则规则出现的次数

? 表示当前的规则可以出现零次或一次

* 表示当前的规则可以出现零次或多次   

+ 表示当前的规则可以出现一次或多次

^ 行开始

$ 行结尾

d 数字字符

w 数字 字母 下划线


本博客文章均已测试验证,欢迎评论、交流、点赞。
部分文章来源于网络,如有侵权请联系删除。
转载请注明原文链接:https://www.cnblogs.com/sueyyyy/p/9260992.html

原文地址:https://www.cnblogs.com/sueyyyy/p/9260992.html