1.
Set<String> set = new HashSet<>();
Set集合:添加的元素是无序、不重复、无索引。无序指的是执行一次无序,无序的顺序定下来了,再执行也是这个顺序。
HashSet:无序、不重复、无索引。
linkedHashSet:有序、不重复、无索引。
TreeSet:按照大小默认升序、不重复、无索引。
2.HashSet的底层原理
哈希值:一个int类型的数,Java中每个对象都有一个哈希值。
哈希值(Hash Value)是通过哈希函数将输入数据(如字符串、文件等)映射为固定长度的值(通常是数字)的一种结果。它在计算机科学中具有广泛的应用,包括数据存储、快速查找、数据完整性验证等。以下是一些与哈希值相关的概念和应用:
(1)哈希函数将任意长度的输入转换为固定长度的输出。理想的哈希函数具有以下特性:
- 确定性:相同的输入始终产生相同的哈希值。
- 快速计算:从输入计算哈希值的过程应迅速。
- 抗碰撞性:不同的输入尽量产生不同的哈希值。
- 均匀分布:哈希值应均匀分布,避免聚集现象。
(2)应用
- 数据结构:如哈希表(Hash Table),利用哈希值快速查找和存储数据。
- 数据完整性:通过对文件内容计算哈希值,验证数据在传输或存储过程中是否被修改。
- 密码学:在安全算法中使用哈希函数保护密/码和敏感信息。
public class Main {
public static void main(String[] args) {
String input = "Hello, world!";
// 计算哈希值
int hashValue = input.hashCode();
System.out.println("输入: " + input);
System.out.println("哈希值: " + hashValue);
}
}
(3)注意事项
- 不同的哈希函数在对同一数据进行哈希时会产生不同的值。
- 理论上,哈希值可能碰撞(即不同数据产生相同哈希值)(哈希碰撞),但理想情况下,这种情况应尽量减少。
------------------------------------------------------------------------------------------------------------------------
这就是无序、不重复、无索引的原因。默认加载因子是为了之后扩容的,当占满了16*0.75=12的时候,就会扩容。
哈希表是增删改查都较好的结构。
当挂载的链表长度超过8的时候,且数组长度大于等于64时,自动将链表转为红黑树(自平衡二叉树)。
小的元素挂在左边,大的元素挂在右边。
3.深入理解HashSet
HashSet集合默认不能对内容一样的两个对象去重复。如果也需要内容去重复,可以在构造器重写hsahCode和equals方法
4.LinkedSet集合的底层原理
linkedHashSet:有序、不重复、无索引。
5.TreeSet集合的底层原理
基于红黑树
5.总结
6.注意事项
集合的并发修改异常:使用迭代器遍历集合时,又同时删除集合里的数据,程序容易发生并发修改异常的错误。
public class test {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("王麻子");
list.add("小李子");
list.add("李爱花");
list.add("李爱花");
list.add("张金霞");
list.add("张金霞");
list.add("张金霞");
list.add("李玉刚");
System.out.println(list);
// 需求:找出集合中全部带“李”的名字,并从集合中删除。
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String name = it.next();
if (name.contains("李")) {
//list.remove(name);//会发生并发修改异常,因为迭代器遍历时,list也在修改;增强for循环和lambda表达式也不行
it.remove();//正确的做法,使用迭代器删除元素,每删除一个数据,相当于在底层i--;for循环倒着遍历。
}
}
System.out.println(list);
}
}