Java——12个关于Java中集合的面试题

文章目录:

1.请问 ArrayList、HashSet、HashMap 是线程安全的吗?如果不是怎么获取线程安全的集合?

2.ArrayList内部用什么实现的?

2.1 无参构造源码分析

2.2 有参构造源码分析(参数为容量)

2.3 有参构造源码分析(参数为集合)

3.并发集合和普通集合的区别?

4.List 和 Map、Set 有什么区别?

5.HashMap 和 Hashtable、TreeMap 有什么区别?

6.Collection 和 Collections 有什么区别?

7.ArrayList 和 LinkedList、Vector 有什么区别?

8.HashSet 和 TreeSet 有什么区别?

9.List a=new ArrayList() 和 ArrayList a =new ArrayList() 的区别?

10.请用两个队列模拟堆栈结构?

11.Map中的key和value可以为null?

12.HashMap排序题


1.请问 ArrayList、HashSet、HashMap 是线程安全的吗?如果不是怎么获取线程安全的集合?

通过以上类的源码进行分析,每个方法都没有加锁,显然都是非线程安全的。在集合中Vector 和HashTable是线程安全的。打开源码会发现其实就是把各自核心方法添加上了synchronized 关键字。Collections工具类提供了相关的 API,可以让上面那3个不安全的集合变为安全的。

Collections.synchronizedCollection(c); //Collection
Collections.synchronizedList(list); //ArrayList
Collections.synchronizedMap(m); //HashMap
Collections.synchronizedSet(s); //HashSet

上面几个方法都是Collections工具类中的静态方法,都有对应的返回值类型,传入什么类型返回什么类型。打开源码其实原理非常简单,就是将集合的核心方法添加上了synchronized关键字。

2.ArrayList内部用什么实现的?

因为数组在创建的时候长度是固定的,那么就有个问题我们往ArrayList中不断的添加对象,它是如何管理这些数组呢?通过源码可以看到ArrayList内部是用Object[]实现的。接下来我们分别分析ArrayList的构造以及add()、remove()、clear()方法的实现原理。

2.1 无参构造源码分析

这里的 elementData 是一个 Object类型的数组,而我们new一个ArrayList的时候,调用这个无参构造,elementData 就被赋值为 DEFAULTCAPACITY_EMPTY_ELEMENTDATA,而它是一个 private static final修饰的Object数组。

2.2 有参构造源码分析(参数为容量)

public ArrayList(int initialCapacity) {if (initialCapacity > 0) {this.elementData = new Object[initialCapacity];} else if (initialCapacity == 0) {this.elementData = EMPTY_ELEMENTDATA;} else {throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);}}

该构造函数传入一个 int 值,该值作为数组的长度值。如果该值小于 0,则抛出一个运行时异常 IllegalArgumentException。如果等于 0,则使用一个空数组。如果大于 0,则创建一个长度为该值的新数组。

2.3 有参构造源码分析(参数为集合)

/*** Constructs a new instance of {@code ArrayList} containing the elements of* the specified collection.** @param collection the collection of elements to add.*/
public ArrayList(Collection<? extends E> collection) {if (collection == null) {throw new NullPointerException("collection == null");}Object[] a = collection.toArray();if (a.getClass() != Object[].class) {Object[] newArray = new Object[a.length];System.arraycopy(a, 0, newArray, 0, a.length);a = newArray;}array = a;size = a.length;
}

如果调用构造函数的时候传入了一个 Collection 的子类,那么先判断该集合是否为 null,为 null 则抛出空指针异常。如果不是则将该集合转换为数组 a(借助toArray()方法),然后将该数组a赋值为成员变量 array,将该数组的长度作为成员变量 size。

综合ArrayList源码中的这三个构造器,得出结论:ArrayList内部就是使用数组来实现的!!!

3.并发集合和普通集合的区别?

并发集合常见的有ConcurrentHashMap、ConcurrentLinkedQueue、ConcurrentLinkedDeque等。并发集合位于java.util.concurrent包下,是jdk1.5之后才有的,在 java 中有普通集合、同步(线程安全)的集合、并发集合。

普通集合通常性能最高,但是不保证多线程的安全性和并发的可靠性。线程安全集合仅仅是给集合添加了 synchronized 同步锁,严重牺牲了性能,而且对并发的效率就更低了,并发集合则通过复杂的策略不仅保证了多线程的安全又提高的并发时的效率。

4.List 和 Map、Set 有什么区别?

● 结构特点:List 和 Set 是存储单列数据的集合,Map 是存储键和值这样的双列数据的集合;List 中存储的数据是有顺序,并且允许重复;Map 中存储的数据是没有顺序的,其键是不能重复的,它的值是可以有重复的,Set 中存储的数据是无序的,且不允许有重复,但元素在集合中的位置由元素的 hashCode 决定,位置是固定的(Set 集合根据 hashCode 来进行数据的存储,所以位置是固定的,但是位置不是用户可以控制的,所以对于用户来说 Set 中的元素还是无序的);

● 实现类:List 接口下的实现类(LinkedList:基于链表实现,链表内存是散乱的,每一个元素存储本身内存地址的同时还存储下一个元素的地址。链表增删快,查找慢;ArrayList:基于数组实现,非线程安全的,效率高,便于索引,但不便于插入删除;Vector:基于数组实现,线程安全的,效率低)。Map 接口下的实现类(HashMap:基于 hash 表的 Map 接口实现,非线程安全,高效,支持 null 值和 null 键;Hashtable:线程安全,低效,不支持 null 值和  null 键;LinkedHashMap:是HashMap 的一个子类,保存了记录的插入顺序;SortedMap 接口:TreeMap,能够把它保存的记录根据键排序,默认是键值的升序排序)。Set 接口下的实现类(HashSet:底层是由 HashMap 实现,不允许集合中有重复的值,使用该方式时需要重写 equals()和 hashCode()方法;LinkedHashSet继承与 HashSet,同时又基于LinkedHashMap 来进行实现,底层使用的是LinkedHashMp)。

● 区别:List集合中对象按照索引位置排序,可以有重复对象,允许按照对象在集合中的索引位置检索对象,例如通过list.get(i)方法来获取集合中的元素;Map中的每一个元素包含一个键和一个值,成对出现,键对象不可以重复,值对象可以重复;Set集合中的对象不按照特定的方式排序,并且没有重复对象,但它的实现类能对集合中的对象按照特定的方式排序,例如 TreeSet类,可以按照默认顺序,也可以通过实现 java.util.Comparator接口来自定义排序方式。

5.HashMap 和 Hashtable、TreeMap 有什么区别?

  • HashMap底层是哈希表数据结构,是非线程安全的,HashMap是Map的一个实现类,是将键映射到值的对象,不允许键值重复。允许空键和空值;由于非线程安全,HashMap的效率要较 Hashtable 的效率高一些。
  • Hashtable底层也是哈希表数据结构,是线程安全的一个集合,不允许 null 值作为一个 key 值或者value 值;Hashtable中所有的方法都带有sychronized关键字,多个线程访问时不需要自己为它的方法实现同步,而 HashMap 在被多个线程访问的时候需要自己为它的方法实现同步。 
  • TreeMap集合底层是一个二叉树,实现了SortedMap接口,能够把它保存的记录根据键排序,默认是按键值的升序排序。

6.Collection 和 Collections 有什么区别?

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

7.ArrayList 和 LinkedList、Vector 有什么区别?

  • ArrayList底层的数据结构是数组,是非线程安全的。支持随机访问,而 LinkedList 的底层数据结构是双向循环链表,不支持随机访问。使用下标访问一个元素,ArrayList 的时间复杂度是 O(1),而 LinkedList 是 O(n)。
  • Vector底层结构也是数组,其中所有的方法都使用了synchronized来实现线程同步、线程安全,由于效率较低,现在使用较少。
  • LinkedList底层的数据结构是双向链表,是非线程安全的。对于这种数据结构而言,对数据的增删效率高,而对数据的检索效率低。
  • ArrayList 是实现了基于动态数组的数据结构,LinkedList 基于链表的数据结构。如果集合数据是对于集合随机访问 get 和 set,ArrayList 绝对优于 LinkedList,因为 LinkedList 要移动指针。如果集合数据是对于集合新增和删除操作 add 和 remove,LinkedList 比较占优势,因为ArrayList要移动数据。
  • 当操作是在一列数据的后面添加数据而不是在前面或中间,并且需要随机地访问其中的元素时,使用ArrayList 会提供比较好的性能;当你的操作是在一列数据的前面或中间添加或删除数据,并且按照顺序访问其中的元素时,就应该使用LinkedList了。

8.HashSet 和 TreeSet 有什么区别?

  • HashSet是Set集合的一个实现类,其底层实现是HashMap的key(实际上是new了一个HashMap集合,实际上也是将元素存储到HashMap集合中了)。HashSet存储元素的顺序并不是按照存入时的顺序(和List不同)而是按照哈希值来存的所以取数据也是按照哈希值取得。元素的哈希值是通过元素的hashcode方法来获取的, HashSet首先判断两个元素的哈希值,如果哈希值一样,接着会比较equals方法 如果 equals结果为true ,HashSet就视为同一个元素。如果equals 为false就不是同一个元素。 哈希值相同equals为false的元素是怎么存储呢,就是在同样的哈希值下顺延(可以认为哈希值相同的元素放在一个哈希桶中)。也就是哈希一样的存一列。
  • TreeSet底层实际上是TreeMap(二叉树),new一个TreeSet的时候实际上是new了一个TreeMap,存储数据的时候,实际上是将数据存到了TreeMap集合中,是使用二叉树的原理对新add()的对象按照指定的顺序排序(升序、降序),每增加一个对象都会进行排序,将对象插入的二叉树指定的位置。

9.List a=new ArrayList() 和 ArrayList a =new ArrayList() 的区别?

  • List list = new ArrayList(); 这句创建了一个 ArrayList 的对象后赋给了List,此时它是一个 List 对象了,有些 ArrayList 中存在的方法 但是 List 就没有这样的属性和方法了,它就不能再用了。
  • ArrayList list=new ArrayList(); 创建一对象则保留了ArrayList 的所有属性。 所以需要用到 ArrayList 独有的方法的时候不能用前者。实例代码如下:

10.请用两个队列模拟堆栈结构?

入栈:a 队列为空,b队列 为空。例:将”a,b,c,d,e”需要入栈的元素先放 a 中,a 进栈为 ”a,b,c,d,e” 出栈:a 队列目前的元素为”a,b,c,d,e”。将 a 队列依次加入 Arraylist 集合 a 中。以倒序的方法,将 a 中的集合取出,放入 b 队列中,再将 b 队列出列。代码如下: 

import java.util.*;/****/
public class TestList {public static void main(String[] args) {Queue<String> queue1=new LinkedList<>(); //a队列Queue<String> queue2=new LinkedList<>(); //b队列ArrayList<String> arrayList=new ArrayList<>(); //arrayList集合是中间参数//向a队列中添加元素queue1.add("a");queue1.add("b");queue1.add("c");queue1.add("d");queue1.add("e");System.out.print("进栈:");//遍历a队列,将其依次加入arrayList集合中for (String q : queue1) {arrayList.add(q);System.out.print(q + " ");}System.out.println();//以倒序的方式取出,存入b队列for (int i=arrayList.size()-1;i>=0;i--) {queue2.add(arrayList.get(i));}//打印出栈队列bSystem.out.println("============");System.out.print("出栈:");for (String q : queue2) {System.out.print(q + " ");}}
}

11.Map中的key和value可以为null?

HashMap 对象的 key、value 值均可为 null。

Hahtable 对象的 key、value 值均不可为 null。且两者的的 key 值均不能重复,若添加 key 相同的键值对,后面的 value 会自动覆盖前面的 value,但不会报错。

代码片段1如下: 

import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;/****/
public class TestMap {public static void main(String[] args) {Map<String,String> map=new HashMap<>();Map<String,String> stringMap=new Hashtable<>();//将HashMap的key、value设置为nullmap.put(null,null);System.out.println("HashMap的[key]和[value]均可以为null:" + map);//将HashTable的key、value设置为nullstringMap.put(null,null);System.out.println(stringMap);}
}

输出结果中,HashMap可以正常输出,而Hashtable则是报了空指针异常 。

再来看代码片段2:

import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;/****/
public class TestMap {public static void main(String[] args) {Map<String,String> map=new HashMap<>();Map<String,String> stringMap=new Hashtable<>();//将HashMap的key、value设置为nullmap.put(null,null);System.out.println("HashMap的[key]和[value]均可以为null:" + map);//将HashTable的key、value设置为nulltry {stringMap.put(null,"hello");System.out.println(stringMap.get(null));}catch (Exception e) {System.out.println("【ERROR】:hashtable 的[key]不能为 null");}try {stringMap.put("hello",null);System.out.println(stringMap.get("hello"));}catch (Exception e) {System.out.println("【ERROR】:hashtable 的[value]不能为 null");}}
}

此时将Hashtable中的key或者value设置为 null,可以正常的被try/catch语句块捕捉。

12.HashMap排序题

已知一个 HashMap<Integer,User>集合, User 有 name(String)和 age(int)属性。请写一个方法实现对HashMap 的排序功能,该方法接收 HashMap<Integer,User>为形参,返回类型为 HashMap<Integer,User>,要求对 HashMap 中的 User 的 age 倒序进行排序。排序时 key=value 键值对不得拆散。

注意:要做出这道题必须对集合的体系结构非常的熟悉。HashMap本身就是不可排序的,但是该题偏偏让HashMap排序,那我们就得想在API中有没有这样的 Map 结构是有序的,我们不难发现其中LinkedHashMap就具有这样的结构,是链表结构有序的,更可喜的是他是  HashMap的子类,我们返回LinkedHashMap<Integer,User>即可,还符合面向接口编程的思想。

但凡是对集合的操作,我们应该保持一个原则就是能用JDK中的API就用JDK中的 API,比如排序算法我们不应该去用冒泡或者选择,而是首先想到用 Collections 集合工具类。

package com.szh.java01;import java.util.*;/****/
class User {private String name;private Integer age;public User() {}public User(String name, Integer age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", age=" + age +'}';}
}public class HashMapTest {public static void main(String[] args) {HashMap<Integer,User> userHashMap=new HashMap<>();userHashMap.put(1,new User("张三",25));userHashMap.put(2,new User("李四",28));userHashMap.put(3,new User("王五",21));System.out.println(userHashMap);HashMap<Integer,User> sortHashMap=sortHashMap(userHashMap);System.out.println(sortHashMap);}private static HashMap<Integer, User> sortHashMap(HashMap<Integer, User> userHashMap) {//首先拿到userHashMap的键值对集合Set<Map.Entry<Integer,User>> entrySet=userHashMap.entrySet();//将Set集合转为List集合,为了使用工具类的排序方法List<Map.Entry<Integer,User>> entryList=new ArrayList<Map.Entry<Integer,User>>(entrySet);//使用Collections集合工具类对entryList进行排序,排序规则使用匿名内部类实现Collections.sort(entryList, new Comparator<Map.Entry<Integer, User>>() {@Overridepublic int compare(Map.Entry<Integer, User> o1, Map.Entry<Integer, User> o2) {return o2.getValue().getAge() - o1.getValue().getAge();}});//创建一个新的有序的HashMap子类的集合LinkedHashMap<Integer,User> linkedHashMap=new LinkedHashMap<>();//将entryList中的数据存入其中for (Map.Entry<Integer,User> entry : entryList) {linkedHashMap.put(entry.getKey(),entry.getValue());}return linkedHashMap;}}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/1382449.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

Java面试题总结 - Java集合篇(附答案)

目录 一、Java 容器都有哪些&#xff1f; 二、Collection 和 Collections 有什么区别&#xff1f; 三、list与Set区别 四、HashMap 和 Hashtable 有什么区别&#xff1f; 五、说一下 HashMap 的实现原理&#xff1f; 六、set有哪些实现类&#xff1f; 七、说一下 HashSet…

【面试】Java集合面试题

文章目录 集合容器概述什么是集合集合的特点集合和数组的区别使用集合框架的好处常用的集合类有哪些&#xff1f;List&#xff0c;Set&#xff0c;Map三者的区别&#xff1f;集合框架底层数据结构哪些集合类是线程安全的&#xff1f;Java集合的快速失败机制 “fail-fast”&…

面试题----集合

目录 概述 List,Set,Map 集合框架底层数据结构总结 List Set Map 为什么要使⽤集合&#xff1f; 如何选⽤集合? 迭代器 Iterator 是什么&#xff1f; 迭代器 Iterator 有啥⽤&#xff1f; Iterator 和 ListIterator 的区别是什么&#xff1f; 有哪些集合是线程不安…

Java集合面试题(总结最全面的面试题!!!)

文章目录 集合概述什么是集合集合的特点集合和数组的区别使用集合框架的好处常用的集合类有哪些&#xff1f;List&#xff0c;Set&#xff0c;Map三者的区别&#xff1f;集合框架底层数据结构哪些集合类是线程安全的&#xff1f;Java集合的快速失败机制 “fail-fast”&#xff…

50道关于Java的集合经典面试题

1. Arraylist与LinkedList区别 可以从它们的底层数据结构、效率、开销进行阐述哈 ArrayList是数组的数据结构&#xff0c;LinkedList是链表的数据结构。随机访问的时候&#xff0c;ArrayList的效率比较高&#xff0c;因为LinkedList要移动指针&#xff0c;而ArrayList是基于索…

JAVA集合一些面试题

集合是程序员在面试的时候很大可能都会被问到。虽然集合不怎么困难&#xff0c;但是能把他仔细划分却又稍显困难。这里稍微搜罗了一些有关集合的面试题来进行分享。 我们先通过一张思维导图认识一下集合的框架构成&#xff0c;方便理解和记忆。 下面简单的归纳了一下给大家整…

集合面试问题总结

简述Java中的集合 集合类存放于 Java.util 包中&#xff0c;主要有 3 种&#xff1a;set(集&#xff09;、list(列表包含 Queue&#xff09;和 map(映射)。 Collection&#xff1a;Collection 是集合 List、Set、Queue 的最基本的接口。 Iterator&#xff1a;迭代器&#xff0…

java集合详解和集合面试题目

一、集合与数组 数组&#xff08;可以存储基本数据类型&#xff09;是用来存现对象的一种容器&#xff0c;但是数组的长度固定&#xff0c;不适合在对象数量未知的情况下使用。 集合&#xff08;只能存储对象&#xff0c;对象类型可以不一样&#xff09;的长度可变&#xff0…

Java集合的常见面试题(全)

这里写目录标题 前言常用的集合类有哪些集合底层数据结构ArrayList 和 LinkedList 的区别HashSet 如何检查重复HashSet与HashMap的区别HashMap 和 Hashtable 的区别HashMap 的底层实现HashMap 的长度为什么是 2 的幂次方ConcurrentHashMap 和 Hashtable 的区别HashMap源码细节C…

集合面试题总结

集合 Collection接口&#xff1a;单列集合&#xff0c;用来存储一个一个的对象 List接口&#xff1a;存储有序的、可重复的数据&#xff0c;。 -->“动态”数组 实现类&#xff1a;ArrayList、LinkedList、Vector Set接口&#xff1a;存储无序的、不可重复的数据 实现类&…

10道集合框架面试题(含解析),来看看你会多少

1.Arraylist 与 LinkedList 异同 &#xff08;1&#xff09;是否保证线程安全&#xff1a; ArrayList 和 LinkedList 都是不同步的&#xff0c;也就是不保证线程安全&#xff1b; &#xff08;2&#xff09;底层数据结构&#xff1a; Arraylist 底层使用的是Object数组&#…

Java集合面试题(总结最全面的面试题)

集合容器概述 什么是集合 集合就是一个放数据的容器&#xff0c;准确的说是放数据对象引用的容器 集合类存放的都是对象的引用&#xff0c;而不是对象的本身 集合类型主要有3种&#xff1a;set(集&#xff09;、list(列表&#xff09;和map(映射)。 集合的特点 集合的特点…

Python编程练习与解答 练习65:温度换算表

编写一个程序&#xff0c;显示摄氏温度和华氏温度转换表。该表的行包括0-100摄氏度之间所有的温度&#xff0c;这些温度时10摄氏度的倍数&#xff0c;列上适当的标题&#xff0c;摄氏度和华氏度之间的换算公式可在互联网上找到。 # 转换公式为&#xff1a;f(&#xff08;c*9)/…

java语言【 #93. 温度换算】(已通过)

题目描述 ​ 读入一个实数表示的摄氏温度 C&#xff0c;将它转换为华氏温度 F 并输出。​ 公式如下&#xff1a; F1.8∗C32 输入 ​ 一个实数表示 C&#xff08;0.0≤C≤100.0&#xff09; 输出 ​ 将 C 转换成 F 的结果。 ​ 结果保留两位小数 样例输入 66.66样例输出 151…

热敏电阻-温度换算算法(分段线性拟合法)

概要 在工业上&#xff0c;会有各种读取环境温度&#xff0c;或读取目标物体温度的需求&#xff0c;通常用到的方案有&#xff1a;传感器测温&#xff1b;热敏电阻测温等。本篇着重讲解使用热敏电阻测温的方法。 热敏电阻 何为热敏电阻&#xff1f;热敏电阻即为热电偶传感器…

摄氏温度和华氏温度换算(vb源码)

【实例简介】初步涉及VB 【实例截图】 文件&#xff1a;590m.com/f/25127180-493490306-f0ccf8&#xff08;访问密码&#xff1a;551685&#xff09; 以下内容无关&#xff1a; -------------------------------------------分割线----------------------------------------…

DS18b20温度值换算

DS18B20 处理正负温度值。 寄存器格式 例子 //计算温度值 //参数 高字节&#xff0c;低字节 double CaculateTemp(uint8_t tmh, uint8_t tml) {uint8_t th;uint8_t tl;double temp 0;tl tml & 0x0F;//取低字节后四位th (tmh << 4) (tml >> 4);//取高字节后…

用Python制作温度换算模块

&#xff08;注&#xff1a;这里通用摄氏度&#xff0c;Python版本为3.8.5&#xff09; 今天教大家做一个温度换算模块&#xff0c;非常简单实用。 这张图是最终效果&#xff1a; &#xff08;CK指将摄氏度转换为开氏度&#xff0c;CRe指将摄氏度转换为列氏度&#xff09; …

c语言——统计分类

我们将一个班的成绩进行分类&#xff0c; 成绩60分以下的为c、成绩61-89分的为b&#xff0c;90分以上的为A //统计分类 /*我们将一个班的成绩进行分类&#xff0c; 成绩60分以下的为c、成绩61-89分的为b&#xff0c;90分以上的为A */ #include<stdio.h> int main() …

如何将Excel中的一列内容合并到一起显示?

最近在工作过程中遇到要将excel中一列内容合并到一个格里显示&#xff0c;经过查询可以通过如下实现&#xff0c;记录下来方便使用。 步骤&#xff1a; 打开excel&#xff0c;复制要整合的内容到excel的一列&#xff0c;在下面一个格里执行下面语句&#xff1a; CONCATENATE(TR…