1. Set
无序,不可重复|去重。
无序: 存放的顺序与内部真实存储的顺序不一致。
去重: 集合不包含元素对e1和e2 ,使得e1.equals(e2)和最多一个null元素。
新增功能: static <E> Set<E> of(E... elements) 返回包含任意数量元素的不可修改集。
遍历方式:
foreach
iterator迭代器
-
常用方法:
E ceiling(E e) 返回此set中大于或等于给定元素的 null元素,如果没有这样的元素,则 null 。 E floor(E e) 返回此set中小于或等于给定元素的最大元素,如果没有这样的元素,则 null 。 E first() 返回此集合中当前的第一个(最低)元素。 E last() 返回此集合中当前的最后一个(最高)元素。 E higher(E e) 返回此集合中的最小元素严格大于给定元素,如果没有这样的元素,则 null 。 E lower(E e) 返回此集合中的最大元素严格小于给定元素,如果没有这样的元素,则 null 。 E pollFirst() 检索并删除第一个(最低)元素,如果此组为空,则返回 null 。 E pollLast() 检索并删除最后一个(最高)元素,如果此集合为空,则返回 null 。
-
TreeSet :
底层结构 : 红黑树。 特点 : 查询效率较高,自动把数据做升序排序,底层是由TreeMap维护的。 新增功能: 新增了一些与比较大小相关的方法。 遍历方式 : foreach iterator迭代器 注意 : TreeSet需要存储相同类型的数据,因为会默认存在比较排序。
-
TreeSet存储javabean类型的数据:
去重与排序: 都是根据比较规则实现的,与equals没有关系 比较规则: 1.内部比较器|内部比较规则|自然排序 : 比较规则定义在javabean类型的内部。 方式:javabean类型实现Comparable接口,重写compareTo(T o)方法,在方法中定义比较规则。 2.外部比较器|外部比较规则|定制排序 : 比较规则定义在javabean类型的外部。 方式:定义一个实现类,实现Comparator接口,重写int compare(T o1, T o2),在方法中定义比较规则。 Arrays.sort(数组) 默认升序排序: static <T> void sort(T[] a, Comparator<? super T> c) 根据指定比较器引发的顺序对指定的对象数组进行排序。
-
定义自然排序方式
两个对象 e1,e2 e1.compareTo(e2) 大小由返回值决定 : 0 ---------> e1==e2 <0 --------> e1<e2 >0 --------> e1>e2 TreeSet在做排序的时候: 把两个数据e1,e2调用compareTo看返回值决定大小,默认升序排序,小的放在前面,大的放在后面。 e1-->this : 101 e2-->o : 102 e1.compareTo(e2)-->this.id-o.id; : -1 升序 : e1,e2 102,102 e1.compareTo(e2)-->o.id-this.id; : 1 升序 : e2,e1 102,101 注意: 1.TreeSet就是根据指定的比较规则,对数据做默认的升序排序。 2.可以根据自定义的比较方式的实现,真实的实现根据指定内容升序|降序。
-
HashSet:
底层结构: 哈希表(数组+链表+红黑树)。 特点: 查询,增删效率高 ,去重,无序,底层是由HashMap维护的。 新增方法 : 无。 遍历: foreach iterator迭代器 注意: 此类允许null元素。 此实现不同步。
2. Map
无序的,去重的。
键值对数据的集合
键值对->映射关系
价值对: K-V
K键 : 无序的,去重的|唯一的 ---> Set
V值 : 无序的,可重复 ---> Collection
K-V可以为任意引用数据类型。
特点:
1.一个key只能对应一个Value。
2.key相同value覆盖。
遍历方式:
1.values 获取所有键值对的值。
Collection<V> values() 返回此映射中包含的值的Collection视图。
2.keySet 获取所有键值对的key,根据key获取value。
Set<K> keySet() 返回此映射中包含的键的Set视图。
3.entrySet 获取所有的键值对,每一个键值对都是一个Entry类型->表示一个键值对。
Set<Map.Entry<K,V>> entrySet() 返回此映射中包含的映射的Set视图。
-
常用方法:
V put(K key, V value) 将指定的值与此映射中的指定键相关联(可选操作)。 V get(Object key) 返回指定键映射到的值,如果此映射不包含键的映射,则返回 null 。 V remove(Object key) 如果存在,则从该映射中移除键的映射(可选操作)。 void clear() 从此映射中删除所有映射(可选操作)。 boolean isEmpty() 如果此映射不包含键 - 值映射,则返回 true 。 boolean containsKey(Object key) 如果此映射包含指定键的映射,则返回 true 。 boolean containsValue(Object value) 如果此映射将一个或多个键映射到指定值,则返回 true 。 static <K,V> Map<K,V> of(K k1, V v1) 返回包含单个映射的不可修改的映射。 default V replace(K key, V value) 仅当指定键当前映射到某个值时,才替换该条目的条目。 int size() 返回此映射中键 - 值映射的数量。
-
TreeMap :
底层: 红黑树。 存储键值对类型的数据,自动升序排序,去重的。 去重,排序: 根据键值对的key实现,与value本身无关。 TreeSet底层是由TreeMap。 注意: 此实现不同步。
-
HashMap :
基于哈希表的Map接口的实现,此实现提供了所有可选的映射操作,并允许null值和null键。 HashSet底层是由HashMap。 底层结构 : 哈希表(数组+链表+红黑树)。
-
哈希表:
数组 : 节点数组Node[] --> 要求数组的长度为2的整数次幂。 Node : int hash,Object key,Object value,,Node next。 每个索引位置存储的为一个单向链表的首节点(尾插法)。 当链表的长度>8,数组的长度>64,会把链表优化成为红黑树。 当链表的长度>8,但是数组的长度不大于64,这时候会实现扩容(数组的扩容)。 初始容量: 哈希表中的数组默认的初始长度 16 static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16 数组的容量最大容量 : static final int MAXIMUM_CAPACITY = 1 << 30; 加载因子: 0.75 一般不建议改变 默认加载因子 : static final float DEFAULT_LOAD_FACTOR = 0.75f; 扩容阀值 threshold : 扩容的临界值。 当数据的个数size>数组的长度*加载因子时就会扩容。 扩容机制: 原容量的2倍。 int newCap = oldCap << 1。 新增功能: 无
-
HashMap的哈希表存储数据的过程:
1.根据key计算哈希值 通过key的hashCode方法的返回值进一步进行hash算法的运算,得到的整数。 int hash = (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); 2.调用putVal方法实现添加数据(hash,key,value) 1)判断是否是第一次调用put方法做添加 if ((tab = table) == null || (n = tab.length) == 0): 如果是第一次添加,直接调用resize()实现扩容。 2)计算位桶的索引 int index = (n - 1) & hash。 3)判断哈希表结构的数组table[index]是否存在数据: 如果不存在数据,证明没有头节点,创建新节点,放入当前数组的对应索引位置作为头节点: table[index] = new Node<>(hash, key, value, next); size数据的个数+1,判断是否>扩容的阀值: 如果大于需要调用resize方法进行扩容。 如果不大于,不需要扩容直接返回null: if (++size > threshold) resize(); return null; 如果存在数据,作为链表的头结点,遍历这个链表,拿到每一个节点的key与hash值判断是否与要添加的key和hash相同,如果相同,value覆盖: if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) value覆盖之后,返回被覆盖的value: V oldValue = e.value; e.value = value; return oldValue;
-
Hashtable 与 HashMap之间的区别:
共同点 : 都是Map接口的实现类,底层结构都是哈希表。 异同点 : 1.继承体系不同。 2.线程是否安全不同: HashMap 线程不安全|不同步。 Hashtable 线程安全的|同步的。 3.扩容机制不同: HashMap扩容机制 : 每次扩容原容量的2倍。 int newCap = oldCap << 1 Hashtable扩容机制 : 原容量的2倍+1。 int newCapacity = (oldCapacity << 1) + 1; 4.键值对数据null值的要求不同: HashMap 可以存储null值的key与value Hashtable key与value都不为null 5.计算hash值与位桶索引index的算法不同: HashMap : int hash = (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); int index = (n - 1) & hash Hashtable : int hash = key.hashCode(); int index = (hash & 0x7FFFFFFF) % tab.length;
-
如何处理HashMap线程不安全问题:
1.使用Hashtable。 2.使用Collections工具类中static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) 返回由指定映射支持的同步(线程安全)映射。 3.juc高级并发编程包 ConcurrentHashMap<K,V>-> 线程安全的哈希表。
3. Collections :
操作集合的工具类
静态工厂
void sort(List) 对List容器内的元素排序,排序的规则是按照升序进行排序。
void shuffle(List) 对List容器内的元素进行随机排列。
void reverse(List) 对List容器内的元素进行逆续排列。
void fill(List, Object) 用一个特定的对象重写整个List容器。
int binarySearch(List, Object) 对于顺序的List容器,采用折半查找的方法查找特定对象。