JAVA面试题整理大全(三、容器)

容器

1. Java 容器都有哪些?

   1)Collection:一个独立元素的序列,这些元素都服从一条或者多条规则。 List必须按照插入的顺序保存元素,而set不能有重复的元素。Queue按照排队规则来确定对象产生的顺序(通常与它们被插入的顺序相同)。
   2)Map:一组成对的“键值对”对象,允许你使用键来查找值。

java容器结构图:

extends
extends
implements
extends
extends
extends
extends
implements
extends
implements
extends
extends
extends
extends
extends
implements
extends
extends
extends
implements
extends
implements
extends
extends
map
map
Collection
java.lang.Iterable
Queue
AbstractCollection
List
Set
Deque
AbstractList
AbstractSequentialList
LinkedList
ArrayList
Vctor
Stack
AbstractSet
TreeSet
HashSet
LinkedHashSet
Map
AbstractMap
HashMap
Hashtable
Dictionary
TreeMap

2. Collection 和 Collections 有什么区别?

   Collection :是定义集合的接口类
   Collections :是操作集合的一个工具类

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

   List 必须按照插入的顺序保存元素,
    set 不能有重复的元素
    Map 根据键值对的形式保存数据元素

4. HashMap 和 Hashtable 有什么区别?

   HashMap :继承于AbstractMap,允许存放null key,null value,线程不安全(多线程访问时,若外部未加同步限制,扩容、空值替换等原因可能出现数据错乱丢失)
   Hashtable :继承于Dictionary,不允许存放null key,null value,操作方法均为synchronized,无需外部同步,线程安全

   两者均是Map的实现类,都是采用了 hash/rehash 算法,尾插法,在jdk 1.8之后hashMap加入红黑树(链表长度达到8时使用红黑树存放,当在6个以下时切换回链表),查询优化效率大幅提升。

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

根据排序场景决定
   TreeMap(红黑树) :基于树形结构排序(key 排序)
   HashMap : 不保证序列
   LinkedHashMap (链表+hash表) : 保证插入顺序

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

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

static class Node<K,V> implements Map.Entry<K,V> {
        final int hash;
        final K key;
        V value;
        Node<K,V> next;
}
transient Node<K,V>[] table;

   HashMap 基于 Hash 算法实现的:

   当我们往Hashmap中put元素时,利用key的hashCode重新hash计算出当前对象的元素在数组中的下标

//通过key计算hash值
static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

   存储时,没有key直接新增到下标第一个,如果出现hash值相同的key,此时有两种情况。(1)如果key相同,则覆盖原始值;(2)如果key不同(出现冲突),则将当前的key-value放入链表中第一个
   获取时,直接找到hash值对应的下标,在进一步判断key是否相同,从而找到对应值。
   理解了以上过程就不难明白HashMap是如何解决hash冲突的问题,核心就是使用了数组的存储方式,然后将冲突的key的对象放入链表中,一旦发现冲突就在链表中做进一步的对比。

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

   HashSet是基于HashMap实现的,内部是存放了一个HashMap,
构造函数:

public HashSet() {
   map = new HashMap<>();
}
public HashSet(Collection<? extends E> c) {
   map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
   addAll(c);
}
public HashSet(int initialCapacity, float loadFactor) {
   map = new HashMap<>(initialCapacity, loadFactor);
}

   当进行存储数据时,会将数据存放到map的key,从而实现可存放null,数据不重复,同时继承了hashMap无序的特性。
(TreeSet默认使用TreeMap,也可指定其他排序map(NavigableMap))

//PRESENT == new Object() 无意义
public boolean add(E e) {
    return map.put(e, PRESENT)==null;
}
public boolean remove(Object o) {
    return map.remove(o)==PRESENT;
}

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

   ArrayList :底层是数组

transient Object[] elementData;

   LinkedList :底层是链表(双向链表)

transient Node<E> first;
transient Node<E> last;

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

(循环、遍历不做演示。)

   1.数组转集合 arr -> list 均为String类 使用Arrays.asList

List<String> list  = Arrays.asList(arr);

   2.数组转集合 arr -> list int <-> Integer 使用stream

list = Arrays.stream(arr).boxed().collect(Collectors.toList());

   3.集合转数组 list -> arr 均为String类 使用toArray

arr = list.toArray(new String[list.size()]);

   4.集合转数组 list -> arr Integer <-> int 使用stream

arr = list.stream().mapToInt(i->i).toArray()

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

   Vector 是线程安全的集合,内部操作方法均使用synchronized修饰,
   ArrayList 是非线程安全集合,内部未采用同步化机制

11. Array 和 ArrayList 有何区别?

   Array数组可以包含基本类型和对象类型,
   ArrayList 是数组的加强版,只能包含对象类型。可以进行自动扩容。

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

   poll(): 返回此队列的开头,如果此队列为空,则返回null
   remove():返回此队列的开头,如果此队列为空,它将抛出异常NoSuchElementException。

13. 哪些集合类是线程安全的?

   Vector:就比Arraylist多了个同步化机制(线程安全)。

   Hashtable:就比Hashmap多了个线程安全。

   ConcurrentHashMap:是一种高效但是线程安全的集合。

   Stack:栈,也是线程安全的,继承于Vector。

14. 迭代器 Iterator 是什么?

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

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

   (1) iterator()方法是java.lang.Iterable接口,被Collection继承。所有Collection下集合使用方法iterator()要求容器返回一个Iterator,第一次调用Iterator的next()方法时,它返回序列的第一个元素。而Map需要调用entrySet或keySet或values(键值set,键set,值Collection)再继续调用iterator()操作
  
   (2) 使用next()获得序列中的下一个元素。
  
   (3) 使用hasNext()检查序列中是否还有元素。
  
   (4) 使用remove()将迭代器新返回的元素删除。

16. Iterator 和 ListIterator 有什么区别?

   Iterator是Java迭代器最简单的实现,
   ListIterator是为List设计的具有更多的功能,它可以从两个方向遍历List,也可以从List中插入和删除元素。
(foreach不能操作内部集合插入、删除)

17. 怎么确保一个集合不能被修改?

利用Collections和Guava提供的类可实现的不可变对象
   Collections:

 map.put(1, "one");
 map.put(2, "two");
 map  = Collections.unmodifiableMap(map);
 map.put(1, "three");

   Guava:

ImmutableList<Integer> list = ImmutableList.of(1, 2, 3);
list.add(4);
ImmutableMap<Integer, Integer> map2 = ImmutableMap.<Integer, Integer>builder().put(1,2).put(3,4).put(5,6).build();
list.put(1,8)

如果进行修改均会抛出UnsupportedOperationException

上一章 JAVA基础
下一章 反射

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值