欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Collection相关面试题(含答案)

程序员文章站 2023-11-17 09:21:40
面试第一人称回答问题Array 和 ArrayList 有何区别?如何实现 Array 和 List 之间的转换?Collection 和 Collections 有什么区别?Collections 工具类中的 sort()方法如何比较元素?来了来了,总是少不了你——HashMapTreeMap 和 TreeSet 在排序时如何比较元素?最后给你们推荐一本书吧Array 和 ArrayList 有何区别?如何实现 Array 和 List 之间的转换?面试官:了解Array这个类嘛?它和AraayLis...

迭代器 Iterator 是什么?Iterator 怎么使用?

提到迭代器 Iterator就要提到迭代器模式,Java 中常用的设计模式之一。用于顺序访问集合对象的元素,无需知道集合对象的底层实现。
Iterator是一个可以被各个集合实现的接口,用于遍历集合里的元素,这样可以避免调用各个集合获取元素的方法。
使用时,map要调用entryset方法。

 Iterator iterator =  list.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
 Iterator iterator=map.entrySet().iterator();

如何边遍历边移除 Collection 中的元素?

这就要用到Iterator了,如果用for遍历的时候删除的话,会报数组越界异常,ArrayIndexOutOfBoundsException,正确的方法应该是

  while (iterator.hasNext()){
        iterator.remove();
        }

为什么Iterator不会产生异常呢
Iterator 是工作在一个独立的线程中,并且拥有一个 mutex 锁。 Iterator 被创建之后会建立一个指向原来对象的单链索引表,当原来的对象数量发生变化时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭代的对象,所以按照 fail-fast 原则 Iterator 会马上抛出 java.util.ConcurrentModificationException 异常。
所以 Iterator 在工作的时候是不允许被迭代的对象被改变的。但你可以使用 Iterator 本身的方法 remove() 来删除对象, Iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性。

Collections 工具类中的 sort()方法如何比较元素?

 public static <T extends Comparable<? super T>> void sort(List<T> list) {
        list.sort(null);
    }
public static <T> void sort(List<T> list, Comparator<? super T> c) {
        list.sort(c);
    }

可以看到他有两种方式的排序,一种是继承了Comparable,这种方法就是传入待排序的容器中,然后进行比较,调用了List.sort()方法,这个List.sort()的底层其实调用了Array.sort()方法,Array.sort()的底层有三种排序算法,有个比较耳熟能详的二分排序法,好奇的自己去看吧,我就不多叨叨了。
另一种要传一个Comparator的子类进去,要重写compare() 方法,这样就可以自定义排序了

ArrayList的优缺点

ArrayList的底层是用数组实现,所以要说优缺点也就只能和数组或者链表进行比较了。
优点:
1.ArrayList可以动态扩容,1.5呗扩容,会将原数组copy过去
2.封装了多个对元素操作的方法
3.索引查询效率更高
缺点:
1.插入删除效率较低

如何实现Array和List之间的相互转换

一种是遍历数组所有元素,add方法添加到List集合中,第二种是用Arrays.asList将数组转成List,第三种就是用Collections.addAll()方法将数组转成List。
List转Array方法就相对少一点,我记得除了遍历元素以外,List有个自带的toArray方法可以将List转成数组。

TreeMap 和 TreeSet 在排序时如何比较元素?

面试官:看来你很了解集合这块知识,那我再问你最后一个问题吧, TreeMap 和 TreeSet 在排序时如何比较元素

我:好的,TreeSet和TreeMap排序时都需要实现Comparable接口,但TreeSet底层默认参数是Comparator,也就是说TreeSet的排序要实现comparaTo()方法,和且TreeSet底层就是调用了TreeMap的方法,这里体现了组合模式。

Collection相关面试题(含答案)
而TreeMap要求存放的键值对映射的键必须实现Comparable接口,从而根据键对元素进行排序。
Collection相关面试题(含答案)

多线程场景下如何使用 ArrayList?

ArrayList是非线程安全的,Vector是线程安全的,但是如果在多线程情形下使用ArrayList如何保证线程安全呢
1.Collections的synchnoizedList可以保证线程安全

List<Object> list =Collections.synchronizedList(new ArrayList<Object>);

2.加锁(synchronized),在add方法上加锁
3.使用线程安全的 CopyOnWriteArrayList 代替

List<Object> list1 = new CopyOnWriteArrayList<Object>();

4.使用ThreadLocal变量确保线程封闭性

ThreadLocal<List<Object>> threadList = new ThreadLocal<List<Object>>() {
        @Override
         protected List<Object> initialValue() {
              return new ArrayList<Object>();
         }
 };

封闭线程往往是比较安全的, 但由于使用ThreadLocal封装变量,相当于把变量丢进执行线程中去,每new一个新的线程,变量也会new一次,一定程度上会造成性能[内存]损耗,但其执行完毕就销毁的机制使得ThreadLocal变成比较优化的并发解决方案。

Java集合的快速失败机制“fail-fast”是什么?

它是 Java 集合的一种错误检测机制,当多个线程对集合进行结构上的改变操作时,有可能会产生 fail-fast 机制。
举个例子
线程A使用Iterator遍历集合时,线程B修改了集合的机构,不是修改元素,这时就会报ConcurrentModificationException 异常,从而产生 fail-fast 机制。
要想解决就要从Iterator入手,Iterator遍历集合时会产生一个变量modCount,当变量的过程时集合结构改变,modCount就会随之改变,所以只要在modCount上加锁,就能解决fail-fast了
或者直接使用线程安全的集合

最后给你们推荐一本书吧

这是我最近在看的一本书,我觉得很适合在座的各位!
Collection相关面试题(含答案)

如果答案里可以补充的,请写在评论区
要是有错误,可别放过我,打死我,快点滴!!
Collection相关面试题(含答案)
啥也不是!!

本文地址:https://blog.csdn.net/qq_42828912/article/details/106791557