【JavaSE】Java(五十七):核心要点总结

简介: 1. HashMap 的实现原理HashMap 是一种基于哈希表的数据结构,它的实现原理简单来说就是将键值对存储在一个数组中,并通过哈希算法计算出每个键对应的下标。下面是 HashMap 实现原理的具体步骤:初始化:创建一个长度为 n 的数组(初始默认长度为 16),该数组每个位置可存放一个链表;以及一个负载因子(load factor),用来表示哈希表允许填充的程度。

1. HashMap 的实现原理


HashMap 是一种基于哈希表的数据结构,它的实现原理简单来说就是将键值对存储在一个数组中,并通过哈希算法计算出每个键对应的下标。下面是 HashMap 实现原理的具体步骤:


初始化:创建一个长度为 n 的数组(初始默认长度为 16),该数组每个位置可存放一个链表;以及一个负载因子(load factor),用来表示哈希表允许填充的程度。


存储数据:通过哈希函数将每个键转化成一个唯一的、固定的索引(下标)位置,并将对应的键值对存储到哈希表中。如果发生哈希冲突(即多个键映射到了同一个位置),则会将这些键值对以链表的形式存储在这个位置上。当某个位置上的链表长度超过指定阈值(8)时,这个链表就会被转化成红黑树,并以红黑树的方式存储和管理。


扩容与重新哈希:当哈希表中的元素个数达到负载因子与数组长度的乘积时,哈希表就会触发扩容操作。扩容的本质是创建一个新的、长度为 2n 的数组,并将原有的键值对重新哈希到新的数组中。


计算哈希值:对于键是引用数据类型的情况,不同对象在内存中占据的位置不同,因此不同的对象可能会生成相同的 hashcode。为避免 key 的 hashcode 造成碰撞问题,HashMap 在处理 hashcode 值碰撞时,会再次根据 hashcode 进行比较,以确定正确的值。


HashMap 底层实现采用了数组、链表和红黑树等数据结构,并且通过哈希算法实现键值对的快速查找和增删操作。

2. Set 有哪些实现类

Set 是 Java 中的一种集合数据类型,它存储的元素是无序且不可重复的。Java 中提供了多种 Set 的实现类,并且每个实现类都有自己的特点和应用场景。下面列出几种常见的 Set 实现类:


HashSet:基于哈希表实现,可以快速地查找、插入和删除元素,具有较高的性能。存储的元素是无序的,且由于使用哈希表作为底层数据结构,所以不保证元素的顺序一定不变。


LinkedHashSet:基于哈希表和链表实现,具有 HashSet 的查询操作速度,并且内部使用链表维护了元素的顺序。因此,遍历该集合时会按添加顺序或访问顺序进行迭代。


TreeSet:基于红黑树(一种自平衡二叉搜索树)实现,可以自动对元素进行排序,存储的元素是有序的。它还提供了一些用于操作有序集合(例如获取子集和范围查找)的方法。


EnumSet:这是一个专门用于枚举类型的 Set 实现类,在 Java 5 中引入。该类具有非常好的性能和空间效率,它是通过一个位向量来表示 Set 中每个可能值的出现情况。


CopyOnWriteArraySet:该类是线程安全的 Set 实现类,它通过对底层数组进行复制来实现并发修改。在读操作频繁、写操作较少的场景下,该类的性能表现较好。


选择 Set 的实现类应根据具体业务需求和使用场景,考虑性能、空间占用、数据排序等方面的因素。



3. HashSet 的实现原理


HashSet 是 Java 中 Set 接口的一个实现类,它基于哈希表(Hash Table)数据结构实现。具体来说,HashSet 底层维护了一个哈希表,用于存储集合中的元素。


以下是 HashSet 的实现原理:


创建 HashSet 实例时,会创建一个初始容量为16,并且负载因子为0.75的空的哈希表(数组),并根据默认的哈希算法计算每个元素在哈希表中的桶(bucket)位置。


往 HashSet 中添加元素时,会先对元素的 hashCode 值进行哈希计算,然后将元素加入到对应的桶中。如果哈希表中已经有元素占据了该桶,则采用链表或红黑树等数据结构,在该桶中维护这些元素。


当哈希表中的元素个数超过容量与负载因子的乘积时,就会触发扩容操作。此时,系统将会重新生成一个两倍大小的哈希表,同时将所有现有元素重新哈希分布到新表中,以保证哈希性质不变。


在查找 HashSet 中某个元素时,首先通过 hashCode 计算出该元素所在的桶,然后根据 .equals() 方法比较元素是否相同。如果多个元素都映射到了同一个桶,则遍历链表或红黑树等数据结构寻找目标元素。


HashSet 通过哈希表建立了 key-value 的映射关系,能够实现高效的查询、插入和删除操作。但由于哈希函数并不是唯一且完美的,所以可能会出现哈希冲突和扩容后的额外开销等问题。


4. 如何实现数组和List之间的转换

Java 中可以通过以下方法实现数组和 List 之间的转换:

Java 中可以通过以下方法实现数组和 List 之间的转换:

  1. 数组转 List
// 使用 Arrays.asList 方法将数组转换为 List
Integer[] arr = {1, 2, 3};
List<Integer> list = Arrays.asList(arr);

注意:使用 asList 方法转换后返回的是一个固定长度的 List,不能进行 add、remove 等修改操作。如果需要对 List 进行修改,可以使用 ArrayList 等可变长度的 List 实现。

  1. List 转数组
 // 使用 toArray 将 List 转换为数组
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
Integer[] arr = list.toArray(new Integer[list.size()]);

注意:需要将 List 的泛型类型作为参数传递给 toArray 方法,并将数组初始化为指定的长度,避免出现空指针异常。


除了上述方法,还可以使用 Java8 中引入的 Stream API 以及 Guava、Apache Commons 等第三方库中提供的工具类来实现数组和 List 之间的转换。

5. Java中的迭代器


Java 中的迭代器(Iterator)是一种用于遍历集合(Collection)元素的接口,它提供了 hasNext() 和 next() 两个方法,可以依次访问集合中的每个元素。

使用 Iterator 能够实现对集合的遍历和操作,而无需关心内部数据结构和实现细节。具体来说,可以通过以下步骤使用 Iterator 对集合进行迭代:

  1. 获取集合的迭代器
List<String> list = new ArrayList<>();
Iterator<String> iterator = list.iterator();

使用 while 循环遍历集合中的元素,直到 hasNext() 返回 false

while (iterator.hasNext()) {
    String str = iterator.next();
    // 对当前元素进行操作
}

在循环中调用 next() 方法获取下一个元素,同时更新迭代器状态,直到所有元素都被遍历完毕。


由于 Iterator 可以遍历任何实现了 java.util.Collection 接口的集合类,因此可以方便地操作各种类型的集合。同时,Iterator 还提供了 remove() 方法,可以在遍历过程中删除集合中的特定元素。


需要注意的是,Iterator 遍历集合时,不支持并发修改(Concurrent Modification),即如果在遍历过程中对集合进行了增加、移除等操作,可能会导致抛出 ConcurrentModificationException 异常。为了避免这种情况,可以使用并发集合类(如 ConcurrentHashMap)或使用显示锁(如 ReentrantLock)等方式进行同步。


相关文章
|
7月前
|
存储 Java 测试技术
滚雪球学Java(18):解密JavaSE中的堆栈:你真的了解Java内存吗?
【4月更文挑战第7天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
68 1
滚雪球学Java(18):解密JavaSE中的堆栈:你真的了解Java内存吗?
|
7月前
|
安全 Java 调度
【Java】JavaSE实现多线程
【Java】JavaSE实现多线程
90 1
|
7月前
|
Java C++ 索引
【Java】JavaSE基础知识
【Java】JavaSE基础知识
138 0
|
7月前
|
Java
滚雪球学Java(17):探索循环控制:JavaSE中的break与continue秘技
【4月更文挑战第6天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
72 1
滚雪球学Java(17):探索循环控制:JavaSE中的break与continue秘技
|
7月前
|
存储 安全 Java
滚雪球学Java(19):JavaSE中的内存管理:你所不知道的秘密
【4月更文挑战第8天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
69 4
滚雪球学Java(19):JavaSE中的内存管理:你所不知道的秘密
|
7月前
|
Java 程序员 编译器
JavaSE&Java8 Lambda 表达式
JavaSE&Java8 Lambda 表达式
34 0
|
7月前
|
存储 Java 程序员
JavaSE&Java的异常
JavaSE&Java的异常
50 0
|
7月前
|
存储 Java 测试技术
滚雪球学Java(11):高效编程之道:精通JavaSE顺序结构的关键技巧
【2月更文挑战第23天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,助你一臂之力,带你早日登顶🚀,欢迎大家关注&&收藏!持续更新中,up!up!up!!
73 2
|
7月前
|
存储 编解码 移动开发
【Java】JavaSE的IO流操作
【Java】JavaSE的IO流操作
82 0
|
7月前
|
Java 大数据
Java大数据面试复习30天冲刺 - 日积月累,每日五题【Day04】——JavaSE
Java大数据面试复习30天冲刺 - 日积月累,每日五题【Day04】——JavaSE
66 0
下一篇
DataWorks