零基础学习Java之Set集合

  • 概述
  • Set的使用
    • 常用方法介绍
    • Set集合的遍历
      • 代码实例
  • Set的实现类
    • HashSet
      • 基本介绍
      • 代码示例
    • LinkedHashSet
      • 基本介绍
      • 代码示例
    • TreeSet
      • 基本介绍
      • 代码示例

概述

Set接口作为Collection的子接口,按理来说应该在原来接口的基础增加更多的方法,但是Set这个子接口呢,并没有提供额外的方法,只不过是在原来的基础上,对数据的要求更加严格了。

Set接口的特点:

  • 无序性:Set集合中的元素是不要求有顺序的
  • 不可重复性:Set集合中的元素是不能出现重复的
  • 无索引:Set集合中的元素是没有索引的(特定的顺序编号)

Set的使用

常用方法介绍

既然Set没有在Collection的基础上添加新的方法,那么其常用方法也是可以参考Collection的常用方法的
Collection的常用方法可参考本文

Set集合的遍历

与Collection集合的遍历方式一样,Set集合也是支持foreach和Iterator两种方式遍历元素的。

代码实例

package com.atguigu.demo.Set;import java.util.Iterator;
import java.util.LinkedHashSet;public class LinkedSet {public static void main(String[] args) {//创建LinkedHashSet集合LinkedHashSet<String> set = new LinkedHashSet<>();//添加元素set.add("张三");set.add("李四");set.add("王五");set.add("张三");//元素个数System.out.println("元素个数:" + set.size());//增强for遍历元素for (String name : set) {System.out.println(name);}//使用iteratorIterator<String> iterator = set.iterator();while (iterator.hasNext()){System.out.println(iterator.next());}}
}

Set的实现类

Set接口有很多的实现类,下面我们介绍下其常用的实现类: HashSet、TreeSet、LinkedHashSet

HashSet

基本介绍

HashSet是Set接口最常使用的实现类,其底层是通过HashMap实现的。(HashMap可以看这个文章)

源码如下:

    /*** Constructs a new, empty set; the backing <tt>HashMap</tt> instance has* default initial capacity (16) and load factor (0.75).*/public HashSet() {map = new HashMap<>();}

HashMap的底层物理实现是一个Hash表,那这样的话,存入元素的时候,就会根据Hash算法来存储了。即当向HashSet集合中存入一个元素时,HashSet会先判断该对象的hashCode值,然后根据hashCode值决定该对象在HashSet中的存储位置:

  • 如果hashCode值不同,直接把该元素存储到hashCode()指定的位置
  • 如果hashCode 值相同,那么会继续判断该元素和集合对象的equals()作比较。

所以存储到HashSet的元素要重写hashCode和equals方法。

代码示例

package com.atguigu.demo.Set;/*定义一个Employee类,该类包含属性:name, birthday,其中 birthday 为 MyDate类的对象;*/
public class Employee {//自定义属性private String name;private MyDate birthday;//构造器public Employee(String name, MyDate birthday) {super();this.name = name;this.birthday = birthday;}public Employee() {super();}public String getName() {return name;}public void setName(String name) {this.name = name;}public MyDate getBirthday() {return birthday;}public void setBirthday(MyDate birthday) {this.birthday = birthday;}//重写hashCode@Overridepublic int hashCode() {final int prime = 31;int result = 1;result = prime * result + ((birthday == null) ? 0 : birthday.hashCode());result = prime * result + ((name == null) ? 0 : name.hashCode());return result;}//重写equals@Overridepublic boolean equals(Object obj) {if (this == obj)return true;if (obj == null)return false;if (getClass() != obj.getClass())return false;Employee other = (Employee) obj;if (birthday == null) {if (other.birthday != null)return false;} else if (!birthday.equals(other.birthday))return false;if (name == null) {if (other.name != null)return false;} else if (!name.equals(other.name))return false;return true;}@Overridepublic String toString() {return "姓名:" + name + ", 生日:" + birthday;}
}//hashSet测试
import java.util.HashSet;public class TestHashSet {@SuppressWarnings("all")public static void main(String[] args) {HashSet<Employee> set = new HashSet<>(); //创建HashSet集合set.add(new Employee("张三", new MyDate(1990,1,1)));//重复元素无法添加,因为MyDate和Employee重写了hashCode和equals方法set.add(new Employee("张三", new MyDate(1990,1,1)));set.add(new Employee("李四", new MyDate(1992,2,2)));for (Employee object : set) {System.out.println(object);}}
}

LinkedHashSet

基本介绍

LinkedHashSet是HashSet的子类,所以它的很多东西都是继承自HashSet的,这里不再说明,但是相对于HashSet,它在结点中增加两个属性before和after维护了结点的前后添加顺序,这是因为其底层采用了链表+哈希表的结构。

源码如下:

   HashSet(int initialCapacity, float loadFactor, boolean dummy) {map = new LinkedHashMap<>(initialCapacity, loadFactor);}

所以LinkedHashSet可以保证元素的插入顺序。

因为维护了一个链表,存储、查找的性能略低于HashSet,但遍历时性能高于HashSet(根据链表进行遍历)。

代码示例


import java.util.Iterator;
import java.util.LinkedHashSet;public class linkedHashSet {public static void main(String[] args) {//创建LinkedHashSet集合LinkedHashSet<String> set = new LinkedHashSet<>();//添加元素set.add("张三");set.add("李四");set.add("王五");set.add("张三");//元素个数System.out.println("元素个数:" + set.size());//增强for遍历元素for (String name : set) {System.out.println(name);}}
}

TreeSet

基本介绍

与前面两种实现类不同,TreeSet底层是基于红黑树结构实现的,另外TreeSet里的元素是有序的,而实现这个有序的特征,是需要TreeSet里的元素实现排序,其实现排序的形式有两种:自然排序和定制排序。

因为放入其中的元素的类必须实现Comparable接口,所以在元素不能为null。

自然排序

这个默认的排序,让待添加的元素类型实现Comparable接口,并重写compareTo方法(数值型按数值大小排列,字符按码值排列,Date、Time按时间戳的大小排列…默认升序)
对于 TreeSet 集合而言,它判断两个对象是否相等的唯一标准是:两个对象通过 compareTo(Object obj) 方法比较返回值为0。

定制排序

如果自然排序(Comparable)规则不符合我们的排序需求,或者元素的类型没有实现Comparable接口。那么在创建TreeSet时,可以单独指定一个Comparator的对象,根据我们自己的需求进行自定义排序。
使用定制排序判断两个元素相等的标准是:通过Comparator比较两个元素返回了0。

代码示例


public class Student {//自定义属性private int id;private String name;//构造器public Student(int id, String name) {super();this.id = id;this.name = name;}public int getId() {return id;}public void setId(int id) {this.id = id;}//省略了name属性的get/set@Overridepublic String toString() {return "Student [id=" + id + ", name=" + name + "]";}
}import org.junit.Test;import java.util.Comparator;
import java.util.TreeSet;public class TestTreeSet {/*自然顺序按照字符串Unicode编码值排序*/@Testpublic void test1(){//MyDate myDate = new MyDate(1990,1,1);//创建TreeSet集合TreeSet<String> set = new TreeSet<>();//TreeSet<MyDate> set2 = new TreeSet<>();    //ClassCastException:com.atguigu.demo.Set.MyDate cannot be cast to java.lang.Comparable//添加元素set.add("zhangsan");  //String它实现了java.lang.Comparable接口set.add("zisi");set.add("wangwu");set.add("hangsan");//set2.add(myDate);//System.out.println(set2);System.out.println("元素个数:" + set.size());for (String str : set) {System.out.println(str);}}/*定制顺序学生类型未实现Comparable接口,单独指定Comparator比较器,按照学生的学号排序*/@Testpublic void test2(){//创建集合,并指定Comparator的对象TreeSet<Student> set = new TreeSet(new Comparator<Student>(){ //那么在创建TreeSet时,可以单独指定一个Comparator的对象@Overridepublic int compare(Student o1, Student o2) {return o1.getId() - o2.getId();}});//添加学生set.add(new Student(3,"张三"));set.add(new Student(1,"李四"));set.add(new Student(2,"王五"));set.add(new Student(3,"张三风"));//元素个数System.out.println("元素个数:" + set.size());//遍历for (Student stu : set) {System.out.println(stu);}}
}

吃透Java集合中的Set集合必备文章,快快收藏相关推荐

  1. 在Java开发中,判断list集合为空还是为null的区别

    在Java开发中,判断list集合为空还是为null的区别 案例测试1 为什么输出not null,是因为null判断的是否对List集合分配内存空间,为不是List集合里面内容是否为空 案例测试2 ...

  2. 使用Stream流, 获取所有的“张”姓学员和“宋”姓学员, 并把获取到的信息存储到新集合中. 然后遍历集合并打印

    一 编程题[Stream流]* 1.3 题目* 定义main()方法,按以下顺序编写程序:*  定义集合List<String>,添加以下数据:* "宋远桥"* &q ...

  3. java list_java中的list集合

    Java 集合 java集合概览 几幅图让你认识Java集合 java中List.Array.Map.Set等集合相互转换的最佳方法 关于Java集合最被关注的10 个问题 本列表会不断更新 文章 s ...

  4. 遍历List集合中的Map集合:

    首先遍历list集合,在list集合中在遍历map集合. 这里使用到增强for,和Iterator迭代器循环map集合. map集合:有多种遍历方式(百度搜一下),这里由于业务需求使用了迭代器Iter ...

  5. java comparator_Java 中如何指定集合元素的排序策略

    1. 前言 最近用到了集合排序(基于 Java 8).现在我能用 Stream 的就用 Stream ,真香!排序可以这么写: List peoples = new ArrayList<> ...

  6. Java/JSP中调用SQL Server存储过程完整示例收藏

    最近做了个Java的小项目(第一次写Java的项目哦), 到网上搜索了半天,找到了一个比较好点的调用存储过程的例子,而且网上普遍采用的都是setXXX((int parameterIndex, XXX ...

  7. java去重复的集合_如何去除Java中List集合中的重复数据

    1.循环list中的所有元素然后删除重复 public class duplicatRemoval { public static List removeDuplicate(List list){ f ...

  8. java listt add_Java8 使用流抽取ListT集合中T的某个属性操作

    免费资源网 - https://freexyz.cn/ 在java开发中,我们经常会遇到需要从一个集合中,抽取集合中元素的某一个属性.在java8之前,我们通常采用for循环去获取,但java8之后我 ...

  9. JAVA中的Map集合

    JAVA中的Map集合 1.Map简介 java.util.map接口 1.Map称为查找表,该数据结构的样子是一个"多行两列"的表格,左列为key,右列为value,Map总是根 ...

最新文章

  1. 数据中心内虚拟机迁移带来的网络技术难题
  2. UA MATH571A 一元线性回归II 统计推断2
  3. C语言中“数组名”和“数组名”
  4. 四十三、Linux磁盘管理和Shell编程
  5. opencv立方体的画法_最详细的立方体透视变化及画法讲解
  6. 10g添加用户 oracle_oracle 10g中如何创建用户
  7. background使用
  8. 计算机专业考研过关率高么,考研过国家线的几率有多大?被刷的有多少?
  9. 解决win10安卓虚拟机每十几分钟蓝屏重启问题
  10. elisa标准曲线怎么做_Curve Expert软件绘制ELISA标准曲线流程 | 每日生物评论
  11. python绝对值函数fabs_Python中abs()和math.fabs()区别
  12. LeetCode(509)——斐波那契数(JavaScript)
  13. @property 和@synthesize
  14. php数据库图片读取不全,图片显示不出来,但是数据库里有显示
  15. 如何让循环里面语句执行完之后再去循环第二次_Go循环语句的使用
  16. 30岁转行做什么好?我的转行四大步骤!
  17. 阿里内网最新发布“M8”级Java面试笔记,助力金九银十
  18. Android 系统背光设置
  19. w500 安装mac
  20. 【Linux Centos6/7 Oracle11g 修改Oracle字符集为ZHS16GBK(附: 其它字符集查询命令)】

热门文章

  1. 深入理解ES6笔记(九)JS的类(class)
  2. 初识 Spring(02)---(IOC)
  3. VS 远程调试 Azure Web App
  4. spring cloud 教程前言
  5. 转:PHP Liunx 服务安全防范方案
  6. “本地连接”属性中“身份验证”选项卡消失的处理方法
  7. HDU_1253 胜利大逃亡(BFS)
  8. CCS编译出错:缺少头文件的解决办法
  9. Xilinx FPGA的配置
  10. C++中floor,ceil , round , rint用法