• Java面试题——集合(主要包含Collection部分,Map部分单写)


    一、集合

     1什么是集合?

      集合是存储数据的容器,这里的数据指的是对象,可以存储不同的对象,并且长度可变。

    2、集合与数组的区别?

    • 数组的长度是固定的,集合的长度是可变的
    • 数组可以存储基本数据类型,也可以存储引用数据类型,集合只能存储引用数据类型
    • 数组存储的元素必须是同一个数据类型,集合存储的对象可以是不同类型。  

    3、哪些集合是线程安全的?

      SHE+v

    • Stack:堆栈类,先进后出
    • HashTable:就比HashMap多了个线程安全
    • enumeration:枚举,相当于迭代器
    • Vetor就比ArrayList多了个同步机制(线程安全),但因为效率低,已经很少使用了    

    二、Colletion接口

    1、 Iterator和ListIterator有什么区别? 

    • Iterator可以遍历List和Set的集合,而ListIterator只能遍历List集合
    • Iterator只支持单向遍历,而ListIterator支持双向遍历(前/后)
    • ListIterator实现Iterator接口,又添加了一些额外功能,如添加一个元素,替换一个元素。

    2、遍历List的方式

     遍历方法:

    1. for循环遍历:基于计数器,集合外部维护着一个计数器,然后依次读取每个元素,直到读到最后一个元素即可
    2. Iterator遍历:Iterator是面向对象的一种设计模式,目的是屏蔽不同集合的特点,统一遍历集合接口,Collection中采用的迭代器模式
    3. foreach:内部还是使用了迭代器的方式实现,使用时不需要显示的声明迭代器和计数器,优点是代码简洁,不易出错,缺点是,在遍历的时候不能操作集合,如增删改,否则会报并发异常

     最佳方法:Java Collection接口中提供了RandomAccess 接口,用于标记集合是否支持RandomAccess接口

    1. 如果一个集合实现了该接口,则它支持快速随机访问,按位置读取元素的平均时间复杂度是O(1),如ArrayList
    2. 如果集合没有实现该接口,表示不支持RandomAccess接口,如LinkedList

        综上:推荐的做法是,如果集合支持RandomAccess可以使用for遍历,否则使用Iterator/foreach遍历。

    3、说下ArrayList的优缺点

     增删慢,查找快

     优点:

    • ArrayList底层采用数组实现,是一种随机访问模式,并且实现了RandomAccess接口,因此查找的速度非常快
    • ArrayList顺序添加元素非常方便  

     缺点:

    • 删除元素的时候需要做元素的复制操作,如果元素很多的话,很消耗性能
    • 插入元素的时候,同样遇到上面的问题,移动元素,让出插入位置

    4、数组与List之间的转换

    • 数组转List:使用Arrays.asList方法
    • List转数组:使用toArray方法
     List<Integer> list = new ArrayList<Integer>();
     list.add(11);
     list.add(22);
     list.add(33);
    
     Object[] objects = list.toArray();  //list->[]
    
     String []strs = new String[]{
       "aa","bb"};
     List<String> strings = Arrays.asList(strs);   //[]->list

    5、ArrayList与LinkedList之间的区别

    • 数据结构:ArrayList底层采用的是数组实现,LinkedList底层采用的是双向链表实现
    • 数据访问:ArrayList要优于LinkedList,因为ArrayList底层采用数组实现,LinkedList采用线性的链式存储结构,需要移动指针来访问。
    • 增删效率:LinkedList要优于ArrayList,ArrayList增删要复制元素,影响其它数组元素的下标,而LinkedList只需要移动指针。
    • 线程安全:ArrayList和LinkedList都是线程不同步的,都不能保证线程安全。
    • 内存空间:ArrayList 内存空间会耗费在列表后面的预留空间;LinkedList 内存空间会耗费在每个数据要多存储一个前驱和后继。

      综上:如果对集合元素增删比较频繁的话推荐使用LinkedList,查找比较频繁的话推荐使用ArrayList。  

    6、多线程场景下使用ArrayList

      由于ArrayList非线程安全,多线程的场景下使用ArrayList,可能会出现问题,可以使用Collections的synchronizedList方法将其转成一个线程安全的List再使用

      List<Integer> list = new ArrayList<Integer>();
      list.add(11);
      list.add(22);
      list.add(33);
    
      List<Integer> integers = Collections.synchronizedList(list);
      integers.add(44);

    7、List与Set的区别

     List和Set都继承与Collection接口

     特点

      List:一个有序(存入和取出的顺序一致)的容器,可以插入Null值,可以有重复元素,元素都有索引,常用的实现类有ArrayList,LinkedList,Vector.

      Set:一个无序(存入和取出的顺序可能不一致)的容器,不允许重复元素,只允许存入一个NULL值,必须保证元素的的唯一性,Set常见的实现类有HashSet,LinkedHashSet,TreeSet.

     遍历

      List因为是有序的,所以支持使用for,也就是通过下标进行遍历,迭代器遍历,而Set只支持迭代器遍历,因为他是无序的,无法通过下标来获取值。

    8、说一下HashSet的实现原理,

      HashSet是基于HashMap实现的HashSet的值存放在HashMap的 key 上,相关的HashSet的操作,基本上都是直接调用底层的HashMap的相关方法来实现的,并且HashSet不可重复,是无序的

    9、说一下HashSet如何检查重复,如何保证数据不可重复?

      说在前面:HashSet是Set的实现,不是Map接口下的实现。。。。
      HashSet的add方法底层使用HashMap的put方法来插入数据,判断数据是否存在的依据,不仅要比较hashcode值还要equals方法。
      HashSet部分源码:

    private static final Object PRESENT = new Object();
    private transient HashMap<E,Object> map;
    
    public HashSet() {
       
        map = new HashMap<>();
    }
    
    public boolean add(E e) {
       
        // 调用HashMap的put方法,PRESENT是一个至始至终都相同的虚值
        return map.put(e, PRESENT)==null;
    }

      HashMap的key是唯一的,由源码可知HashSet的key就是使用HashMap的key,如果HashSet中遇到相同的key时,对于新的value就会覆盖旧的value,返回旧的value,所以是不会重复的。
      HashMap比较key是否相等是先比较hashcode,再equals

      <mark>回顾hashcode和equals。</mark>
      Java对hashcode()和equals()有以下规定:

    1. 如果两个对象相等,则它们的hashcode()一定相等
    2. 如果两个对象相等,则它们的equals也返回true
    3. 如果两个对象的hashcode相等,但是它们不一定相等。

      综上我们再重写equals时,规定也必须重写hashcode
      hashcode()的默认行为是对堆上的对象产生独特值,如果没有重写hashcode(),无论如何两个对象都不会相等(即使两个对象指向相同的数据)
      == 与 equals的区别

      • == 是判断两个变量或实例是否指向相同的内存地址,equals是判断两个变量或实例指向的内存地址对应的值是否相等
      • ==是对内存地址进行比较,equals是对字符串进行比较
      • ==是比较引用是否相同,equals是值是否相同

    10、 HashSet和HashMap的区别?

      

    HashMapHashSet
    实现Map接口 实现Set接口
    存储键值对 存储对象
    调用put方法向map中添加元素 调用add方法向Set中添加元素
    HashMap使用key来计算hashcode值 HashSet使用成员对象来计算hashcode值,如果相等则在调用equals判断,如果对象不同的话,返回false
    HashMap相比HashSet快,因为它是使用唯一的key来获取值 HashSet比HashMap稍慢点

    11、comparable和comparator的区别

    1. comparable在java.lang.Comparable它有一个comparaTo方法用于排序;comparator在java.util包中,它有一个compare(Object obj1,Object obj2)用于排序
    2. 如果实现类没有实现comparable接口或者实现了comparable接口但是不满足于comparable接口提供的compareTo方法,我们可以自定义比较方法,只需要实现Comparator接口重写compare(Object obj1,Object obj2)方法。
    3. comparable需要比较对象来实现接口,使用对象调用方法来比较对象,需要改变对象内部结构(重写compareTo),耦合度高。comparator相当于一个通用的比较工具接口,需要定制一个比较类去实现它,重写里面的compare方法,方法参数即比较的对象,对象不用做任何的改变,解耦。

    12、Collection和Collections的区别

      Collectionjava.utils.Collectioni的集合接口,也是集合的顶级接口,它提供了对集合对象的基本操作和通用方法,Collection类在Java类库中有很多体现,直接实现类有List,Set。
      Collections:是集合类的一个工具类,提供了一系列的静态方法,用于对集合中的元素进行排序,搜索等操作

    三、Map

    1、Hashtable和ConcurrentHashMap有什么区别? 

      锁分段技术:首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。 

      ConcurrentHashMap提供了与Hashtable和SynchronizedMap不同的锁机制。Hashtable中采用的锁机制是一次锁住整个hash表,从而在同一时刻只能由一个线程对其进行操作;而ConcurrentHashMap中则是一次锁住一个桶。

      ConcurrentHashMap默认将hash表分为16个桶,诸如get、put、remove等常用操作只锁住当前需要用到的桶。这样,原来只能一个线程进入,现在却能同时有16个写线程执行,并发性能的提升是显而易见的。

    2、Vector、Collections.synchronizedList 和CopyOnWriteArrayList有什么区别? 

      ArrayList是线程不安全的,但是有几个与它结构相似的容器是线程安全的: Vector、Collections.synchronizedList 和CopyOnWriteArrayList

      下面分别说一下这几个线程安全的容器的区别:

      Vector:它几乎在每个方法声明处都加了synchronized关键字来使容器安全

      Collections.synchronizedList:也是几乎都是每个方法都加上synchronized关键字的,只不过它不是加在方法的声明处,而是方法的内部

      CopyOnWriteArrayList

    原文入口:https://blog.nowcoder.net/n/62973d62e5214fc4aebc1df8cdd571dd#11__5

     

    一个小小后端的爬行痕迹
  • 相关阅读:
    CF1236B Alice and the List of Presents |数学
    luogu P1832 A+B Problem |背包
    CF832D Misha, Grisha and Underground |LCA
    bzoj1709[Usaco2007 Oct]Super Paintball超级弹珠*
    bzoj3314[Usaco2013 Nov]Crowded Cows*
    bzoj4300绝世好题
    bzoj2101[Usaco2010 Dec]Treasure Chest 藏宝箱*
    bzoj3437小P的牧场
    bzoj2016[Usaco2010]Chocolate Eating*
    bzoj2015[Usaco2010 Feb]Chocolate Giving*
  • 原文地址:https://www.cnblogs.com/heikedeblack/p/14985087.html
Copyright © 2020-2023  润新知