Java的单列表——Set

60 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第32天,点击查看活动详情


Set系列集合

  • 无序:存取顺序不一致
  • 不重复:可以去除重复
  • 无索引:没有带索引的方法,所以不能使用普通for循环遍历,也不能通过索引来获取元素

Set集合的实现类

  • HashSet:无序、不重复、无索引
  • LinkedHashSet:有序、不重复、无索引
  • TreeSet:可排序、不重复、无索引

存储字符串并遍历

利用Set系列的集合,添加字符串,并使用多种方式遍历

  • 迭代器
  • 增强for
  • Lambda表达式

1.创建一个Set集合的对象

Set<String> s = new HashSet<>();

2.添加元素

s.add("张三");  
s.add("张三");  
s.add("李四");  
s.add("王五");
  • 如果当前元素是第一次添加,那么可以添加成功,返回true
  • 如果当前元素是第二次添加,那么添加失败,返回false

3.打印集合

System.out.println(s);//[李四, 张三, 王五]

4.迭代器遍历

Iterator<String> iterator = s.iterator();  
while (iterator.hasNext()) {  
    String str = iterator.next();  
    System.out.println(str);  
}

5.增强for

for (String str : s) {  
    System.out.println(str);  
}

6.Lambda表达式

s.forEach(str -> System.out.println(str));

456结果:

image.png

HashSet底层原理

  • HashSet集合底层采取哈希表存储数据
  • 哈希表是一种对于增删改查数据性能都较好的结构

哈希值:对象的整数表现形式

  • 根据hashCode方法算出来的int类型的整数
  • 该方法定义在Object类中,所有对象都可以调用,默认使用地址值进行计算
  • 一般情况下,会重写hashCode方法,利用对象内部的属性值计算哈希值

对象的哈希值特点:

  • 如果没有重写hashCode方法,不同对象计算出的哈希值是不同的
  • 如果已经重写hashCode方法,不同的对象只要属性值相同,计算出的哈希值就是一样的
  • 在小部分情况下,不同的属性值或者不同的地址值计算出来的哈希值也有可能一样(哈希碰撞)

1.创建对象

Student student1 = new Student("zhangsan", 18);  
Student student2 = new Student("zhangsan", 18);

2.如果没有重写hashCode方法,不同对象计算出的哈希值是不一样的

System.out.println(student1.hashCode());  
System.out.println(student2.hashCode());

结果:

image.png

3.重写hashCode

@Override  
public int hashCode() {  
    return Objects.hash(name, age);  
}

结果:

image.png

4.在小部分情况下,不同的属性值或者不同的地址值计算出来的哈希值也有可能一样(哈希碰撞)

System.out.println("abc".hashCode());  
System.out.println("acD".hashCode());

结果:

image.png

LinkedHashSet底层原理

  • 有序、不重复、无索引
  • 这里的有序指的是保证存储和取出的元素顺序一致
  • 原理:底层数据结构依然是哈希表,只是每个元素又额外的多了一个双链表的机制记录存储的顺序

1.创建4个学生对象

Student student1 = new Student("zhangsan", 18);  
Student student2 = new Student("lisi", 19);  
Student student3 = new Student("wangwu", 20);  
Student student4 = new Student("zhangsan", 18);

2.创建集合的对象

LinkedHashSet<Student> linkedHashSet = new LinkedHashSet<>();

3.添加元素

System.out.println(linkedHashSet.add(student1));  
System.out.println(linkedHashSet.add(student2));  
System.out.println(linkedHashSet.add(student3));  
System.out.println(linkedHashSet.add(student4));

4.打印集合

System.out.println(linkedHashSet);

结果:

image.png 可以看到输入输出的顺序一致