面试题—集合

集合

1.java 容器都有哪些?

常用容器的图录:
在这里插入图片描述

2. Collection 和 Collections 有什么区别?

  • java.util.Collection
    是一个集合接口(集合类的一个顶级接口)。它提供了对集合对象进行基本操作的通用接口方法。Collection接口在Java类库中有很多具体的实现。Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式,其直接继承接口有List与Set。
  • Collections则是集合类的一个工具类/帮助类,其中提供了一系列静态方法,用于对集合中元素进行排序、搜索以及线程安全等各种操作。

3.List、Set、Map 之间的区别是什么?

List代表有序、重复的集合;Set代表无序不可重复的集合;Map代表具有映射关系的集合。

4.HashMap 和 Hashtable 有什么区别?

  • hashMap是线性不安全的,hashTable是线性安全的,hashMap效率要比hashTable高。

  • hashMap允许空键值,而hashTable不允许。

  • hashMap的初始容量是16,hashTable初始容量是11,

相同点:都是Map接口的实现类

5.如何决定使用 HashMap 还是 TreeMap?

对于在Map中插入、删除和定位元素这类操作,HashMap是最好的选择。然而,假如你需要对一个有序的key集合进行遍历,TreeMap是更好的选择。
备注:TreeMap性能通常比HashMap要慢,因为它底层采用红黑树来管理KEY-VALUE对,每个键值对都是一个树的节点。

6.说一下 HashMap 的实现原理?

HashMap概述: HashMap是基于哈希表的Map接口的非同步实现。此实现提供所有可选的映射操作,并允许使用null值和null键。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。

HashMap的数据结构: 数组+链表

当我们往Hashmap中put元素时,首先根据key的hashcode重新计算hash值,根绝hash值得到这个元素在数组中的位置(下标),如果该数组在该位置上已经存放了其他元素,那么在这个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放入链尾.如果数组中该位置没有元素,就直接将该元素放到数组的该位置上。

需要注意Jdk 1.8中对HashMap的实现做了优化,当链表中的节点数据超过八个之后,该链表会转为红黑树来提高查询效率,从原来的O(n)到O(logn)

备注:
在这里插入图片描述
《HashMap结构及原理》

6.LinkedHashMap(了解)

是HashMap子类,采用双向链表维护键值对的次序,该链表负责维护Map的迭代顺序,迭代顺序与键值对的插入顺序一致。

7. 说一下 HashSet 的实现原理?

  • HashSet底层由HashMap实现,hashMap底层是数组+链表的存储结构
  • HashSet的值存放于HashMap的key上
  • HashMap的value统一为PRESENT,它是一个静态的Object类。

如果试图将某类的对象作为hashMap的key时,必须重写该类的equals和hashCode方法,而且要保证它亮的返回值一致;即hashCode相等的两个对象,他们通过equals比较应该返回true。(原因:因为如果两个对象的equals相当,但是hashcode不等,hashSet会将他们存储在不同的位置,即也会添加成功,这与hashSet定义就有矛盾了,因为它的元素是不能重复的)
注意:hashMap插入重复的key,会被覆盖(可以结合hashMap底层链表结构理解)。
《详解重写equals()方法就必须重写hashCode()方法的原因》

8.treeSet

treeSet底层使用的就是treeMap,treeMap底层是采用红黑树的数据结构, 红黑树本质上是一棵一定程度上相对平衡的二叉搜索树。
默认情况下,treeSet采用自然排序。(treeSet也支持定制排序)

9.HashSet 与treeSet

HashSet 性能比treeSet性能好,特别是最常用的插入、查询等操作。如果需要一个有序的set,就用treeSet。

10.hashSet和LinkedHashSet

LinkedHashSet是hashSet子类,又基于 LinkedHashMap 来实现的,通过hashcode决定元素的位置,通过双向链表维护元素的次序(与插入顺序一致)。
LinkedHashSet在迭代访问Set中的全部元素时,性能比HashSet好,但是插入时性能稍微逊色于HashSet。

11.properties

是hashTable的子类;
相当于key、value都是String类型的map.

12.ArrayList 和 LinkedList 的区别是什么?

最明显的区别是 ArrrayList底层的数据结构是数组,支持随机访问,而 LinkedList 的底层数据结构是双向循环链表,不支持随机访问。
数组:寻址容易,插入删除困难。
链表:寻址困难,插入删除容易。

13.如何实现数组和 List 之间的转换?

List转换成为数组:调用ArrayList的toArray方法。
数组转换成为List:调用Arrays的asList方法。

14.ArrayList 和 Vector 的区别是什么?

ArrayList 是非线性安全的,Vector 是线性安全的,ArrayList 性能比Vector 好。

15.Array 和 ArrayList 有何区别?

Array可以容纳基本类型和对象,而ArrayList只能容纳对象。
Array是指定大小的,而ArrayList大小是固定的。
Array没有提供ArrayList那么多功能,比如addAll、removeAll和iterator等。

16.在 Queue 中 poll()和 remove()有什么区别?

poll() 和 remove() 都是从队列中取出一个元素,但是 poll() 在获取元素失败的时候会返回空,但是 remove() 失败的时候会抛出异常。

17.如何使用线性安全的list

使用collections的线性安全包装

List list = Collections.synchronizedList(new ArrayList());
      ...
  synchronized (list) {
      Iterator i = list.iterator(); // Must be in synchronized block
      while (i.hasNext())
          foo(i.next());
  }

当我们对synchronizedList进行遍历的时候一定不要忘了,在外部也加上synchronized(list),以保证线程安全(这个synchronized块是为了保障内部三行代码在多个线程里同时执行的并发问题)。
https://blog.csdn.net/weixin_45240169/article/details/111400516

18.迭代器 Iterator 是什么?

迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构。迭代器通常被称为“轻量级”对象,因为创建它的代价小。

19.Iterator 怎么使用?有什么特点?

Java中的Iterator功能比较简单,并且只能单向移动:
  
(1) 使用方法iterator()要求容器返回一个Iterator。第一次调用Iterator的next()方法时,它返回序列的第一个元素。注意:iterator()方法是java.lang.Iterable接口,被Collection继承。
  
(2) 使用next()获得序列中的下一个元素。
  
(3) 使用hasNext()检查序列中是否还有元素。
  
(4) 使用remove()将迭代器新返回的元素删除。
  
Iterator是Java迭代器最简单的实现,为List设计的ListIterator具有更多的功能,它可以从两个方向遍历List,也可以从List中插入和删除元素。

20.Iterator 和 ListIterator 有什么区别?

Iterator可用来遍历Set和List集合,但是ListIterator只能用来遍历List。
Iterator对集合只能是前向遍历,ListIterator既可以前向也可以后向。
ListIterator实现了Iterator接口,并包含其他的功能,比如:增加元素,替换元素,获取前一个和后一个元素的索引,等等。

扩展:
在这里插入图片描述

21.JAVA中循环删除list元素的方法总结

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

22.如何重写equals和hashcode方法(动手写)

参照<如何正确的重写equals() 和 hashCode()方法>

23.如何实现list排序

在这里插入图片描述
执行结果:
在这里插入图片描述
可以用lambda表达式写,更简洁

public class OneTest {
	public static void main(String args[]){
		List<User> list = new ArrayList<>();
		list.add(new User(10,"xm"));
		list.add(new User(11,"xh"));
		// 升序
		// Collections.sort(list, (user1,user2)->user1.getAge()-user2.getAge());
		
		// 降序
		Collections.sort(list, (user1,user2)->user2.getAge()-user1.getAge());
		System.out.print(list);
	}
}

使用stream:

public class OneTest {
	public static void main(String args[]){
		List<User> list = new ArrayList<>();
		list.add(new User(10,"xm"));
		list.add(new User(11,"xh"));
		List<User> ll = list.stream().sorted((user1,user2)->user2.getAge()-user1.getAge())
				.collect(Collectors.toList());
		System.out.print(ll);
	}
}

26.Comparable接口和Comparator接口的比较

参照<Comparable接口和Comparator接口的比较>

  • 1、Comparable和Comparator都是用来实现集合中元素的比较、排序的。
  • 2、Comparable是在类内部定义的方法实现的排序,位于java.lang下。
  • 3、Comparator是在类外部实现的排序,位于java.util下。
  • 4、实现Comparable接口需要覆盖compareTo方法,实现Comparator接口需要覆盖compare方法。

27.set、map、list遍历方式

		//使用增强for循环遍历集合,由于Set集合没有get()方法,所有无法使用普通for循环遍历
		for (Object obj : stuSet) {
			StudentDemo sDemo = (StudentDemo)obj;
			System.out.println("姓名:"+sDemo.getStuName()+"-学号:"+sDemo.getStuId()+"-成绩:"+sDemo.getStuGrade());
		}
		
		System.out.println("******方法二:******");
		//使用Iterator迭代器遍历Set集合
		Iterator iterator = stuSet.iterator();
		while (iterator.hasNext()) {
			StudentDemo stuIt = (StudentDemo)iterator.next();
			System.out.println("姓名:"+stuIt.getStuName()+"-学号:"+stuIt.getStuId()+"-成绩:"+stuIt.getStuGrade());	
		}

list参照21
map遍历参照<java中Map遍历的四种方式>

28.Enumeration接口和Iterator接口的区别有哪些?

Enumeration(英[ɪˌnjuːməˈreɪʃn])速度是Iterator的2倍,同时占用更少的内存。但是,Iterator远远比Enumeration安全,因为其他线程不能够修改正在被iterator遍历的集合里面的对象。同时,Iterator允许调用者删除底层集合里面的元素,这对Enumeration来说是不可能的。

29.Properties类对于文件的读取和写入

参照<Properties类对于文件的读取和写入>

30.什么是泛型

泛型就是参数化类型,也就是所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。
在泛型出现之前,集合中添加对象只能是object类型的,在取出使用时,必须进行强制类型转换,容易引发ClassCastException。泛型提供了编译器的类型安全,确保你只能把正确类型的对象放入集合中。

31.java的泛型是如何工作的?什么是类型擦除?

泛型是通过类型擦除来实现的,编译器在编译时擦除了所有类型相关的信息,所以在运行时不存在任何类型相关的信息。例如List在运行时仅用一个List来表示。这样做的目的是确保能和java5之前的版本开发二进制类库进行兼容。你无法在运行时访问到类型参数,因为编译器已经把泛型类型转换成了原始类型。

32.什么是泛型中的限定通配符和非限定通配符?

限定通配符是对类型进行了限制。有两种限定通配符,一种是<? extends T>,它通过确保类型必须是T的子类来限定类型的上限。另一种是<? super T>,它通过确保类型必须是T的父类来限定类型的下限。泛型类型必须用限定内的类型来进行初始化,否则会导致编译错误。
非限定通配符用<?>来表示,泛型类型可以用任何类型来进行初始化。

33.自定义一个集合

参照<手把手写一个集合框架(一)动态数组>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值