Java面试基础二——集合相关
文章开始把我喜欢的这句话送个大家:这个世界上还有什么比自己写的代码运行在一亿人的电脑上更酷的事情吗,如果有那就是让这个数字再扩大十倍
1.add与addAll
如果有多个已经被实例化的List 集合,想要把他们组合成一个整体,并且,这里必须直接使用List 自身提供的一个方法List.addAll(),否则使用了List.add()方法,则会输出不正常的信息。add是将传入的参数作为当前List中的一个Item存储,即使你传入一个List也只会另当前的List增加1个元素
addAll是传入一个List,将此List中的所有元素加入到当前List中,也就是当前List会增加的元素个数为传入的List的大小
List.add(list1),List.add(list2);List.add(list3), 这时,List.size 它的大小是3。
List.add(list1),List.add(list2);List.add(list3), 这时,List.size 它的大小就是所有list 实例化后的总数和总的记录数。
2.Collection的iterator()方法:遍历过程不能更改
Iterator it = collection.iterator();
while(it.hasNext()){
Object obj= it.next();
}
Collection接口的派生接口list和set
list:listIterator()多了一些add之类的方法允许添加删除设定元素还能向前向后遍历
list 接口的实现类:LinkedList ArrayList Vector Stack
(1)LinkedList :允许null,允许在首部和尾部操作可作为Stack(堆栈)queue(队列)deque(双向队列)LinkedList无同步方法需要在创建时自己实现:
List list = Collections.synchronizeList(new LinkedList())
(2)ArrayList实现了可变大小的数组,允许null,未实现同步
(3)Vector同步的
(4)Stack继承自vector 实现了堆栈
Set接口:不能重复
Map接口:没有继承Collection接口
(1)Hashtable继承自Map接口,同步的,不允许null value null key实现了一个key到value的哈希表
get和put 操作的时间复杂度为常数loadfactor 参数初始值为0.75较好的均衡了空间和时间,增大loadfactor 会减少空间但查找时间会增加
必须实现hashCode() equals()方法
(2)HashMap类:非同步的,允许null value null key
(3)WeakHashMap类:对key实施弱引用,如果key不再被外部引用可以被GC 回收
总结:
如果需要堆栈队列等应该使用list,需要快速插入删除应使用LinkedList需要快速随机访问元素用ArrayList,
返回应尽可能返回接口而非实际的类型,方便以后更改,客户端代码不需要改变。
1.Comparable与Comparator的区别
Comparable是排序接口。若一个类实现了Comparable接口,就意味着该类支持排序。实现了Comparable接口的类的对象的列表或数组可以通过Collections.sort或Arrays.sort进行自动排序。
Comparator是比较接口,我们如果需要控制某个类的次序,而该类本身不支持排序(即没有实现Comparable接口),那么我们就可以建立一个“该类的比较器”来进行排序,这个“比较器”只需要实现Comparator接口即可。也就是说,我们可以通过实现Comparator来新建一个比较器,然后通过这个比较器对类进行排序。该接口定义如下:
packagejava.util;
publicinterfaceComparator<T>
{
intcompare(T o1, T o2);
booleanequals(Object obj);
}
注意:1、若一个类要实现Comparator接口:它一定要实现compare(T o1, T o2) 函数,但可以不实现equals(Object obj) 函数。
2、int compare(T o1, T o2) 是“比较o1和o2的大小”。返回“负数”,意味着“o1比o2小”;返回“零”,意味着“o1等于o2”;返回“正数”,意味着“o1大于o2”。
现在假如上面的Person类没有实现Comparable接口,该如何比较大小呢?我们可以新建一个类PersonCompartor,让其实现Comparator接口,从而构造一个“比较器"。
publicclassPersonCompartor implementsComparator<Person>
{
@Override
publicintcompare(Person o1, Person o2)
{
returno1.getAge()-o2.getAge();
}
}
Comparable和Comparator区别总结
Comparable是排序接口,若一个类实现了Comparable接口,就意味着“该类支持排序”。而Comparator是比较器,我们若需要控制某个类的次序,可以建立一个“该类的比较器”来进行排序。
Comparable相当于“内部比较器”,而Comparator相当于“外部比较器”。
两种方法各有优劣,用Comparable 简单,只要实现Comparable 接口的对象直接就成为一个可以比较的对象,但是需要修改源代码。用Comparator 的好处是不需要修改源代码,而是另外实现一个比较器,当某个自定义的对象需要作比较的时候,把比较器和对象一起传递过去就可以比大小了,并且在Comparator 里面用户可以自己实现复杂的可以通用的逻辑,使其可以匹配一些比较简单的对象,那样就可以节省很多重复劳动了。
2.集合常用
Set mySet = new HashSet()
List myList = new ArrayList()
Queue myQueue = new LinkedList()
ArrayList 和Vector的区别vector是同步的也就是线程安全的适用于多线程ArrayList是非同步的也就是线程不安全的适用于单线程,且vector比ArrayList 多一个可以指定空间不够时扩容的参数的构造方法
vector默认扩容为2倍,ArrayList 默认扩容为1.5倍
3.从JVM的角度看,我们使用关键字new创建一个类的时候,这个类可以没有被加载。但是使用newInstance()方法的时候,就必须保证:1、这个类已经加载;2、这个类已经连接了。而完成上面两个步骤的正是Class的静态方法forName()所完成的,这个静态方法调用了启动类加载器,即加载java API的那个加载器。
Java中工厂模式经常使用newInstance()方法来创建对象,因此从为什么要使用工厂模式上可以找到具体答案。例如:
class c = Class.forName(“Example”);
factory = (ExampleInterface)c.newInstance();
其中ExampleInterface是Example的接口,可以写成如下形式:
String className = "Example";
class c = Class.forName(className);
factory = (ExampleInterface)c.newInstance();
进一步可以写成如下形式:
String className = readfromXMlConfig;//从xml 配置文件中获得字符串
class c = Class.forName(className);
factory = (ExampleInterface)c.newInstance();
上面代码已经不存在Example的类名称,它的优点是,无论Example类怎么变化,上述代码不变,甚至可以更换Example的兄弟类Example2 , Example3 , Example4……,只要他们继承ExampleInterface就可以
最常用:Object obj = Class.forName(s).newInstance()
网上有种说法说newinstance只能调用无参构造,从上面例子中可以看出并不是这样。
4.==判断两个对象的地址,基础类型的值
integer 400 ==int 400//true拆箱
integer 400.equals(int 400)//true装箱
陷阱
(1)注意integer 对象是否为null
Integer i1=null
int i=i1//抛出异常
(2)IntegerCache-128到127之间不会再创建对象而是复用,超出则会创建对象==判断为假
如果要比较两个对象的内容是否相同,尽量不使用== 或者!= 来比较,可以使用equal()来实现。
5.if(instance instanceof interface )//true
if(child instanceof parent)//true