面试总结
1.jdk底下的包有哪些,这些包相应的功能有哪些?
java.lang.* 提供利用 Java 编程语言进行程序设计的基础类。最重要的类是 Object(它是类层次结构的根)。
java.util.* 实用包提供了各种实用功能的类,主要包括日期类、数据结构类和随机数类等。
java.io.* java.io提供了系统输入输出类和接口,实现对文件的输入输出,管道的数据传输以及网络数据传输的功能。
2.hashMap的底层是怎么实现的?
- 先看一下HashMap与HashTable的区别:①前者的key值和value的值允许为空(为空值时怎么存储呢??)②前者是不同步的(不同步是什么意思呢??)
- HashMap的底层主要是基于数组和链表来实现的,它之所以有相当快的查询速度主要是因为它是通过计算散列码来决定存储的位置。HashMap中主要是通过key的 hashCode来计算hash值的,只要hashCode相同,计算出来的hash值就一样。
图中,紫色部分即代表哈希表,也称为哈希数组,数组的每个元素都是一个单链表的头节点,链表是用来解决冲突的,如果不同的key映射到了数组的同一位置处,就将 其放入单链表中。
3.看源码:
HashMap其实就是一个Entry数组,Entry对象中包含了键和值,其中next也是一个Entry对象,它就是用来处理hash冲突的,形成一个链表。
static class Entry<K,V> implements Map.Entry<K,V> { final K key; V value; // 指向下一个节点 Entry<K,V> next; final int hash; }
转自:http://www.cnblogs.com/ITtangtang/p/3948406.html
3.set是如何判断重复元素的?
1. set的基本声明形式:Set<Object> set=new HashSet<Object>();若Object是基础的封装类型,如Integer,String,Double,Float等,因为这些基础的封装类已经重写了equals和hashCode()这两个方法,但是对于用户自己构建的类,比如:
package ReviewInterview;
public class Person {
private String name;
private int id;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Person(String name, int id, int age) {
super();
this.name = name;
this.id = id;
this.age = age;
}
}
对于这样的一个类,和普通的封装类型的类存在set中又会有什么样的不同呢?
2. 先看普通的封装类型存进set中:
例子:testString.java
package ReviewInterview;
import java.util.HashSet;
import java.util.Set;
public class test {
public static void main(String[] args) {
Set<String> set=new HashSet<String>();
set.add("hello");
set.add("thank");
set.add("hello");
for(String element:set){
System.out.print(element+" ");
}
}
}
运行的结果是:hello thank
再来看看对于Person这个类,存入set会怎么样呢?
例子:testPerson.java
package ReviewInterview;
import java.util.HashSet;
import java.util.Set;
public class testPerson {
public static void main(String[] args) {
Set<Person> set=new HashSet<Person>();
set.add(new Person("张三",001,25));
set.add(new Person("李四",002,35));
set.add(new Person("王五",003,45));
set.add(new Person("王五",003,45));
for(Person element:set){
System.out.println(element+" ");
}
}
}
输出的结果竟然是:
ReviewInterview.Person@544a5ab2
ReviewInterview.Person@152b6651
ReviewInterview.Person@6bbc4459
ReviewInterview.Person@5d888759
其实这就是下面的问题,toString的用法,可以通过查阅JavaAPI中Object类,有个方法就是toString,也就是说所有继承自Obeject的类中都有toString方法
public string toString(){
return getClass().getName() + '@' + Integer.toHexString(hashCode())
}
所以这个类也不例外输出的就是上面的内容。我们在Person中重写一下toString的方法:
@Override
public String toString() {
return "Person [name=" + name + ", id=" + id + ", age=" + age + "]";
}
这时候运行的结果:
Person [name=王五, id=3, age=45]
Person [name=李四, id=2, age=35]
Person [name=张三, id=1, age=25]
Person [name=王五, id=3, age=45]
怎么会有两个王五?set不是没有重复的吗?这就是这个问题的关键,set中是如何去掉重复元素的?通过equals的方式来去掉重复的元素,对于普通的封装类型来说equals
但是在Person这类中没有重写equals,所以加入重写的方法:
@Override//覆盖Object类中的hashCode()方法
public int hashCode() {
return this.name.hashCode()*this.id*this.age;//产生一个独有的hashcode
}
@Override//覆盖Object类中的equals()方法
public boolean equals(Object obj) {
if(this==obj){
return true;
}
if(!(obj instanceof Person)){
return false;
}
Person Person2=(Person)obj;
if(this.name.equals(Person2.name)&&this.id==(Person2.id)&&this.age==Person2.age){
return true;
}
else{
return false;
}
}
之后,运行的结果就是:
Person [name=张三, id=1, age=25]
Person [name=李四, id=2, age=35]
Person [name=王五, id=3, age=45]
所以得出结论:JVM通过类中hashCode()、equals()两个方法来判断两个对象是否是同一个对象。当然set也是这样的。
4.map,list和set的区别?
map:存入的是健值对<key,value>,key值无重复,且支持null,null这样的存储。底层实现是数组+链表这种数据结构实现,包含HashMap,TreeMap(已经排序)
list:LinkedList底层链表实现,增删快,查找慢。ArrayList和Vector底层数组实现,ArrayList非线程安全,Vector线程安全。
set:集合,数据无序且无重复
5.基本类型和封装类的区别?我如何确定使用哪一种?
①基本数据类型只能按值传递,封装类按引用(地址)传值。
②某些情况下,数据必须作为对象出现,此时必须使用封装类来将简单类型封装成对象。
- 比如,如果想使用List来保存数值,由于List中只能添加对象,因此我们需要将数据封装到封装类中再加入List。在JDK5.0以后可以自动封包,可以简写成 list.add(1)的形式,但添加的数据依然是封装后的对象。
- 另外,有些情况下,我们也会编写诸如func(Object o)的这种方法,它可以接受所有类型的对象数据,但对于简单数据类型,我们则必须使用封装类的对象。
③某些情况下,使用封装类使我们可以更加方便的操作数据。比如封装类具有一些基本类型不具备的方法,比如valueOf(), toString(), 以及方便的返回各种类型数据的方 法,如Integer的shortValue(), longValue(), intValue()等。
6.说说你对java中Object类的理解。
Object是所有类的父类,它有很多类对象会用到的方法,例如比较常用的toString 、equals,当你新建xx类时,你可以重写Object已经定义的方法,也可以直接调用 Object 中的方法,如果你写一个封装的方法,不确定传进来的是什么类型的值,就可以使用Object作为一个笼统类
7.toString方法的作用。
public string toString(){
return getClass().getName() + '@' + Integer.toHexString(hashCode())
}
toString是Object类的方法,所有类都从Object类继承。如果你定义的类没有覆盖toString方法,则对象在调用toString方法时用的是Object类toString方法,返回的是“类名@hashcode".
System.out.println(obj)在参数是一个对象时,会首先调用该对象的toString方法。
8.equals和“==”的区别。
“==”用于基础数据类型的时候是直接比较两个值是否相同,用于引用数据类型时是比较两个引用的地址是否相同,也就是是否指向同一个对象。
“equals”用于比较字符串的字符序列是否相同。
例子:
String str1="abcd";
String str2="abcd";
String str3=new String("abcd");
String str4=new String("abcd");
System.out.println(str1==str2); //true
System.out.println(str1==str3); //false
System.out.println(str1.equals(str2)); //true
System.out.println(str1.equals(str3)); //true
System.out.println(str3.equals(str4)); //true
System.out.println(str3==str4); //false