声明:题目大部分来源于Java后端公众号,有些个人整理,但答案皆为个人整理,仅供参考。
GitHub:https://github.com/JDawnF
目录
1.Set:集合中的对象不按特定方式排序(针对内存地址来说,即非线性),并且没有重复对象。它的有些实现类能对集合中的对象按特定方式排序。
2.List:集合中的对象线性方式储存,可以有重复对象,允许按照对象在集合中的索引位置检索对象。有序可重复。
1.Map:通过键值对进行取值,key-value一一对应的,其中key不可以重复,而value可以重复
ConcurrentHashMap 的工作原理及代码实现,如何统计所有的元素个数
HashMap 和 ConcurrentHashMap 的区别
什么是CopyOnWriteArrayList,它与ArrayList有何不同?
Java中的集合
Java中的集合主要分为value,key-value(Collection,Map)两种,存储值分为List和Set,存储为key-value得失Map。
Collection接口中主要有这些方法:
boolean add(Object o) :向集合中加入一个对象的引用
void clear():删除集合中所有的对象,即不再持有这些对象的引用
boolean isEmpty() :判断集合是否为空
boolean contains(Object o) : 判断集合中是否持有特定对象的引用
Iterartor iterator() :返回一个Iterator对象,可以用来遍历集合中的元素
boolean remove(Object o) :从集合中删除一个对象的引用
int size() :返回集合中元素的数目
Object[] toArray() : 返回一个数组,该数组中包括集合中的所有元素
boolean equals(Object o):判断值是否相等
int hashCode(): 返回当前集合的hash值,可以作为判断地址是否想相等
Collection接口继承 Iterable<T> 接口,这个接口可以返回一个迭代器,主要有一下三个方法:
List和Set都是继承Collection接口。
List 和 Set 区别
1.Set:集合中的对象不按特定方式排序(针对内存地址来说,即非线性),并且没有重复对象。它的有些实现类能对集合中的对象按特定方式排序。
- 不允许重复对象,只允许一个 null 元素,根据equals和hashcode判断,一个对象要存储在set中,必须重写equals和hashcode方法;
- 无序容器,你无法保证每个元素的存储顺序,TreeSet通过 Comparator 或者 Comparable 维护了一个排序顺序。
- Set 接口最流行的几个实现类是 HashSet、LinkedHashSet 以及 TreeSet。最流行的是基于 HashMap 实现的 HashSet;TreeSet 还实现了 SortedSet 接口,因此 TreeSet 是一个根据其 compare() 和 compareTo() 的定义进行排序的有序容器。
2.List:集合中的对象线性方式储存,可以有重复对象,允许按照对象在集合中的索引位置检索对象。有序可重复。
-
可以允许重复的对象,可以插入多个null元素。
-
是一个有序容器,保持了每个元素的插入顺序,输出的顺序就是插入的顺序。
-
常用的实现类有 ArrayList、LinkedList 和 Vector。ArrayList 最为流行,它提供了使用索引的随意访问,而 LinkedList 则对于经常需要从 List 中添加或删除元素的场合更为合适。
Set和hashCode以及equals方法的联系
因为set接口中是不允许存在重复的对象或者值的,所以需要对存入set中的对象或者值进行判断,而hashCode和equals就是用来对这些对象和值进行判断的。
List 和 Map 区别
1.Map:通过键值对进行取值,key-value一一对应的,其中key不可以重复,而value可以重复
区别:
- Map用 put(k,v) / get(k),还可以使用containsKey()/containsValue()来检查其中是否含有某个key/value。
- List通过get()方法来一次取出一个元素。使用数字来选择一堆对象中的一个,get(0)...。(add/get)
- Collection没有get()方法来取得某个元素。只能通过iterator()遍历元素。
Arraylist 与 LinkedList 区别
1.Arraylist(线程不安全):
- 底层是数组(数组在内存中是一块连续的内存,如果插入或删除元素需要移动内存),可以插入空数据
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable
实现了 RandomAccess 接口,所以支持随机访问
private static final int DEFAULT_CAPACITY = 10;
数组的默认大小为 10。
-
插入数据的时候,会先进行扩容校验,添加元素时使用 ensureCapacityInternal() 方法来保证容量足够,如果不够时,需要使用 grow() 方法进行扩容,新容量的大小为
oldCapacity + (oldCapacity >> 1)
,也就是旧容量的 1.5 倍。public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; }
- 首先进行扩容校验。
- 将插入的值放到尾部,并将 size + 1 。
- 如果是调用
add(index,e)
在指定位置添加的话:public void add(int index, E element) { rangeCheckForAdd(index); ensureCapacityInternal(size + 1); // Increments modCount!! //复制,向后移动 System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; size++; }
- 也是首先扩容校验。
- 接着对数据进行复制,目的是把 index 位置空出来放本次插入的数据,并将后面的数据向后移动一个位置。
private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity < 0) newCapacity =