2022Java集合最全面试题,为秋招做好准备

集合:

193.Java集合体系结构(List、Set、Collection、Map的区别和联系)

 

1、Collection 接口存储一组不唯一,无序的对象

2、List 接口存储一组不唯一,有序(插入顺序)的对象

3、Set 接口存储一组唯一,无序的对象

4、Map接口存储一组键值对象,提供key到value的映射。Key无序,唯一。value不要求有序,允许重复。(如果只使用key存储,而不使用value,那就是Set)

194.Vector和ArrayList的区别和联系

相同点:

1)实现原理相同---底层都使用数组

2)功能相同---实现增删改查等操作的方法相似

3)都是长度可变的数组结构,很多情况下可以互用

不同点:

1)Vector是早期JDK版本提供,ArrayList是新版本替代Vector的

2)Vector线程安全,ArrayList重速度轻安全,线程非安全长度需增长时,Vector默认增长一倍,ArrayList增长50%

195.ArrayList和LinkedList的区别和联系

相同点:

两者都实现了List接口,都具有List中元素有序、不唯一的特点。

不同点:

ArrayList实现了长度可变的数组,在内存中分配连续空间。遍历元素和随机访问元素的效率比较高;

LinkedList采用链表存储方式。插入、删除元素时效率比较高

196.HashMap和Hashtable的区别和联系

相同点:

实现原理相同,功能相同,底层都是哈希表结构,查询速度快,在很多情况下可以互用

不同点:

1、Hashtable是早期提供的接口,HashMap是新版JDK提供的接口

2、Hashtable继承Dictionary类,HashMap实现Map接口

3、Hashtable线程安全,HashMap线程非安全

4、Hashtable不允许null值,HashMap允许null值

197.HashSet的使用和原理(hashCode()和equals())

1)哈希表的查询速度特别快,时间复杂度为O(1)。

2)HashMap、Hashtable、HashSet这些集合采用的是哈希表结构,需要用到hashCode哈希码,hashCode是一个整数值。

3)系统类已经覆盖了hashCode方法 自定义类如果要放入hash类集合,必须重写hashcode。如果不重写,调用的是Object的hashcode,而Object的hashCode实际上是地址。

4)向哈希表中添加数据的原理:当向集合Set中增加对象时,首先集合计算要增加对象的hashCode码,根据该值来得到一个位置用来存放当前对象,如在该位置没有一个对象存在的话,那么集合Set认为该对象在集合中不存在,直接增加进去。如果在该位置有一个对象存在的话,接着将准备增加到集合中的对象与该位置上的对象进行equals方法比较,如果该equals方法返回false,那么集合认为集合中不存在该对象,在进行一次散列,将该对象放到散列后计算出的新地址里。如果equals方法返回true,那么集合认为集合中已经存在该对象了,不会再将该对象增加到集合中了。

5)在哈希表中判断两个元素是否重复要使用到hashCode()和equals()。hashCode决定数据在表中的存储位置,而equals判断是否存在相同数据。

6) Y=K(X) :K是函数,X是哈希码,Y是地址

198.TreeSet的原理和使用(Comparable和comparator)

1)TreeSet集合,元素不允许重复且有序(自然顺序)

2)TreeSet采用树结构存储数据,存入元素时需要和树中元素进行对比,需要指定比较策略。

3)可以通过Comparable(外部比较器)和Comparator(内部比较器)来指定比较策略,实现了Comparable的系统类可以顺利存入TreeSet。自定义类可以实现Comparable接口来指定比较策略。

4)可创建Comparator接口实现类来指定比较策略,并通过TreeSet构造方法参数传入。这种方式尤其对系统类非常适用。

199.集合和数组的比较(为什么引入集合)

数组不是面向对象的,存在明显的缺陷,集合完全弥补了数组的一些缺点,比数组更灵活更实用,可大大提高软件的开发效率而且不同的集合框架类可适用于不同场合。具体如下:

1)数组的效率高于集合类.

2)数组能存放基本数据类型和对象,而集合类中只能放对象。

3)数组容量固定且无法动态改变,集合类容量动态改变。

4)数组无法判断其中实际存有多少元素,length只告诉了array的容量。

5)集合有多种实现方式和不同的适用场合,而不像数组仅采用顺序表方式。

6)集合以类的形式存在,具有封装、继承、多态等类的特性,通过简单的方法和属性调用即可实现各种复杂操作,大大提高软件的开发效率。

200.Collection和Collections的区别

1)Collection是Java提供的集合接口,存储一组不唯一,无序的对象。它有两个子接口List和Set。

2)Java中还有一个Collections类,专门用来操作集合类 ,它提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。

201.下列说法正确的有()(选择一项)

A.LinkedList继承自List
B.AbstractSet继承自Set
C.HashSet继承自AbstractSet
D.TreeMap继承自HashMap

答案: C

分析:A:LinkedList实现List接口

B:AbstractSet实现Set接口

D:TreeMap继承AbstractMap

202.Java的HashMap和Hashtable有什么区别HashSet和HashMap有什么区别?使用这些结构保存的数需要重载的方法是哪些?

答:HashMap与Hashtable实现原理相同,功能相同,底层都是哈希表结构,查询速度快,在很多情况下可以互用

两者的主要区别如下

1、Hashtable是早期JDK提供的接口,HashMap是新版JDK提供的接口

2、Hashtable继承Dictionary类,HashMap实现Map接口

3、Hashtable线程安全,HashMap线程非安全

4、Hashtable不允许null值,HashMap允许null值

HashSet与HashMap的区别

1、HashSet底层是采用HashMap实现的。HashSet 的实现比较简单,HashSet 的绝大部分方法都是通过调用 HashMap 的方法来实现的,因此 HashSet 和 HashMap 两个集合在实现本质上是相同的。

2、HashMap的key就是放进HashSet中对象,value是Object类型的。

3、当调用HashSet的add方法时,实际上是向HashMap中增加了一行(key-value对),该行的key就是向HashSet增加的那个对象,该行的value就是一个Object类型的常量

203.列出Java中的集合类层次结构?

答:Java中集合主要分为两种:Collection和Map。Collection是List和Set接口的父接口;ArrayList和LinkedList是List的实现类;HashSet和TreeSet是Set的实现类;LinkedHashSet是HashSet的子类。HashMap和TreeMap是Map的实现类;LinkedHashMap是HashMap的子类。

图中:虚线框中为接口,实线框中为类。

204.List,Set,Map各有什么特点

答:List 接口存储一组不唯一,有序(插入顺序)的对象。

Set 接口存储一组唯一,无序的对象。

Map接口存储一组键值对象,提供key到value的映射。key无序,唯一。value不要求有序,允许重复。(如果只使用key存储,而不使用value,那就是Set)。

205.ArrayList list=new ArrayList(20);中的list扩充几次()

A.0
B.1
C.2
D.3

答案:A

分析:已经指定了长度, 所以不扩容

206.List、Set、Map哪个继承自Collection接口,一下说法正确的是()

A.List Map
B.Set Map
C.List Set
D.List Map Set

答案:C

分析:Map接口继承了java.lang.Object类,但没有实现任何接口.

207.合并两个有序的链表

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

public class Solution {

public ListNode mergeTwoLists(ListNode l1, ListNode l2) {

if (l1 == null || l2 == null) {

            return l1 != null ? l1 : l2;

        }

        ListNode head = l1.val < l2.val ? l1 : l2;

        ListNode other = l1.val >= l2.val ? l1 : l2;

        ListNode prevHead = head;

        ListNode prevOther = other;

        while (prevHead != null) {

            ListNode next = prevHead.next;

            if (next != null && next.val > prevOther.val) {

                prevHead.next = prevOther;

                prevOther = next;

            }

            if(prevHead.next==null){

                prevHead.next=prevOther;

                break;

            }

            prevHead=prevHead.next;

        }

        return head;

}

}

208.用递归方式实现链表的转置。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

/**

Definition for singly-linked list.

public class ListNode {

int val;

ListNode next;

ListNode(int x) { val = x; }

* }

*/

public class Solution {

public ListNode reverseList(ListNode head) {

if(head==null||head.next ==null)

            return head;

        ListNode prev = reverseList(head.next);

        head.next.next = head;

        head.next = null;

        return prev;

}

}

209.给定一个不包含相同元素的整数集合,nums,返回所有可能的子集集合。解答中集合不能包含重复的子集。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

public class Solution {

    public List<List<Integer>> subsets (int[] nums) {

        List<List<Integer>> res = new ArrayList<ArrayList<Integer>>();

        List<Integer> item = new ArrayList<Integer>();

        if(nums.length == 0 || nums == null)

            return res;

        Arrays.sort(nums); //排序

        dfs(nums, 0, item, res);  //递归调用

        res.add(new ArrayList<Integer>());  //最后加上一个空集

        return res;

    }

    public static void dfs(int[] nums, int start, List<Integer> item, List<List<Integer>> res){

        for(int i = start; i < nums.length; i ++){

            item.add(nums[i]);

            //item是以整数为元素的动态数组,而res是以数组为元素的数组,在这一步,当item增加完元素后,item所有元素构成一个完整的子串,再由res纳入

            res.add(new ArrayList<Integer>(item));

            dfs(nums, i + 1, item, res);

            item.remove(item.size() - 1);

        }

    }

}

210.以下结构中,哪个具有同步功能()

A.HashMap
B.ConcurrentHashMap
C.WeakHashMap
D.TreeMap

答案:B

分析:

A,C,D都线程不安全,B线程安全,具有同步功能

211.以下结构中,插入性能最高的是()

A.ArrayList
B.Linkedlist
C.tor
D.Collection

答案:B

分析:

数组插入、删除效率差,排除A

tor不是java里面的数据结构,是一种网络路由技术;因此排除C

Collection 是集合的接口,不是某种数据结构;因此排除D

212.以下结构中,哪个最适合当作stack使用()

A.LinkedHashMap
B.LinkedHashSet
C.LinkedList

LinkedList

分析:

Stack是先进后出的线性结构;所以链表比较合适;不需要散列表的数据结构

213.Map的实现类中,哪些是有序的,哪些是无序的,有序的是如何保证其有序性,你觉得哪个有序性性能更高,你有没有更好或者更高效的实现方式?

答:1. Map的实现类有HashMap,LinkedHashMap,TreeMap

2. HashMap是有无序的,LinkedHashMap和TreeMap都是有序的(LinkedHashMap记录了添加数据的顺序;TreeMap默认是自然升序)

3. LinkedHashMap底层存储结构是哈希表+链表,链表记录了添加数据的顺序

4. TreeMap底层存储结构是二叉树,二叉树的中序遍历保证了数据的有序性

5. LinkedHashMap有序性能比较高,因为底层数据存储结构采用的哈希表

214.下面的代码在绝大部分时间内都运行得很正常,请问什么情况下会出现问题?根源在哪里?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

package com.bjsxt;

import java.util.LinkedList;

public class Stack {

LinkedList list = new LinkedList();

public synchronized void push(Object x) {

synchronized (list) {

list.addLast(x);

notify();

}

}

public  synchronized Object pop() throws  Exception{

synchronized(list){

if(list.size()<=0){

wait();

}

return list.removeLast( );

}

}

}

答:将if( list.size() <= 0 )改成:while( list.size() <= 0 )

215.TreeMap和TreeSet在排序时如何比较元素?Collections工具类中的sort()方法如何比较元素?

答:TreeSet要求存放的对象所属的类必须实现Comparable接口,该接口提供了比较元素的compareTo()方法,当插入元素时会 回调该方法比较元素的大小。TreeMap要求存放的键值对映射的键必须实现Comparable接口从而根据键对元素进行排序。Collections 工具类的sort方法有两种重载的形式,第一种要求传入的待排序容器中存放的对象比较实现Comparable接口以实现元素的比较;第二种不强制性的要求容器中的元素必须可比较,但是要求传入第二个参数,参数是Comparator接口的子类型(需要重写compare方法实现元素的比较),相当于一个临时定义的排序规则,其实就是是通过接口注入比较元素大小的算法,也是对回调模式的应用。

216.List里面如何剔除相同的对象?请简单用代码实现一种方法

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

public class Test {

public static void main(String[] args) {

  List<String> li1 = new ArrayList<String>();

  li1.add("8");

  li1.add("8");

  li1.add("9");

  li1.add("9");

  li1.add("0");

  System.out.println(li1);

  //方法:将List中数据取出来来存到Set中

  HashSet<String> set = new HashSet<String>();

  for(int i=0;i<li1.size();i++){

  set.add(li1.get(i));

  }

  System.out.println(set);

}

}

217.Java.util.Map的实现类有

分析:Java中的java.util.Map的实现类

1、HashMap

2、Hashtable

3、LinkedHashMap

4、TreeMap

218.下列叙述中正确的是()

A.循环队列有队头和队尾两个指针,因此,循环队列是非线性结构
B.在循环队列中,只需要队头指针就能反映队列中元素的动态变化情况
C.在循环队列中,只需要队尾指针就能反映队列中元素的动态变化情况
D.在循环队列中元素的个数是由队头指针和队尾指针共同决定的

答案:D

分析:循环队列中元素的个数是由队首指针和队尾指针共同决定的,元素的动态变化也是通过队首指针和队尾指针来反映的,当队首等于队尾时,队列为空。

219.List、Set、Map 是否继承自Collection 接口?

答:List、Set 的父接口是Collection,Map 不是其子接口,而是与Collection接口是平行关系,互不包含。

Map是键值对映射容器,与List和Set有明显的区别,而Set存储的零散的元素且不允许有重复元素(数学中的集合也是如此),List是线性结构的容器,适用于按数值索引访问元素的情形。 

220.说出ArrayList、Vector、LinkedList 的存储性能和特性?

答:ArrayList 和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector由于使用了synchronized 方法(线程安全),通常性能上较ArrayList 差,而LinkedList 使用双向链表实现存储(将内存中零散的内存单元通过附加的引用关联起来,形成一个可以按序号索引的线性结构,这种链式存储方式与数组的连续存储方式相比,其实对内存的利用率更高),按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。Vector属于遗留容器(早期的JDK中使用的容器,除此之外Hashtable、Dictionary、BitSet、Stack、Properties都是遗留容器),现在已经不推荐使用,但是由于ArrayList和LinkedListed都是非线程安全的,如果需要多个线程操作同一个容器,那么可以通过工具类Collections中的synchronizedList方法将其转换成线程安全的容器后再使用(这其实是装潢模式最好的例子,将已有对象传入另一个类的构造器中创建新的对象来增加新功能)。

补充:遗留容器中的Properties类和Stack类在设计上有严重的问题,Properties是一个键和值都是字符串的特殊的键值对映射,在设计上应该是关联一个Hashtable并将其两个泛型参数设置为String类型,但是Java API中的Properties直接继承了Hashtable,这很明显是对继承的滥用。这里复用代码的方式应该是HAS-A关系而不是IS-A关系,另一方面容器都属于工具类,继承工具类本身就是一个错误的做法,使用工具类最好的方式是HAS-A关系(关联)或USE-A关系(依赖) 。同理,Stack类继承Vector也是不正确的。 

221.List、Map、Set 三个接口,存取元素时,各有什么特点?

答:List以特定索引来存取元素,可有重复元素。

Set不能存放重复元素(用对象的equals()方法来区分元素是否重复) 。Map保存键值对(key-value pair)映射,映射关系可以是一对一或多对一。Set和Map容器都有基于哈希存储和排序树(红黑树)的两种实现版本,基于哈希存储的版本理论存取时间复杂度为O(1),而基于排序树版本的实现在插入或删除元素时会按照元素或元素的键(key)构成排序树从而达到排序和去重的效果。 

222.TreeMap和TreeSet在排序时如何比较元素?Collections工具类中的sort()方法如何比较元素?

答:TreeSet要求存放的对象所属的类必须实现Comparable接口,该接口提供了比较元素的compareTo()方法,当插入元素时会回调该方法比较元素的大小。

TreeMap要求存放的键值对映射的键必须实现Comparable接口从而根据键对元素进行排序。

Collections工具类的sort方法有两种重载的形式,第一种要求传入的待排序容器中存放的对象比较实现Comparable接口以实现元素的比较;第二种不强制性的要求容器中的元素必须可比较,但是要求传入第二个参数,参数是Comparator接口的子类型 (需要重写compare方法实现元素的比较),相当于一个临时定义的排序规则,其实就是是通过接口注入比较元素大小的算法,也是对回调模式的应用。

例子1:

Student.java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

package com.bjsxt;

public class Student implements Comparable<Student> {

    private String name;        // 姓名

    private int age;            // 年龄

    public Student(String name, int age) {

        this.name = name;

        this.age = age;

    }

    @Override

    public String toString() {

        return "Student [name=" + name + ", age=" + age + "]";

    }

    @Override

    public int compareTo(Student o) {

        return this.age - o.age; // 比较年龄(年龄的升序)

    }

  }

Test01.java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

package com.bjsxt;

import java.util.Set;

import java.util.TreeSet;

class Test01 {

  public static void main(String[] args) {

        Set<Student> set = new TreeSet<>();     // Java 7的钻石语法(构造器后面的尖括号中不需要写类型)

        set.add(new Student("Hao LUO"33));

        set.add(new Student("XJ WANG"32));

        set.add(new Student("Bruce LEE"60));

        set.add(new Student("Bob YANG"22));

          for(Student stu : set) {

            System.out.println(stu);

        }

//      输出结果:

//      Student [name=Bob YANG, age=22]

//      Student [name=XJ WANG, age=32]

//      Student [name=Hao LUO, age=33]

//      Student [name=Bruce LEE, age=60]

    }

}

例子2:

Student.java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

package com.bjsxt;

public class Student {

    private String name;    // 姓名

    private int age;        // 年龄

    public Student(String name, int age) {

        this.name = name;

        this.age = age;

    }

    /**

     * 获取学生姓名

     */

    public String getName() {

        return name;

    }

    /**

     * 获取学生年龄

     */

    public int getAge() {

        return age;

    }

    @Override

    public String toString() {

        return "Student [name=" + name + ", age=" + age + "]";

    }

  }

Test02.java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

package com.bjsxt;

import java.util.ArrayList;

import java.util.Collections;

import java.util.Comparator;

import java.util.List;

  class Test02 {

   public static void main(String[] args) {

        List<Student> list = new ArrayList<>();     // Java 7的钻石语法(构造器后面的尖括号中不需要写类型)

        list.add(new Student("Hao LUO"33));

        list.add(new Student("XJ WANG"32));

        list.add(new Student("Bruce LEE"60));

        list.add(new Student("Bob YANG"22));

        // 通过sort方法的第二个参数传入一个Comparator接口对象

        // 相当于是传入一个比较对象大小的算法到sort方法中

        // 由于Java中没有函数指针、仿函数、委托这样的概念

        // 因此要将一个算法传入一个方法中唯一的选择就是通过接口回调

        Collections.sort(list, new Comparator<Student> () {

         @Override

            public int compare(Student o1, Student o2) {

                return o1.getName().compareTo(o2.getName());    // 比较学生姓名

            }

        });

        for(Student stu : list) {

            System.out.println(stu);

        }

//      输出结果:

//      Student [name=Bob YANG, age=22]

//      Student [name=Bruce LEE, age=60]

//      Student [name=Hao LUO, age=33]

//      Student [name=XJ WANG, age=32]

    }

}

最新2022整理收集的一些高频面试题(都整理成文档),有很多干货,包含Java基础、语法、String相关、集合、多线程、IO流、网络编程、异常处理、Web方面相关、设计模式、高级框架、微服务框架、数据库、JVM、Linux操作等资料,也有详细的学习规划图,面试题整理等,需要获取这些内容的朋友点赞+关注后私信回复《222》即可免费获取! 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值