Java 集合(二)——List、Set集合和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 集合有的特点它都有,同时它还有以下特点:

  1. 是一个无序的集合,存储元素和取出元素的顺序有可能不一致。
  2. 底层是一个哈希表结构,查询的速度非常的快。

HashSet 集合代码演示如下所示:

public class SetDemo01 {
   

    public static void main(String[] args) {
   
        Set<Integer> set = new HashSet<>();
        // 使用 add() 方法添加元素
        set.add(1);
        set.add(3);
        set.add(2);
        set.add(1);

        // 使用迭代器遍历集合
        Iterator<Integer> 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); // 1163157884

        Person 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@4554617c
        System.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<String> set = new HashSet<String> ();
        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” 只有一个)
结果

我们根据代码来分析一下:

  1. HashSet set = new HashSet ():现在我们已经知道hashSet 底层是一个哈希表,所以这句代码会创建一个哈希表。
  2. set.add(s1):add() 方法会调用 s1 的 hashCode() 方法。计算字符串 “abc” 的哈希值,哈希值是 96354,在集合中找有没有 96354 这个哈希值的元素,发现没有就把 s1 存储到集合中
  3. set.add(s2):add() 方法会调用 s2 的 hashCode() 方法。计算字符串 “abc” 的哈希值,哈希值是 96354,在集合中找有没有 96354 这个哈希值的元素,发现有(哈希冲突),s2 会调用 equals() 方法和哈希值相同的元素进行比较,s2.equals(s1) 返回 true,两个元素相同,就不会把 s2 存储到集合中。
  4. set.add(“重地”);:add() 方法会调用 “重地” 的 hashCode() 方法。计算字符串 “重地” 的哈希值,哈希值是
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值