1.List接口
1.1 迭代器Iterator是什么?
迭代器是一个能遍历并选择容器中元素的对象。由于Collection集成了Iterator接口。所以List接口可以通过Iterator迭代器遍历或者获取元素。
Iterator遍历集合的特点是它只能单向遍历,但更安全,因为它可以确保,在遍历当前集合时,如果过集合的元素被修改,程序会抛出ConcurrentModificationException异常。
1.2 遍历List集合的方式有哪些?
1.for 循环遍历,基于一个外部的计数器,一次读取集合中每一个位置的元素,只到读到最后一个元素结束。
2.迭代器遍历,迭代器是一种设计模式,具有统一的遍历集合接口。
3.foreach遍历,foreach内部也是通过迭代器实现的。使用时不需要显示声明迭代器或计数器,有点是代码简洁,缺点是不能在遍历集合时对集合进行修改,增删等操作。
1.3 ArrayList有哪些优缺点?
1.ArrayList底层通过数组实现,因此在顺序添加元素时速度非常快。
2.由于实现了RandomAccess标记接口,具有随机访问能力,因此在查找元素时速度非常快。
3.在指定位置删除或插入元素时,需要做元素复制操作,如果需要复制的元素过多,会影响系统性能。
综上所述ArrayList适合顺序添加、随机查找元素的场景。
1.4 ArrayList和LinkedList的区别是什么?
1.ArrayList底层通过数组实现,LinkedList底层是双向链表数据结构。
2.ArrayList实现了RandomAccess标记接口,随机访问效率高,LinkedList是通过链表线性存储,需要指针从前向后移动依次查找。
3.两个类都是线程不安全。
综合来说,在需要频繁读取集合元素时推荐使用ArrayList,需要频繁的向集合中添加或删除集合元素时使用LinkedList更合适。
1.5 ArrayList和Vector区别是什么?
1.两个类底层数据结构都是数组。
2.Vector使用Synchronized同步锁,线程是安全的,ArrayList线程不安全。所以在使用时ArrayList性能要优于Vector。
3.两个类都会动态扩容,只不过Vector默认是扩容1倍,而ArrayList默认扩容50%。
1.6 如何和在多线程情况下使用ArrayList?
ArrayList是线程不安全的,如果在多线程下使用,需要使用Collections 工具类中synchronizedList方法,将ArrayList转换成线程安全的容器后再使用。
具体代码如下:
public class Demo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list = Collections.synchronizedList(list);
list.add("张三");
list.add("李四");
for(int i=0; i<list.size(); i++) {
System.out.println(list.get(i));
}
}
}
1.7 List和Set的区别是什么?
1.两者都继承自Collection接口
2.List是一个有序的容器,容器中元素可以重复,也可以存储多个null元素,元素都有索引,常用的实现类有ArrayList、LinkedList和Vector.
3.Set是一个无须的容器,容器中元素不能重复,只能存在一个null元素。常用的实现类包括HashSet、TreeSet、LinkedHashSet等。
4.List支持for循环,迭代器,foreach循环等多种遍历方式,Set支持迭代器遍历。List可以用下标获取元素,Set因为是无序的不支持通过下标获取元素。
5.Set查询效率低,插入删除效率高,List查询效率高,插入删除效率低。
2.Set接口
2.1 HashSet的实现原理是什么?
HashSet底层数据结构是HashMap,集合中的元素存储在HashMap的key中,而HashMap的value则统一为present,因此HashSet中存储的元素时无序且唯一的,这里的无序指的是插入顺序和遍历顺序不一致。
2.2 HashSet是如何保证数据不重复的?
向HashSet中添加元素时,会调用HashMap的put方法,把元素存储在HashMap的key中,HashMap判断key是否相等,会先调用hashcode方法然后调用equals方法表key值,如果比较结果相同,则覆盖原有value,返回旧的value,从而保证key唯一。
2.3 hashCode()和equals()的相关规定是什么?
hashCode是jdk根据对象的地址或字符串或数字算出来的int类型数值。
如果两个对象equals相等则hashCode值 一定相等,反过来如果两个对象的hashCode值相等,他们不一定相等,这就是说如果要覆盖equals 方法,一定也要同步覆盖hashCode()方法。如果没有覆盖hashCode() 方法,则覆盖了equals() 方法的类的任何两个对象,绝对不会相等。
2.4 ==和equals()的区别是什么?
==只比较两个对象的存贮地址是否相同,equals() 会比较两个对象的值是否相同。