Set : 无序,不可重复|去重
无序: 存放的顺序与内部真实存储的顺序不一致去重: 集合不包含元素对e1和e2 ,使得e1.equals(e2)和最多一个null元素。
遍历方式:
foreach
iterator迭代器
public class Class001_Set {
public static void main(String[] args) {
Set set = new HashSet<>();
set.add("ddd");
set.add("aaa");
set.add("ccc");
set.add("bbb");
set.add("bbb");
set.add("bbb");
set.add(null);
set.add(null);
set.add(null);
System.out.println(set);
System.out.println("----------foreach--------------");
for(String str:set){
System.out.println(str);
}
System.out.println("----------iterator迭代器--------------");
Iterator it = set.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
}
1.TreeSet 实现类
底层结构 :
红黑树
特点 :
查询效率较高,自动把数据做升序排序
底层是由TreeMap维护的
新增功能:
新增了一些与比较大小相关的方法(详见如下代码)
遍历方式 :
foreach
iterator迭代器
注意 :
TreeSet需要存储相同类型的数据,因为会默认存在比较排序
public class Class002_TreeSet {
public static void main(String[] args) {
TreeSet tree = new TreeSet();
tree.add(3.2);
tree.add(2.2);
tree.add(5.2);
tree.add(1.2);
tree.add(.2);
System.out.println(tree);
TreeSet tree2 = new TreeSet();
tree2.add("bc");
tree2.add("ab");
tree2.add("a");
tree2.add("abc");
System.out.println(tree2);
//E ceiling(E e) 返回此set中大于或等于给定元素的 null元素,如果没有这样的元素,则 null 。
System.out.println(tree.ceiling(2.3));
//E floor(E e) 返回此set中小于或等于给定元素的最大元素,如果没有这样的元素,则 null 。
System.out.println(tree.floor(2.3));
//E first() 返回此集合中当前的第一个(最低)元素。
System.out.println(tree.first());
//E last() 返回此集合中当前的最后一个(最高)元素。
//E higher(E e) 返回此集合中的最小元素严格大于给定元素,如果没有这样的元素,则 null 。
System.out.println(tree.higher(2.2));
//E lower(E e) 返回此集合中的最大元素严格小于给定元素,如果没有这样的元素,则 null 。
//E pollFirst() 检索并删除第一个(最低)元素,如果此组为空,则返回 null 。
//E pollLast() 检索并删除最后一个(最高)元素,如果此集合为空,则返回 null 。
System.out.println(tree.pollFirst());
System.out.println(tree);
}
}
利用TreeSet 来实现存储Javabean类型的数据
TreeSet的去重与排序: 都是根据比较规则实现的,与equals没有关系
排序比较规则:
内部比较器|内部比较规则|自然排序 : 比较规则定义在javabean类型的内部
javabean类型实现Comparable接口,重写compareTo(T o)方法,在方法中定义比较规则外部比较器|外部比较规则|定制排序 : 比较规则定义在javabean类型的外部
先定义一个实现类,实现Comparator接口,再重写int compare(T o1, T o2),在方法中定义比较规则
升序和降序
TreeSet在做排序的时候: 把两个数据e1,e2调用compareTo看返回值决定大小,默认升序排序,小的放在前面,大的放在后面
e1–>this : 101; e2–>o : 102
升序:<0 --------> e1 e1.compareTo(e2)–>o.id-this.id;: 1 注意: TreeSet就是根据指定的比较规则,对数据做默认的升序排序但是可以根据自定义的比较方式的实现,真实的实现根据指定内容升序|降序
此类允许null元素。且此实现不同步。 底层结构:
哈希表(数组+链表+红黑树) 特点:
查询,增删效率高 ,去重,无序 底层是由HashMap维护的遍历:
foreachiterator迭代器 新增方法 : 无
定义: Map接口储存一组成对的键-值对象,提供key(键)到value(值)的映射,Map中的key不要求有序,不允许重复( 同 Set)。value同样不要求有序,但可以重复(同Collection)。最常见的Map实现类是HashMap,他的储存方式是哈希表,优点是查询指定元素效率高。K-V可以为任意引用数据类型 (Map其实就是保存了两个对象之间的映射关系的一种集合。) 特点: 方法: 遍历方式: 1.values 获取所有键值对的值 TreeMap简介 - 幽暗森林之猪大屁 - 博客园 (cnblogs.com) TreeMap 实现了Map接口,成为Map框架中的一员,可以包含着key-value形式的元素; 底层: 红黑树 特点: 存储键值对类型的数据,自动升序排序,去重的去重,排序: 根据键值对的key实现,与value本身无关TreeSet底层是由TreeMap 请注意,此实现不同步。 去重|排序: 根据key的类型的比较规则 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6NutuYz9-1647964445208)(JavaSE初级知识 212640.assets/key_value.png)] HashMap基于哈希表的Map接口的实现。 此实现提供了所有可选的映射操作,并允许null值和null键。 HashSet 底层是由HashMap维护的 底层结构 : 哈希表(数组+链表+红黑树) 哈希表: 初始容量: 哈希表中的数组默认的初始长度 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计算哈希值 2.调用putVal方法实现添加数据(hash,key,value) HashMap去重 : 根据key做去重,要求key的数据类型重写hashCode与equals方法 HashMap排序:HashMap不能排序,因为Hash是链表,不存在排序,只有TreeSet和TreeMap可以排序。 Hashtable 与 HashMap之间的异同点: * * * 共同点 : 都是Map接口的实现类,底层结构都是哈希表 5.计算hash值与位桶索引index的算法不同 如何处理HashMap线程不安全问题: 1.使用Hashtablepublic class Class003_Comparable {
public static void main(String[] args) {
//TreeSet
2.HashSet 实现类 * * *
public class Class004_HashSet {
public static void main(String[] args) {
System.out.println("abc".hashCode());
System.out.println(new Person("zhangsan",18).hashCode());
System.out.println(new Person("zhangsan",18).hashCode());
System.out.println(new Integer(105).hashCode());
HashSet
8.3 Map 接口
8.3.1 Map 接口
一个key只能对应一个Value
当key相同时,value就会被覆盖get(Object key)返回指定键映射到的值,如果此映射不包含键的映射,则返回 nullclear()从此映射中删除所有映射(可选操作)。remove(Object key)如果存在,则从该映射中移除键的映射(可选操作)。
Collection values() 返回此映射中包含的值的Collection视图。
2.keySet 获取所有键值对的key,根据key获取value
Set keySet() 返回此映射中包含的键的Set视图。
3.entrySet 获取所有的键值对,每一个键值对都是一个Entry类型->表示一个键值对
Setpublic class Class001_Map {
public static void main(String[] args) {
Map
8.3.2 TreeMap 实现类
key的数据类型实现内部比较器
传递外部比较规则
public class Class002_TreeMap {
public static void main(String[] args) {
//TreeMap
8.3.3 HashMap 实现类
数组 : 节点数组Node[] --> 要求数组的长度为2的整数次幂
Node : int hash,Object key,Object value,Node next
每个索引位置存储的为一个单向链表的首节点(尾插法)
当链表的长度>8,数组的长度>64,会把链表优化成为红黑树
当链表的长度>8,但是数组的长度不大于64,这时候会实现扩容(数组的扩容)
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
通过key的hashCode方法的返回值进一步进行hash算法的运算,得到的整数
int hash = (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
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;
不同点 :
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
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;
2.使用Collections工具类中static
3.juc高级并发编程包 ConcurrentHashMap



