Java集合Set 集合、List和Collections类
一、前言在 Java 集合(一) 中我们已经讲了 Collection 集合接口、Iterator 迭代器和泛型 , 今天我们来讲 Set 集合、List 集合 和 Collections 工具类 。
二、Set 集合Set 接口继承自 Collection 接口 , 它与 Collection 接口中地方法基本一致 , 并没有对 Collection 接口进行功能上的扩展 , 只是比 Collection 接口更加严格了 , 与 List 集合不同的是 , Set 集合不允许存储重复的元素 , 而且 Set 集合是没有索引的 。
Set 集合有多个子类 , 这里我们介绍其中的 HashSet 与 LinkedHashSet 这两个集合 。
2.1、HashSet 集合HashSet 集合实现了 Set 接口 , 首先 Set 集合有的特点它都有 , 同时它还有以下特点:
- 是一个无序的集合 , 存储元素和取出元素的顺序有可能不一致 。
- 底层是一个哈希表结构 , 查询的速度非常的快 。
public class SetDemo01 {public static void main(String[] args) {Set set = new HashSet<>();// 使用 add() 方法添加元素set.add(1);set.add(3);set.add(2);set.add(1);// 使用迭代器遍历集合Iterator iterator = set.iterator();while (iterator.hasNext()) {System.out.println(iterator.next());}// 使用增强 for 循环遍历for (Integer integer : set) {System.out.println(integer);}}}复制代码
2.2、哈希值哈希值是一个十进制的整数 , 由系统随机给出 , 实际上就是对象的地址值 , 是一个逻辑地址 , 是模拟出来的地址 , 不是数据实际存储的物理地址 。 在 Object 类有一个方法 hashCode() , 可以获取对象的哈希值 。hashCode() 方法源码如下:(native 代表该方法调用的是本地操作系统的方法)
public native int hashCode();复制代码
toString() 的源码如下:public String toString() {return getClass().getName() + "@" + Integer.toHexString(hashCode());}复制代码
可以看出 toString() 也调用了 hashCode() 并将其转化为十六进制 。哈希值代码演示如下所示:
public class Person extends Object {public static void main(String[] args) {Person p1 = new Person();int h1 = p1.hashCode();System.out.println(h1); // 1163157884Person p2 = new Person();int h2 = p2.hashCode();System.out.println(h2); // 1956725890/*** toString() 的源码* public String toString() {*return getClass().getName() + "@" + Integer.toHexString(hashCode());*}*/System.out.println(p1); // com.zjgsu.Set.Person@4554617cSystem.out.println(p2); // com.zjgsu.Set.Person@74a14482/*** String 类的哈希值* String 类重写了 hashCode() 所以下面两个哈希值是一样的*/String s1 = new String("abc");String s2 = new String("abc");System.out.println(s1.hashCode());System.out.println(s2.hashCode());}}复制代码
2.3、哈希表在 JDK1.8 之前哈希表 =数组 + 链表 , 但是在JDK1.8之后 , 哈希表 = 数组 + 链表 + 红黑树(提高查询效率) 。 具体如下图所示:文章插图
2.4、Set 集合存储元素不重复的原理我们先来执行以下下面的代码:
public class SetDemo02 {public static void main(String[] args) {HashSet set = new HashSet ();String s1 = new String("abc");String s2 = new String("abc");set.add(s1);set.add(s2);set.add("重地");set.add("通话");set.add("abc");System.out.println(set); // [重地, 通话, abc]}}复制代码
打印结果如下所示:(可以看到 "abc" 只有一个)文章插图
我们根据代码来分析一下:
- HashSet set = new HashSet ():现在我们已经知道hashSet 底层是一个哈希表 , 所以这句代码会创建一个哈希表 。
- set.add(s1):add() 方法会调用 s1 的 hashCode() 方法 。 计算字符串 “abc” 的哈希值 , 哈希值是 96354 , 在集合中找有没有 96354 这个哈希值的元素 , 发现没有 , 就把 s1 存储到集合中 。
- set.add(s2):add() 方法会调用 s2 的 hashCode() 方法 。 计算字符串 “abc” 的哈希值 , 哈希值是 96354 , 在集合中找有没有 96354 这个哈希值的元素 , 发现有(哈希冲突) , s2 会调用 equals() 方法和哈希值相同的元素进行比较 , s2.equals(s1) 返回 true , 两个元素相同 , 就不会把 s2 存储到集合中 。
- set.add("重地");:add() 方法会调用 "重地" 的 hashCode() 方法 。 计算字符串 “重地” 的哈希值 , 哈希值是 1179395 , 在集合中找有没有 1179395 这个哈希值的元素 , 发现 没有 , 就把"重地"存储到集合中 。
- set.add("通话");:add() 方法会调用 "通话" 的 hashCode() 方法 。 计算字符串 “通话” 的哈希值 , 哈希值是 1179395 , 在集合中找有没有 1179395 这个哈希值的元素 , 发现有(哈希冲突) , "通话" 会调用 equals() 方法和哈希值相同的元素进行比较 , "通话".equals("重地") 返回 false , 两个元素不同 , 就把"通话"存储到集合中 。
- 现状|程序员现状揭秘:平均年薪20.36万,Java人才需求量最大
- 程序员学英语第1天——JavaScript 程序测试的介绍1
- 三年Java开发,刚从美团、京东、阿里面试归来,分享个人面经
- 《深入理解Java虚拟机》:对象创建、布局和访问全过程
- java面试题整理
- Kotlin集合vs Kotlin序列与Java流
- Java安全之Javassist动态编程
- 推荐Java工程师必看,12个Hadoop领域的上手项目
- 震惊!京东T4大佬面试整整三个月,才写了两份java面试笔记
- 整理:常见的Java开发框架有哪些,看过,就赶紧收藏吧