集合
集合是“确定的一堆东西”,集合里的“东西”则称为元素。现代的集合一般被定义为:由一个或多个确定的元素所构成的整体 。
集合分类
Collection 接口的接口 对象的集合(单列集合)
├——-List 接口:元素按进入先后有序保存,可重复
│—————-├ LinkedList 接口实现类, 链表, 插入删除, 没有同步, 线程不安全
│—————-├ ArrayList 接口实现类, 数组, 随机访问, 没有同步, 线程不安全
│—————-└ Vector 接口实现类 数组, 同步, 线程安全
│ ———————-└ Stack 是Vector类的实现类
└——-Set 接口: 仅接收一次,不可重复,并做内部排序
├—————-└HashSet 使用hash表(数组)存储元素
│————————└ LinkedHashSet 链表维护元素的插入次序
└ —————-TreeSet 底层实现为二叉树,元素排好序
Map 接口 键值对的集合 (双列集合)
├———Hashtable 接口实现类, 同步, 线程安全
├———HashMap 接口实现类 ,没有同步, 线程不安全-
│—————–├ LinkedHashMap 双向链表和哈希表实现
│—————–└ WeakHashMap
├ ——–TreeMap 红黑树对所有的key进行排序
└———IdentifyHashMap
线程安全的集合都有哪些
线程安全
就是当多线程访问时,采用了加锁的机制;即当一个线程访问该类的某个数据时,会对这个数据进行保护,其他线程不能对其访问,直到该线程读取完之后,其他线程才可以使用。防止出现数据不一致或者数据被污染的情况。
线程安全的集合对象
Vector 线程安全
HashTable 线程安全
StringBuffer 线程安全
集合大纲图
Collection 接口
collection的父类是Iterable接口,Iterable是集合中的顶级父类。
我们翻源码可以发现 collection 下都有哪些集合
让我们一起来看看这个Collection里边的方法
package java.util;
import java.util.function.Predicate;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
/**
* @author Josh Bloch
* @author Neal Gafter
* @see Set Set 接口: 仅接收一次,不可重复,并做内部排序
* @see List List 接口:元素按进入先后有序保存,可重复
* @see Map Map 接口 键值对的集合 (双列集合)
* @see SortedSet
* @see SortedMap
* @see HashSet
* @see TreeSet
* @see ArrayList
* @see LinkedList
* @see Vector
* @see Collections
* @see Arrays
* @see AbstractCollection
*/
public interface Collection<E> extends Iterable<E> {
int size(); //获取集合的大小
boolean isEmpty();//判断集合是否为空
boolean contains(Object o);//判断这个集合中是否存在这个数据 存在返回true 不存在则 false
Iterator<E> iterator();//迭代器循环
Object[] toArray();//将list直接转为Object[] 数组;
<T> T[] toArray(T[] a);//将list转化为你所需要类型的数组,当然我们用的时候会转化为与list内容相同的类型。
boolean add(E e);//像集合中添加数据
boolean remove(Object o);//删除所传入的值
boolean containsAll(Collection<?> c);//判断集合中是否存在所传入集合中的元素
boolean addAll(Collection<? extends E> c);//像本集合中添加集合
boolean removeAll(Collection<?> c);//删除存在于指定集合中的动态数组元素。
default boolean removeIf(Predicate<? super E> filter) {//按照一定规则过滤集合中的元素
Objects.requireNonNull(filter);
boolean removed = false;
final Iterator<E> each = iterator();
while (each.hasNext()) {
if (filter.test(each.next())) {
each.remove();
removed = true;
}
}
return removed;
}
boolean retainAll(Collection<?> c);//删除指定集合中不存在的那些元素。
void clear();//清空集合
boolean equals(Object o);//比较
int hashCode();//获取当前对象的hash值
@Override
default Spliterator<E> spliterator() {//作用是为并行提供一个可切割的spliterator,然后可以并行处理
return Spliterators.spliterator(this, 0);
}
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
default Stream<E> parallelStream() {
return StreamSupport.stream(spliterator(), true);
}
}
我们可以发现 Collection下的集合很多 常用的有 List Set Map 这三个集合
List
├——-List 接口:元素按进入先后有序保存,可重复
│—————-├ LinkedList: 接口实现类, 链表, 插入删除, 没有同步, 线程不安全
│—————-├ ArrayList: 接口实现类, 数组, 随机访问, 没有同步, 线程不安全
│—————-└ Vector: 接口实现类 数组, 同步, 线程安全
│ ———————-└ Stack: 是Vector类的实现类
LinkedList
LinkedList是以链表实现的,插入、删除时只需要改变前后两个节点指针指向即可
ArrayList
ArrayList就是动态数组,用MSDN中的说法,就是Array的复杂版本,它提供了动态
的增加和减少元素,实现了ICollection和IList接口,灵活的设置数组的大小等好处
Vector
Vector是跟ArrayList一样的 只是线程安全,所以 执行起来是比ArrayList 慢
Vector下还有一个Stack实现类 它是一个底层的栈 里边也有一些执行的方法
看一下List集合的方法
package java.util;
import java.util.function.UnaryOperator;
/**
* @see Collection
* @see Set
* @see ArrayList 数组形式,随机访问,没有同步,线程不安全
* @see LinkedList 链表形式, 插入删除, 没有同步, 线程不安全
* @see Vector 数组形式, 同步, 线程安全
*/
public interface List<E> extends Collection<E> {
int size();//获取List集合大小
boolean isEmpty();//判断集合是否为空
boolean contains(Object o);//判断这个集合中是否存在这个数据 存在返回true 不存在则 false
Iterator<E> iterator();迭代器循环输出
Object[] toArray();//将list直接转为Object[] 数组;
<T> T[] toArray(T[] a);//将list转化为你所需要类型的数组,当然我们用的时候会转化为与list内容相同的类型。
boolean add(E e);//向集合中添加数据
boolean remove(Object o);//删除集合中存在的传入值
boolean containsAll(Collection<?> c);//判断集合中是否存在所传入集合中的元素
boolean addAll(Collection<? extends E> c);//向集合中添加集合
boolean addAll(int index, Collection<? extends E> c);//向集合中添加集合 第一个值是 需要插入的地方 从第几个数据开始插入
boolean removeAll(Collection<?> c);//删除跟传入集合中的值相同的元素
boolean retainAll(Collection<?> c);//删除指定集合中不存在的那些元素。
default void replaceAll(UnaryOperator<E> operator) {
Objects.requireNonNull(operator);
final ListIterator<E> li = this.listIterator();
while (li.hasNext()) {
li.set(operator.apply(li.next()));
}
}
@SuppressWarnings({"unchecked", "rawtypes"})
default void sort(Comparator<? super E> c) { //排序
Object[] a = this.toArray();
Arrays.sort(a, (Comparator) c);
ListIterator<E> i = this.listIterator();
for (Object e : a) {
i.next();
i.set((E) e);
}
}
void clear();
boolean equals(Object o);
int hashCode();//获取集合的hash值
E get(int index);//获取集合中第几个值
E set(int index, E element);//向集合中存入数据 第一个值是 插入的地方 第二个是插入的值
void add(int index, E element);//向集合中插入数据 第一个值 是插入的地方,第二个是插入的数据
E remove(int index);//删除集合中指定的第几个值 int
int indexOf(Object o);//从头开始 获取固定元素
int lastIndexOf(Object o);//从尾部开始
ListIterator<E> listIterator();//遍历
//注意获取listIterator迭代器之后,必须调用next()方法,才算进入到list的第一个元素。
//代码中 iter,next(),就是为了让迭代器只向list的第一个元素。所以,可以理解成,直接获取
//迭代器后,迭代器的对象指向的是一个head节点,它的下一个才是开始遍历的元素。
ListIterator<E> listIterator(int index);
List<E> subList(int fromIndex, int toIndex);//获取 规定的值 之间的 元素 第一个 从哪里开始获取(包含),第二个值是 到哪结束 (不包含)
@Override
default Spliterator<E> spliterator() {
return Spliterators.spliterator(this, Spliterator.ORDERED);
}
}
Set
└——-Set 接口: 仅接收一次,不可重复,并做内部排序
├—————-└HashSet 使用hash表(数组)存储元素
│————————└ LinkedHashSet 链表维护元素的插入次序
└ —————-TreeSet 底层实现为二叉树,元素排好序
set接口下还有两个集合 分别问 HashSet 和TreeSet
HashSet:
HashSet是Java集合Set的一个实现类,Set是一个接口
对于 HashSet 而言,它是基于 HashMap 实现的,底层采用 HashMap 来保存元素。
HashSet 下 还有 一个LinkedHashSet 实现
LinkedHashSet:
具有set集合不重复的特点,同时具有可预测的迭代顺序,也就是我们插入的顺序。
并且linkedHashSet是一个非线程安全的集合。如果有多个线程同时访问当前linked
hashset集合容器,并且有一个线程对当前容器中的元素做了修改,那么必须要在外
部实现同步保证数据的冥等性。
TreeSet:
TreeSet是一个有序的集合,它的作用是提供有序的Set集合。它继承了AbstractSet抽象类,
实现了NavigableSet<E>,Cloneable,Serializable接口。TreeSet是基于TreeMap实现的,
TreeSet的元素支持2种排序方式:自然排序或者根据提供的Comparator进行排序。
Set集合都有哪些方法:
package java.util;
/* @see Collection
* @see List
* @see SortedSet
* @see HashSet 使用hash表(数组)存储元素
* @see TreeSet 底层实现为二叉树,元素排好序
* @see AbstractSet
* @see Collections#singleton(java.lang.Object)
* @see Collections#EMPTY_SET
*/
public interface Set<E> extends Collection<E> {
int size();//获取集合大小
boolean isEmpty();//判断集合是否为空
boolean contains(Object o);//判断集合中是否拥有这个数据
Iterator<E> iterator();//迭代器循环输出
Object[] toArray();//将list直接转为Object[] 数组;
<T> T[] toArray(T[] a);//将list转化为你所需要类型的数组,当然我们用的时候会转化为与list内容相同的类型。
boolean add(E e);//向集合中添加数据
boolean remove(Object o);//删除指定跟传入数据相同的元素
boolean containsAll(Collection<?> c);//删除包含传入集合数据的元素
boolean addAll(Collection<? extends E> c);//添加集合
boolean retainAll(Collection<?> c);//删除指定集合中不存在的那些元素。
boolean removeAll(Collection<?> c);//删除跟传入集合中的值相同的元素
void clear();//清空集合中的数据
boolean equals(Object o);//比较哦
int hashCode();//获取hash值
@Override
default Spliterator<E> spliterator() {
return Spliterators.spliterator(this, Spliterator.DISTINCT);
}
}
Map
Map 接口 键值对的集合 (双列集合)
├———Hashtable 接口实现类, 同步, 线程安全
├———HashMap 接口实现类 ,没有同步, 线程不安全-
│—————–├ LinkedHashMap 双向链表和哈希表实现
│—————–└ WeakHashMap
├ ——–TreeMap 红黑树对所有的key进行排序
└———IdentifyHashMap
Hashtable
Hashtable是基于哈希表实现的,每个元素是一个key-value对,其内部是通过单链表解决冲突问题,
容量不足(超过了阀值)时,同样会自动增长。
Hashtable是JDK1.0引入的类,是线程安全的,能用于多线程环境中。
Hashtable实现了Serializable接口,它支持序列化,实现了Cloneable接口,能被克隆。
HashMap
HashMap是基于哈希表实现的,每一个元素是一个key-value对,其内部通过单链表解决冲突问题,
容量不足(超过了阀值)时,同样会自动增长。
HashMap中还包含了 LinkedHashMap 和 WeakHashMap
LinkedHashMap:
它通过维护一个运行于所有条目的双向链表,LinkedHashMap保证了元素迭代的顺序。
该迭代顺序可以是插入顺序或者是访问顺序。
WeakHashMap :
它是一个散列表,它存储的内容也是键值对(key-value)映射,而且键和值都可以是null。
不过WeakHashMap的键是“弱键”。在 WeakHashMap 中,当某个键不再正常使用时,
会被从 WeakHashMap中被自动移除。更精确地说,对于一个给定的键,其映射的存在并
不阻止垃圾回收器对该键的丢弃,这就使该键成为可终止的,被终止,然后被回收。某
个键被终止时,它对应的键值对也就从映射中有效地移除了。
TreeMap
TreeMap存储K-V键值对,通过红黑树(R-B tree)实现;
TreeMap继承了NavigableMap接口,NavigableMap接口继承了SortedMap接口,可支持一系列的
导航定位以及导航操作的方法,当然只是提供了接口,需要TreeMap自己去实现;
TreeMap实现了Cloneable接口,可被克隆,实现了Serializable接口,可序列化;
TreeMap因为是通过红黑树实现,红黑树结构天然支持排序,默认情况下通过Key值的自然顺序进行排序;
Map中的方法
package java.util;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.io.Serializable;
/**
* @author Josh Bloch
* @see HashMap
* @see TreeMap
* @see Hashtable
* @see SortedMap
* @see Collection
* @see Set
* @since 1.2
*/
public interface Map<K,V> {
int size();//获取集合的大小
boolean isEmpty();//判断集合是否为null
boolean containsKey(Object key);//判断集合中是否拥有传入的key值
boolean containsValue(Object value);//判断集合中是否拥有传入的value值
V get(Object key);//获取集合中的数据
V put(K key, V value);//向集合中添加数据(key/value的键值对形式)
V remove(Object key);//删除指定的key
void putAll(Map<? extends K, ? extends V> m);//向集合中添加map集合
void clear();//清空集合
Set<K> keySet();//返回此映射中包含的键的 Set 视图
// 将map中所有的键存入到Set集合,因为set具备迭代器,所有迭代方式取出所有的键
//再根据get()方法 ,获取每一个键对应的值
Collection<V> values();//获取集合中的所有的value值;
Set<Map.Entry<K, V>> entrySet();//返回此映射中包含的映射关系的 Set 视图。 Map.Entry表示映射关系。
//entrySet():迭代后可以e.getKey(),e.getValue()取key和value。返回的是Entry接口 。
interface Entry<K,V> {//使用Entry对象遍历 每个Map集合创建的时候就会创建一个Entry对象用来记录键与值(键值对对象,键与值得映射关系)
K getKey();
V getValue();
V setValue(V value);
boolean equals(Object o);
int hashCode();
public static <K extends Comparable<? super K>, V> Comparator<Map.Entry<K,V>> comparingByKey() {
return (Comparator<Map.Entry<K, V>> & Serializable)
(c1, c2) -> c1.getKey().compareTo(c2.getKey());
}
public static <K, V extends Comparable<? super V>> Comparator<Map.Entry<K,V>> comparingByValue() {
return (Comparator<Map.Entry<K, V>> & Serializable)
(c1, c2) -> c1.getValue().compareTo(c2.getValue());
}
public static <K, V> Comparator<Map.Entry<K, V>> comparingByKey(Comparator<? super K> cmp) {
Objects.requireNonNull(cmp);
return (Comparator<Map.Entry<K, V>> & Serializable)
(c1, c2) -> cmp.compare(c1.getKey(), c2.getKey());
}
public static <K, V> Comparator<Map.Entry<K, V>> comparingByValue(Comparator<? super V> cmp) {
Objects.requireNonNull(cmp);
return (Comparator<Map.Entry<K, V>> & Serializable)
(c1, c2) -> cmp.compare(c1.getValue(), c2.getValue());
}
}
boolean equals(Object o);//比较
int hashCode();//获取map集合的hash值
default V getOrDefault(Object key, V defaultValue) {//集合中如果没有传入的key值 那么就是用默认的 传入的defaultValue值 ,如果有就返回对应的value值
V v;
return (((v = get(key)) != null) || containsKey(key))
? v
: defaultValue;
}
default void forEach(BiConsumer<? super K, ? super V> action) {//循环
Objects.requireNonNull(action);
for (Map.Entry<K, V> entry : entrySet()) {
K k;
V v;
try {
k = entry.getKey();
v = entry.getValue();
} catch(IllegalStateException ise) {
// this usually means the entry is no longer in the map.
throw new ConcurrentModificationException(ise);
}
action.accept(k, v);
}
}
default void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {//将 hashMap 中的所有映射关系替换成给定的函数所执行的结果。
Objects.requireNonNull(function);
for (Map.Entry<K, V> entry : entrySet()) {
K k;
V v;
try {
k = entry.getKey();
v = entry.getValue();
} catch(IllegalStateException ise) {
// this usually means the entry is no longer in the map.
throw new ConcurrentModificationException(ise);
}
// ise thrown from function is not a cme.
v = function.apply(k, v);
try {
entry.setValue(v);
} catch(IllegalStateException ise) {
// this usually means the entry is no longer in the map.
throw new ConcurrentModificationException(ise);
}
}
}
default V putIfAbsent(K key, V value) {//putIfAbsent方法,只有在key不存在或者key为null的时候,value值才会被覆盖
V v = get(key);
if (v == null) {
v = put(key, value);
}
return v;
}
default boolean remove(Object key, Object value) {//删除指定的key/value
Object curValue = get(key);
if (!Objects.equals(curValue, value) ||
(curValue == null && !containsKey(key))) {
return false;
}
remove(key);
return true;
}
default boolean replace(K key, V oldValue, V newValue) {//替换 hashMap 中是指定的 key 对应的 value。
Object curValue = get(key);
if (!Objects.equals(curValue, oldValue) ||
(curValue == null && !containsKey(key))) {
return false;
}
put(key, newValue);
return true;
}
default V replace(K key, V value) {//替换 hashMap 中是指定的 key 对应的 value。
V curValue;
if (((curValue = get(key)) != null) || containsKey(key)) {
curValue = put(key, value);
}
return curValue;
}
default V computeIfAbsent(K key,
Function<? super K, ? extends V> mappingFunction) {//和putIfAbsent类似但是,在返回值上不一样,value值不存在的时候,返回的是新的value值,同时可以通过自定义一些条件进行过滤。
Objects.requireNonNull(mappingFunction);
V v;
if ((v = get(key)) == null) {
V newValue;
if ((newValue = mappingFunction.apply(key)) != null) {
put(key, newValue);
return newValue;
}
}
return v;
}
default V computeIfPresent(K key,
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {//只有当key存在的时候才执行操作
Objects.requireNonNull(remappingFunction);
V oldValue;
if ((oldValue = get(key)) != null) {
V newValue = remappingFunction.apply(key, oldValue);
if (newValue != null) {
put(key, newValue);
return newValue;
} else {
remove(key);
return null;
}
} else {
return null;
}
}
default V compute(K key,
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {//传入的值如果集合中有 那么就替换 如果没有 就他添加进去
Objects.requireNonNull(remappingFunction);
V oldValue = get(key);
V newValue = remappingFunction.apply(key, oldValue);
if (newValue == null) {
// delete mapping
if (oldValue != null || containsKey(key)) {
// something to remove
remove(key);
return null;
} else {
// nothing to do. Leave things as they were.
return null;
}
} else {
// add or replace old mapping
put(key, newValue);
return newValue;
}
}
default V merge(K key, V value,
BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
//1. 如果value不为空,进行merge处理。为空直接赋值newValue。实际上就是一个put操作。
// 然后将key对应的oldValue和newValue 根据传来的function进行处理。
//2 当处理后的value值为空,map会移除当前key
Objects.requireNonNull(remappingFunction);
Objects.requireNonNull(value);
V oldValue = get(key);
V newValue = (oldValue == null) ? value :
remappingFunction.apply(oldValue, value);
if(newValue == null) {
remove(key);
} else {
put(key, newValue);
}
return newValue;
}
}