面试题总结(3)
String:是一个固定的不可变的字符串
StringBuffer:线程安全的可变的字符序列
StringBuilder:线程不安全的可变的字符序列
(1) String和StringBuffer、StringBuilder它们可以储存和操作字符串,即包含多个字符的字符数据。String 类型和 StringBuffer 类型的主要性能区别其实在于 String 是不可变的对象, 因此在每次对 String 类型进行改变的时候其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象,所以经常改变内容的字符串最好不要用 String ,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC 就会开始工作,那速度一定会相当慢的。如果是使用 StringBuffer 类则结果就不一样了,每次结果都会对 StringBuffer 对象本身进行操作,而不是生成新的对象,再改变对象引用
(2) StringBuffer和StringBuilder中StringBuffer是线程安全的StringBuilder是线程不安全的,三者之间执行的速度是StringBuilder > StringBuffer > String;
(3)另外,String实现了equals方法,new String(“abc”).equals(new String(“abc”)的结果为true,而StringBuffer没有实现equals方法,所以new StringBuffer(“abc”).equals(new StringBuffer(“abc”)的结果为false。
数组没有length()这个方法,有length的属性。String有length()这个方法
可以更详细的叙述每个集合。
collectons : List ArrayList vector
Set HashSet TreeSet
Map: HashMap TreeMap Hashtable
Collection接口 和Map接口,是两个独立的接口,、有各自的子接口和实现类
List集合 有序的可以放重复元素
Set集合 无序的 不可以放重复元素
ArrayList和Vector基于数组,LinkedList基于链表
ArrayList和LinkedList是线程不安全的
Vector是线程安全的
1)ArrayList 和Vector底层实现是基于数组的实现,而LinkedList底层实现是基于链表的实现。
2)ArrayList和Vector 实现了List接口(List继承于Collection接口)、而LinkedList除了实现了List接口以外还实现了Deque接口。
3)他们都是有序集合,即存储在集合中的元素的位置都是有顺序的,我们以后可以按位置索引号取出某个元素,,并且其中的数据是允许重复的。
4)从同步性来说 Vector是属于线程安全的而ArrayList 和LinkedList不是线程安全的
5)从效率来说ArrayList和Vector底层属于数组 查找修改速度快 增加删除效率慢
LinkedList底层是链表 所以 增删比较快 查改 慢
6)(这个可以选择回答)从数据增长来说:ArrayList与Vector都有一个初始的容量大小,当存储进它们里面的元素的个数超过了容量时。
在jdk1.7中 ArrayList底层实现增长的方式是:
int newCapacity = oldCapacity + (oldCapacity >> 1);
Vector实现增长的方式是
int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity);
1)继承不同。
public class Hashtable extends Dictionary implements Map
public class HashMap extends AbstractMap implements Map
2)Hashtable 中的方法是同步的(线程安全的),而HashMap中的方法在缺省情况下是非同步的(线程不安全的)。在多线程并发的环境下,可以直接使用Hashtable,但是要使用HashMap的话就要自己增加同步处理了
3)Hashtable不允许使用null 作为key和value,否则会引发空指针异常,HashMap允许空(null)作为键值(key)和Value,但最多只能有一项key-value中key为null,但是key-value中可以有多个value为null
Collection是集合类的上级接口,继承于他的接口主要有Set和List.
Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。
Set里的元素是不能重复的,元素重复与否是使用equals()方法进行判断的。equals()和==方法决定引用值是否指向同一对象equals()在类中被覆盖,为的是当两个分离的对象的内容和类型相配的话,返回真值。
对。
如果对象要保存在HashSet或HashMap中,它们的equals相等,那么,它们的hashcode值就必须相等。
如果不是要保存在HashSet或HashMap,则与hashcode没有什么关系了,这时候hashcode不等是可以的,例如ArrayList存储的对象就不用实现hashcode,但是通常都会去实现的。
当前的add方法放入的是哪个对象,就调用哪个对象的compareTo方法,至于这个compareTo方法怎么做,就看当前这个对象的类中是如何编写这个方法的。
Public class Parent implements Comparable {
private int age = 0;
public Parent(int age) {
this.age = age;
}
Public int compareTo(Object o) {
System.out.println("method of parent");
Parent o1 = (Parent) o;
return age > o1.age ? 1 : age < o1.age ? -1 : 0;
}
}
public class Child extends Parent {
public Child() {
super(3);
}
publicint compareTo(Object o) {
System.out.println("methodof child");
return 1;
}
}
publicclass TreeSetTest {
public static void main(String[] args) {
TreeSet set = new TreeSet();
set.add(new Parent(3));
set.add(new Child());
set.add(new Parent(4));
System.out.println(set.size());
}
}
执行结果:
method of parent
methodof child
method of parent
method of parent
3
HashMap 输出的文本是无序的,TreeMap输出的文本是有序的
一个平衡树的性能是O(logn)。Java里的TreeMap用一个红黑树来保证key/value的排序。红黑树是平衡二叉树。保证二叉树的平衡性,使得插入,删除和查找都比较快,时间复杂度都是O(log n)。不过它没有HashMap快,HashMap的时间复杂度是O(1),但是TreeMap的优点在于它里面键值是排过序的,这样就提供了一些其他的很有用的功能。
使用无序的HashSet和HashMap,还是使用有序的TreeSet和TreeMap,主要取决于你的实际使用场景,一定程度上还和数据的大小以及运行环境有关。比较实际的一个原因是,如果插入和更新都比较频繁的话,那么保证元素的有序可以提高快速和频繁查找的性能。如果对于排序操作(例如产生一个报表合作者运行一个批处理程序)的要求不是很频繁的话,那么把数据以无序的方式存储,然后在需要排序的时候用Collections.sort(?)来进行排序,会比用有序的方式来存储可能会更加高效。这个只是一种可选的方式,没人能给你一个确切的答案。即使是复杂度的理论,例如O(n),成立的前提也是在n足够大的情况下。只要在n足够小的情况下,就算是O(n)的算法也可能会比O(log n)的算法更加高效。另外,一个算法可能在AMD处理器上的速度比在Intel处理器上快。如果你的系统有交换区的话,那么你还要考虑磁盘的性能。唯一可以确定的性能测试途径是用大小合适的数据来测试和衡量程序的性能和内存使用量。在你所选择的硬件上来测试这两种指标,是最合适的方法。