Java面试基础4(集合&IO)

57、介绍 Collection框架的结构
 
---|Collection: 单列集合
---|List: 有存储顺序, 可重复
---|ArrayList: 数组实现, 查找快, 增删慢
               由于是数组实现, 在增和删的时候会牵扯到数组
增容, 以及拷贝元素. 所以慢。数组是可以直接
按索引查找, 所以查找时较快
---|LinkedList: 链表实现, 增删快, 查找慢
               由于链表实现, 增加时只要让前一个元素记住自
己就可以, 删除时让前一个元素记住后一个元
素, 后一个元素记住前一个元素. 这样的增删效
率较高但查询时需要一个一个的遍历, 所以效率
较低
---|Vector: 和ArrayList原理相同, 但线程安全, 效率略低
               和ArrayList实现方式相同, 但考虑了线程安全问
题, 所以效率略低
---|Set: 无存储顺序, 不可重复
---|HashSet
---|TreeSet
---|LinkedHashSet
---| Map: 键值对
---|HashMap
---|TreeMap
---|HashTable
---|LinkedHashMap




58、Collection框架中实现比较要实现什么接口
 comparable/comparator


59、ArrayList 和 Vector的区别
   都实现了list接口,都是有序集合,数据允许重复。
ArrayList:线程不安全,当存储元素的个数超过容量时,ArrayList增加原来的0.5倍。
Vector:线程安全,当存储元素的个数超过容量时,vector增加原来的一倍。


60、HashMap和 Hashtable的区别
  HashMap:线程不安全的,可以将空值作为一个表的条目的key或value,是HashTable的轻量级封装。
  Hashtable:线程安全的。


61、List和 Map区别?
  List是存储单例数据的集合,Map是存储键和值这样的双列数据的集合。List中存取的数据是有序的,且允许重复;Map中存储的数据是没有顺序的,键不能重复,值可以重复。


62、List, Set, Map是否继承自 Collection 接口?
 List、Set是,Map不是。


63、List、Map、Set三个接口,存取元素时,各有什么特点?
     首先,List 与Set 具有相似性,它们都是单列元素的集合,所以,它们有一个功共同的父接口,叫Collection。Set 里面不允许有重复的元素,所谓重复,即不能有两个相等(注意,
不是仅仅是相同)的对象,即假设Set 集合中有了一个A 对象,现在我要向Set 集合再存入一个B 对象,但B 对象与A 对象equals 相等,则B 对象存储不进去,所以,Set 集合的add 方法有一个boolean 的返回值,当集合中没有某个元素,此时add 方法可成功加入该元素时,则返回true,当集合含有与某个元素equals 相等的元素时,此时add 方法无法加入该元素,返回结果为false。Set 取元素时,没法说取第几个,只能以Iterator 接口取得所有的元素,再逐一遍历各个元素。
      List 表示有先后顺序的集合,注意,不是那种按年龄、按大小、按价格之类的排序。当我们多次调用add(Obj e)方法时,每次加入的对象就像火车站买票有排队顺序一样,按先来后到的顺序排序。有时候,也可以插队,即调用add(int index,Obj e)方法,就可以指定当前对象在集合中的存放位置。一个对象可以被反复存储进List 中,每调用一次add 方法,这个对象就被插入进集合中一次,其实,并不是把这个对象本身存储进了集合中,而是在集合中用一个索引变量指向这个对象,当这个对象被add 多次时,即相当于集合中有多个索引指向了这个对象。List 除了可以以Iterator 接口取得所有的元素,再逐一遍历各个元素之外,还可以调用get(index i)来明确说明取第几个。
      Map 与List 和Set 不同,它是双列的集合,其中有put 方法,定义如下:put(objkey,objvalue),每次存储时,要存储一对key/value,不能存储重复的key,这个重复的规则也是按equals 比较相等。取则可以根据key 获得相应的value,即get(Object key)返回值为key 所对应的value。另外,也可以获得所有的key 的结合,还可以获得所有的value的结合,还可以获得key 和value 组合成的Map.Entry 对象的集合。
      List 以特定次序来持有元素,可有重复元素。Set 无法拥有重复元素,内部排序。Map 保存key-value 值,value 可多值。


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


65、去掉一个 Vector集合中重复的元素
 方法一:
Vector newVector=new Vector();
for(int i=0;i<vector.size();i++){
 Object obj=vector.get(i);
 if(!newVector.contains(obj)){
   newVector.add(obj);
 }
}


方法二:
HashSet set=new HashSet(vector);


66、Collection和 Collections的区别。
Collection是集合类的根接口,collections是一个工具类,提供一系列的方法对集合进行搜索、排序、线程安全化等操作。


67、Set里的元素是不能重复的,那么用什么方法来区分重复与否呢?是用==还是 equals()?它们有何区别?
   ==是用来判断两者是否是同一对象(同一事物),而equals是用来判断是否引用同一个对象。再看一下Set里面存的是对象,还是对象的引用。根据java的存储机制可知,set里面存放的是对象的引用,所以当两个元素只要满足了equals()时就已经指向同一个对象,也就出现了重复元素。所以应该用equals()来判断。


68、你所知道的集合类都有哪些?主要方法?
最常用的集合类是List 和Map。List 的具体实现包括ArrayList 和Vector,它们是可变大小的列表,比较适合构建、存储和操作任何类型对象的元素列表。
List 适用于按数值索引访问元素的情形。
    Map 提供了一个更通用的元素存储方法。Map 集合类用于存储元素对(称作"键"和"值"),其中每个键映射到一个值。


69、两个对象值相同(x.equals(y) == true),但却可有不同的 hash code,这句话对不对?
   对。如果对象要保存在HashSet 或HashMap 中,它们的equals 相等,那么它们的hashcode值就必须相等。如果不是要保存在HashSet或HashMap,则与hashcode没有什么关系了,这时候hashcode不等是可以的,例如arrayList 存储的对象就不用实现hashcode,当然,我们没有理由不实现,通常都会去实现的。


70、TreeSet里面放对象,如果同时放入了父类和子类的实例对象,那比较时使用的是父类的 compareTo方法,还是使用的子类的 compareTo方法,还是抛异常!
当前的add 方法放入的是哪个对象,就调用哪个对象的compareTo 方法,至于这个compareTo 方法怎么做,就看当前这个对象的类中是如何编写这个方法。


71、说出一些常用的类,包,接口,请各举5个
   常用的类:BufferedReader 、BufferedWriter、 FileReader 、FileWirter 、String 、Integer、java.util.Date、System、Class、List、HashMap
常用的包:java.lang 、java.io、 java.util
java.sql、javax.servlet、org.apache.strtuts.action、org.hibernate
常用的接口:Remote List Map Document
NodeList,Servlet,HttpServletRequest,HttpServletResponse,Transaction(Hibernate)、Session(Hibernate),HttpSession


72、java中有几种类型的流?JDK为每种类型的流提供了一些抽象类以供继承,请说出他们分别是哪些类?
字符流和字节流。字节流继承与InputStream、OutputStream,字符流继承于InputStreamReader、OutPutStreamWriter.


73、字节流与字符流的区别
要把一片二进制数据数据逐一输出到某个设备中,或者从某个设备中逐一读取一片二进制数据,不管输入输出设备是什么,我们要用统一的方式来完成这些操作,用一种抽象的方式进行描述,这个抽象描述方式起名为IO 流,对应的抽象类为OutputStream 和InputStream,不同的实现类就代表不同的输入和输出设备,它们都是针对字节进行操作的。
在应用中,经常要完全是字符的一段文本输出去或读进来,用字节流可以吗?计算机中的一切最终都是二进制的字节形式存在。对于“中国”这些字符,首先要得到其对应的字节,然后将字节写入到输出流。读取时,首先读到的是字节,可是我们要把它显示为字符,我们需要将字节转换成字符。由于这样的需求很广泛,人家专门提供了字符流的包装类。
底层设备永远只接受字节数据,有时候要写字符串到底层设备,需要将字符串转成字节再进行写入。字符流是字节流的包装,字符流则是直接接受字符串,它内部将串转成字节,再写入底层设备,这为我们向IO 设别写入或读取字符串提供了一点点方便。
字符向字节转换时,要注意编码的问题,因为字符串转成字节数组,其实是转成该字符的某种编码的字节形式,读取也是反之的道理。


import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.io.PrintWriter;
public class IOTest {
public static void main(String[]args) throws Exception {
String str = "中国人";
/*FileOutputStream fos = new FileOutputStream("1.txt");
fos.write(str.getBytes("UTF-8"));
fos.close();*/


/*FileWriter fw =new FileWriter("1.txt");
fw.write(str);
fw.close();*/


PrintWriter pw=new PrintWriter("1.txt","utf-8");
pw.write(str);
pw.close();


/*FileReader fr =new FileReader("1.txt");
char[] buf = new char[1024];
int len =fr.read(buf);
String myStr = new String(buf,0,len);
System.out.println(myStr);*/


/*FileInputStream fr = new FileInputStream("1.txt");
byte[] buf = newbyte[1024];
int len =fr.read(buf);
String myStr = newString(buf,0,len,"UTF-8");
System.out.println(myStr);*/


BufferedReader br =new BufferedReader(
new InputStreamReader(
new FileInputStream("1.txt"),"UTF-8"
)
);
StringmyStr =br.readLine();
br.close();
System.out.println(myStr);
}
}


74、什么是 java序列化,如何实现 java序列化?或者请解释 Serializable接口的作用。
    我们有时候将一个java 对象变成字节流的形式传出去或者从一个字节流中恢复成一个java对象,例如,要将java 对象存储到硬盘或者传送给网络上的其他计算机,这个过程我们可以自己写代码去把一个java 对象变成某个格式的字节流再传输,但是,jre 本身就提供了这种支持,我们可以调用OutputStream 的writeObject 方法来做,如果要让java 帮我们做,要被传输的对象必须实现 serializable接口,这样,javac编译时就会进行特殊处理,编译的类才可以被writeObject 方法操作,这就是所谓的序列化。需要被序列化的类必须实现
Serializable 接口,该接口是一个mini 接口,其中没有需要实现的方法,implementsSerializable 只是为了标注该对象是可被序列化的。
      例如,在web 开发中,如果对象被保存在了Session 中,tomcat 在重启时要把Session 对象序列化到硬盘,这个对象就必须实现Serializable 接口。如果对象要经过分布式系统进行网络传输或通过rmi 等远程调用,这就需要在网络上传输对象,被传输的对象就必须实现Serializable 接口。


75、描述一下 JVM加载 class文件的原理机制?
   JVM 中类的装载是由ClassLoader 和它的子类来实现的,Java ClassLoader 是一个重要的Java 运行时系统组件。它负责在运行时查找和装入类文件的类。


76、heap和 stack有什么区别。
     java 的内存分为两类,一类是栈内存,一类是堆内存。栈内存是指程序进入一个方法时,会为这个方法单独分配一块私属存储空间,用于存储这个方法内部的局部变量,当这个方法结束时,分配给这个方法的栈会释放,这个栈中的变量也将随之释放。
堆是与栈作用不同的内存,一般用于存放不放在当前方法栈中的那些数据,例如,使用new创建的对象都放在堆里,所以,它不会随方法的结束而消失。方法中的局部变量使用 final修饰后,放在堆中,而不是栈中。


77、GC是什么?为什么要有 GC?
GC 是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java 提供的GC 功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java 语言没有提供释放已分配内存的显示操作方法。




78、垃圾回收的优点和原理。并考虑2种回收机制。

Java 语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java 程序员在编写程序的时候不再需要考虑内存管理。由于有个垃圾回收机制,Java 中的对象不再有"作用域"的概念,只有对象的引用才有"作用域"。垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。垃圾回收器通常是作为一个单独的低级别的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。回收机制有分代复制垃圾回收和标记垃圾回收,增量垃圾回收。


79、垃圾回收器的基本原理是什么?垃圾回收器可以马上回收内存吗?有什么办法主动通知虚拟机进行垃圾回收?
对于GC 来说,当程序员创建对象时,GC 就开始监控这个对象的地址、大小以及使用情况。通常,GC 采用有向图的方式记录和管理堆(heap)中的所有对象。通过这种方式确定哪些对象是"可达的",哪些对象是"不可达的"。当GC 确定一些对象为"不可达"时,GC 就有责任回收这些内存空间。可以。程序员可以手动执行System.gc(),通知GC 运行,但是Java语言规范并不保证GC 一定会执行。


80、什么时候用 assert。
   assertion(断言)在软件开发中是一种常用的调试方式,很多开发语言中都支持这种机制。在实现中,assertion 就是在程序中的一条语句,它对一个boolean 表达式进行检查,一个正确程序必须保证这个boolean 表达式的值为true;如果该值为false,说明程序已经处于不正确的状态下,assert将给出警告或退出。一般来说,assertion用于保证程序最基本、关键的正确性。assertion 检查通常在开发和测试时开启。为了提高性能,在软件发布后,assertion 检查通常是关闭的。


81、java中会存在内存泄漏吗,请简单描述。
   所谓内存泄露就是指一个不再被程序使用的对象或变量一直被占据在内存中。java 中有垃圾回收机制,它可以保证一对象不再被引用的时候,即对象编程了孤儿的时候,对象将自动被垃圾回收器从内存中清除掉。由于Java 使用有向图的方式进行垃圾回收管理,可以消除引用循环的问题,例如有两个对象,相互引用,只要它们和根进程不可达的,那么GC 也是可以回收它们的
     java 中的内存泄露的情况:长生命周期的对象持有短生命周期对象的引用就很可能发生内存泄露,尽管短生命周期对象已经不再需要,但是因为长生命周期对象持有它的引用而导致
不能被回收,这就是java 中内存泄露的发生场景,通俗地说,就是程序员可能创建了一个对象,以后一直不再使用这个对象,这个对象却一直被引用,即这个对象无用但是却无法被垃圾回收器回收的,这就是java 中可能出现内存泄露的情况,例如,缓存系统,我们加载了一个对象放在缓存中(例如放在一个全局map 对象中),然后一直不再使用它,这个对象一直被缓存引用,但却不再被使用。
检查java 中的内存泄露,一定要让程序将各种分支情况都完整执行到程序结束,然后看某个对象是否被使用过,如果没有,则才能判定这个对象属于内存泄露。


    如果一个外部类的实例对象的方法返回了一个内部类的实例对象,这个内部类对象被长期引用了,即使那个外部类实例对象不再被使用,但由于内部类持久外部类的实例对象,这个外
部类对象将不会被垃圾回收,这也会造成内存泄露。


82、能不能自己写个类,也叫 java.lang.String?

 可以,但在应用的时候,需要用自己的类加载器去加载,否则,系统的类加载器永远只是去加载jre.jar 包中的那个java.lang.String。由于在tomcat 的web 应用程序中,都是由webapp自己的类加载器先自己加载WEB-INF/classess 目录中的类,然后才委托上级的类加载器加载,如果我们在tomcat 的web 应用程序中写一个java.lang.String,这时候Servlet 程序加载的就是我们自己写的java.lang.String,但是这么干就会出很多潜在的问题,原来所有用了java.lang.String 类的都将出现问题。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值