Java集合容器面试题

导读:本篇文章讲解 Java集合容器面试题,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

Java常见面试题_2022最新版

序号 内容 链接
1 Java基础面试题 https://blog.csdn.net/weixin_46030002/article/details/126399353
2 Java集合容器面试题 https://blog.csdn.net/weixin_46030002/article/details/126425298
3 Java线程面试题 https://blog.csdn.net/weixin_46030002/article/details/126518395
4 Java异常面试题 https://blog.csdn.net/weixin_46030002/article/details/126482778
5 Spring常见面试题 https://blog.csdn.net/weixin_46030002/article/details/127281194
6 SpringMVC常见面试题 https://blog.csdn.net/weixin_46030002/article/details/127057785
7 Mybatis常见面试题 https://blog.csdn.net/weixin_46030002/article/details/126026561
8 MySQL常见面试题 https://blog.csdn.net/weixin_46030002/article/details/126557564
9 Redis常见面试题 https://blog.csdn.net/weixin_46030002/article/details/126435834
  • Java常见面试题_2022最新版持续更新中…


一、集合容器面试题

常用的集合类有哪些

CollectionMap 接口是所有集合容器的父接口
常用的集合类:

  • Collection接口
    • List 接口
      • ArrayList
      • LinkedList
      • CopyOnWriteArrayList
    • Set接口
      • HashSet
      • TreeSet
      • LinkedHashSet
    • Queue 接口
      • Deque
  • Map接口
    • HashMap
    • TreeMap
    • ConcurrentHashMap

请添加图片描述

List,Set,Map的区别

  • List,Set 是Collection的子接口
    • List:
      • 有序(存入集合的顺序和取出的顺序一致)
      • 可以存储重复元素
      • 常用的实现类有:ArrayList,LinkedList,Vector
    • Set:
      • 无序(存入元素和取出元素的顺序可能不一致),所以我们一般不以有序无序来作为Set的特点,它不同实现类不太一样,有的有序,有的无序
      • 不可以存储重复元素
      • 常用的实现类有:HashSet,LinkedHashSet,TreeSet
  • Map 是一个键值对集合,存储键,值和之间的映射
    • key 无序
    • value 不要求有序,允许存放重复元素

集合和数组的区别

  • 数组的长度是固定的,集合的长度是可变的
  • 数组中既可以存储基本类型,也可以存储引用类型;
    • 基本类型存的是值
    • 引用类型存的是地址值
  • 集合中只能存储引用类型
    • 如果存储的是基本类型,会自动装箱成包装类
  • 数组中只能存储同一种类型的元素,集合中可以存储不同类型的元素

Collection 和 Collections 的区别

  • Collection 是集合框架的父级接口,提供了对集合对象进行基本操作的通用接口方法。Collection 为其子集合提供了一个统一的操作方式(向上造型);
  • Collections 是一个工具类,他包含了很多操纵集合的静态方法,用于对集合中元素进行排序、搜索、线程安全等等操作;此类构造方法被 private 修饰,所以不能实例化,服务于 Collection 集合.

集合中哪些是安全的

  • Vector
  • CopyOnWriteArrayList
  • HashTable
  • ConcurrentHashMap

泛型的种类

  • <E> 通常在集合中使用

    • E
      • Element
  • <T> 通常表示类

    • T
      • Type
  • <K,V> 通常表示键值对

    • K
      • Key
    • V
      • Value
  • ? 表示泛型通配符


(一)List

List 获取集合元素调用哪个API

list.size()

ArrayList 和 LinkedList 的区别

  • ArrayList
    • 数据结构:基于Object动态数组实现
    • 随机访问效率(可以理解为查询效率,略微有些不同):效率高,直接可以通过下标进行访问
    • 增删元素效率:增删元素效率较低,增删元素影响数组内的其他元素下标
    • 内存占用空间:较低
    • 线程安全:不同步,不保证线程安全
  • LinkedList
    • 数据结构:基于双向链表实现
    • 随机访问效率(可以理解为查询效率,略微有些不同):线型数据存储方式,需要通过指针从前往后依次查询
    • 增删元素效率:增删元素效率较高
    • 内存占用空间:较高,每个节点除了存储元素之外,还存储2个引用,prev指向上一个节点,next指向下一个节点
    • 线程安全:不同步,不保证线程安全

需要频繁读取集合中元素,我们一般使用ArrayList;插入和删除操作比较多时,使用LinkedList

ArrayList 和 Vector 的区别

ArrayList 和 Vector 都是 List 集合接口的实现类,他们底层都是数组这样的存储结构,它们都是有序集合。
Vector是 Java中的遗留容器,现在不怎么使用了

  • 线程安全:Vector 使用了 Synchronized 来实现线程同步,是线程安全的,而 ArrayList 是非线程安全的。
  • 性能:ArrayList 在性能方面要优于 Vector。
  • 扩容机制:Vector扩容每次增加1倍,ArrayList扩容每次增加50%

List 是接口还是类,List 是怎么遍历的

List 是接口

List<String> list=new ArrayList<String>();
list.add("a");
list.add("b");
list.add("c");
// 方法一
for(String s:list){ // 使用 foreach 循环
   System.out.print(s);
}
// 方法二
for(int i=0;i<list.size();i++){ // 对于 ArrayList 来说速度比较快, 用 for 循环, 以 size 为条件遍历:
   String str=list.get(i);
   System.out.print(str);
}
// 方法三
Iterator<String> it=list.iterator(); // 集合类的通用遍历方式, 迭代器遍历
while(it.hasNext()){
   System.out.print(it.next());
}

数组和集合(List)之间如何转换

// 数组转(ArrayList)集合 -- Arrays. asList(array)
String[] str = new String[]{"zs","ls","ww"};
List<String> strings = Arrays.asList(str)
// 集合(ArrayList)转数组
List<String> list = new ArrayList<>();
list.add("zs");
list.add("ls");
list.add("ww");
list.toArray();

循环遍历集合过程中如何删掉某个元素

List<String> list = new ArrayList<>();
list.add("张三");
list.add("李四");
list.add("王五");
list.add("赵六");
list.add("邹七");
list.add("张三");
list.add("李四");
list.add("李四");
//切记,这里需要用迭代器删除,而不要使用list的remove方法
Iterator it = list.iterator();
while (it.hasNext()) {
    String name = (String)it.next();
    if ("李四".equals(name)) {
        it.remove();
    }
}
System.out.println(list);

错误案例:

for(Integer i : list){ 
	list.remove(i); // 循环遍历的过程中,不能使用list.remove方法进行删除  
}

(二)Set

如何给 ArrayList 去重(去除重复元素)

public static List duplicateList(List list) {
       HashSet set = new HashSet();
       set.addAll(list);
       return new ArrayList(set);
}

public static void main(String[] args)() {
    List list = new ArrayList();
    list.add(new Integer(1));
    list.add(new Integer(2));
    list.add(new Integer(2));
    list.add(new Integer(4));
    list.add(new Integer(4));
    
    List list2 = duplicateList(list);
	System.out.println(list2)
}

HashSet实现原理

  • HashSet 是基于 HashMap 实现的,默认构造一个初始容量为16,负载因子为0.75的 HashMap。封装了一个 HashMap 对象类存储所有的集合元素,所有放入 HashSet 中的集合元素实际上是由 HashMap 的 key 来保存,而 HashMap 的 value 则存储了一个 PRESENT ,它是一个静态的 Object 对象。
  • HashSet的操作都是基于HashMap的。

HashSet

// 与支持 Map 中的对象关联的虚拟值
private static final Object PRESENT = new Object();

public HashSet() {
	map = new HashMap<>();
}

public boolean add(E e) {
    return map.put(e, PRESENT)==null;
}

HashMap

public V put(K key, V value) {
	return putVal(hash(key), key, value, false, true);
}

PRESENT 存在的意义

  • add 方法返回值为 boolean,表明当前添加的元素是否出现了重复
    • 如果此 set 尚未包含指定元素,则返回 true(元素不重复)
    • 如果此 set 尚包含指定元素,则返回 false(元素重复)
  • 里面实际调用了 map.put(k,v),put 方法返回值情况有两种
    • 如果 key 出现重复,返回上回存放的 value ,并进行覆盖
      • 返回 PRESENT 对象,add 返回 false
    • 如果第一次存放,put 返回的是 null
      • add 返回 true

(三)Map

HashMap 底层原理

Java 中最常见的两种数据结构:数组,链表
数组:查询快,根据索引(下标)查询,插入删除慢
链表:查询速度慢,需要遍历整个链表,但是插入和删除快
HashMap 是数组和链表组成的,我们又称为散列表。

HashMap 基于 Hash 算法实现的,我们通过 put(key,value)存储,get(key)来获取值。
当传入 key 时,HashMap 会根据 key. hashCode() 计算出 hash 值,根据 hash 值将 value 保存。
当计算出的 hash 值相同时,我们称之为 hash 冲突,HashMap 的做法是用链表和红黑树存储相同 hash 值的 value。当 hash 冲突的个数比较少时,使用链表否则使用红黑树,当子节点大于等于 8 时使用红黑树。

HashMap 和 HashTable 有什么区别?

HashMap 是线程不安全的,HashMap 是 Map 的一个子接口,是将键映射到值得对象,不允许键值重复;允许空键和空值;由于非线程安全,HashMap 的效率要较 HashTable 的效率高一些。
HashTable 是线程安全的一个集合,不允许 null 值作为一个 key 值或者 Value 值;
HashTable 是 sychronize,多个线程访问时不需要自己为它的方法实现同步,而 HashMap 在被多个线程访问的时候需要自己为它的方法实现同步。

HashMap 遍历的所有方法

  • Set set = map.keySet() Object value = map.get(key)
  • map.forEach((k,v) -> System.out.println(k+":"+v));
  • Set<Map.Entry<String,Integer>> entrySet = map.entrySet();
  • Collection values = map.values();

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

Map<String,Integer> map = new HashMap<>();
map.put("语文",99);
map.put("数学",98);
map.put("英语",97);
map.put("物理",96);
map.put("化学",99);

/*
    遍历所有的key
    Set<key> keySet()
    将Map中所有的key存入一个Set集合后将其返回
 */
Set<String> keySet = map.keySet();
for(String key : keySet){
    System.out.println("key:"+key);
    Integer value = map.get(key);
    System.out.println("value: "+value);
}
-----------------------------------------------------
/*
    Map也支持使用forEach方法遍历键值对
 */
map.forEach((k,v)-> System.out.println(k+":"+v));

-----------------------------------------------------
/*
    遍历每一组键值对
    Set<Entry> entrySet()
    将当前Map中每组键值对以一个Entry实例表示并存入Set集合将其返回
 */
Set<Map.Entry<String,Integer>> entrySet = map.entrySet();
for(Map.Entry<String,Integer> e : entrySet){
    String key = e.getKey();
    Integer value = e.getValue();
    System.out.println(key+":"+value);
}
-----------------------------------------------------
/*
    遍历所有的value
    Collection values()
    将当前Map中所有的value以一个集合形式返回
 */
Collection<Integer> values = map.values();
values.forEach((e)->System.out.println("value:"+e));

HashMap 和 HashSet 的区别

  • HashMap 实现了 Map 接口,HashSet 实现了 Set 接口

  • HashMap 存储键值对,HashSet 存储对象

  • HashMap 添加元素 put(key,value)HashSet 添加元素 add(Element e)

  • HashMap 使用 key 来计算 hashcode,HashSet 使用成员对象计算 hashcode值,如果两个对象hashcode相同,比较equals方法来判断对象是否相等,不等返回false

  • HashMap 比较快,HashSet 较慢

  • 持久更新中…

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/107632.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!