JAVA零基础小白学习免费教程day14-Set&HashMap
Posted teayear
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA零基础小白学习免费教程day14-Set&HashMap相关的知识,希望对你有一定的参考价值。
day14_JAVAOOP
课程目标
1. 【理解】Set集合的特点
2. 【理解】Set集合不重复的原理
3. 【掌握】HaseSet集合的基本使用
4. 【理解】LinkedHashSet的特点
5. 【理解】Map集合的特点
6. 【掌握】HashMap的使用
7. 【理解】LinkedHashMap的特点
8. 【掌握】Map集合的案例
9. 【掌握】模拟斗地主案例
Set集合
Set集合概述
java.util.Set
接口和java.util.List
接口一样,同样继承自Collection
接口,它与Collection
接口中的方法基本一致,并没有对Collection
接口进行功能上的扩充,只是比Collection
接口更加严格了。与List
接口不同的是,Set
接口中元素无序,并且都会以某种规则保证存入的元素不出现重复。
Set
集合有多个子类,这里我们介绍其中的java.util.HashSet
、java.util.LinkedHashSet
这两个集合。
Set集合的特点
总结: 无序,唯一
HashSet集合
什么是HashSet集合
java.util.HashSet
是Set
接口的一个实现类,它所存储的元素是不可重复的,并且元素都是无序的(即存取顺序不一致)。java.util.HashSet
底层的实现其实是一个java.util.HashMap
支持,由于我们暂时还未学习,先做了解。
HashSet
是根据对象的哈希值来确定元素在集合中的存储位置,因此具有良好的存取和查找性能。保证元素唯一性的方式依赖于:hashCode
与equals
方法。
HashSet集合的特点
HashSet代码演示
/**
Collection
|--List
有序(存储顺序和取出顺序一致),可重复
|--Set
无序(存储顺序和取出顺序不一致),唯一
HashSet:它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。
注意:
虽然Set集合的元素无序,但是,作为集合来说,它肯定有它自己的存储顺序,
而你的顺序恰好和它的存储顺序一致,这代表不了有序,你可以多存储一些数据,就能看到效果。
*/
public class HashSetDemo
public static void main(String[] args)
//创建 Set集合
HashSet<String> set = new HashSet<String>();
//添加元素
set.add(new String("cba"));
set.add("abc");
set.add("bac");
set.add("cba");
//遍历
for (String name : set)
System.out.println(name);
如何保证Hashset集合唯一?
底层依赖 两个方法:hashCode()和equals()。
步骤:
首先比较哈希值
如果相同,继续走,比较地址值或者走equals()
如果不同,就直接添加到集合中
按照方法的步骤来说:
先看hashCode()值是否相同
相同:继续走equals()方法
返回true: 说明元素重复,就不添加
返回false:说明元素不重复,就添加到集合
不同:就直接把元素添加到集合
如果类没有重写这两个方法,默认使用的Object()。一般来说一样。
而String类重写了hashCode()和equals()方法,所以,它就可以把内容相同的字符串去掉。只留下一个。
HashSet存储自定义类型元素
-
定义Student类
public class Student private String name; private int age; public Student() public Student(String name, int age) this.name = name; this.age = age; public String getName() return name; public void setName(String name) this.name = name; public int getAge() return age; public void setAge(int age) this.age = age; @Override public String toString() return "Student" + "name='" + name + '\\'' + ", age=" + age + ''; //不需要你手动重写Object hashCode和equals ,再去测试 @Override public boolean equals(Object o) if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Student student = (Student) o; return age == student.age && Objects.equals(name, student.name); @Override public int hashCode() return Objects.hash(name, age);
-
定义测试类
public class HashSetDemo2 public static void main(String[] args) //创建集合对象 该集合中存储 Student类型对象 HashSet<Student> stuSet = new HashSet<Student>(); //存储 stuSet.add(new Student("于谦", 43)); stuSet.add(new Student("于谦", 43)); stuSet.add(new Student("郭麒麟", 23)); stuSet.add(new Student("郭麒麟", 23)); for (Student stu2 : stuSet) System.out.println(stu2);
-
结果分析
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RTN5ZlPY-1672475567262)(assets/image-20201119201258204.png)]
我们发现有重复的元素,不是Set集合中的元素是不能重复的吗,为什么存储了重复的元素的呢? 下面我们就来分析分析Set集合存储不重复的原理!!!
/*
* 需求:存储自定义对象,并保证元素的唯一性
* 要求:如果两个对象的成员变量值都相同,则为同一个元素。
*
* 目前是不符合我的要求的:因为我们知道HashSet底层依赖的是hashCode()和equals()方法。
* 而这hashCode()和equals()两个方法我们在学生类中没有重写,所以,默认使用的是Object类。
* 这个时候,他们的哈希值是不会一样的,根本就不会继续判断,执行了添加操作。
*/
你使用的是HashSet集合,这个集合的底层是哈希表结构。
而哈希表结构底层依赖:hashCode()和equals()方法。
如果你认为对象的成员变量值相同即为同一个对象的话,你就应该重写这两个方法。
如何重写呢? 不同担心,自动生成即可。
HashSet集合存储数据的结构
什么是哈希表
在JDK1.8之前,哈希表底层采用数组+链表实现,即使用链表处理冲突,同一hash值的链表都存储在一个链表里。但是当位于一个桶中的元素较多,即hash值相等的元素较多时,通过key值依次查找的效率较低。而JDK1.8中,哈希表存储采用数组+链表+红黑树实现,当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找时间。
简单的来说,哈希表是由数组+链表+红黑树(JDK1.8增加了红黑树部分)实现的,如下图所示。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BrUtgqNR-1672475567266)(assets/哈希表.png)]
-
存储流程分析:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XWVL17u8-1672475567267)(assets/哈希流程图.png)]
-
总结
总而言之,JDK1.8引入红黑树大程度优化了HashMap的性能,那么对于我们来讲保证HashSet集合元素的唯一,其实就是根据对象的hashCode和equals方法来决定的。【如果我们往集合中存放自定义的对象,那么保证其唯一,就必须复写hashCode和equals方法建立属于当前对象的比较方式】。
LinkedHashSet
什么是LinkedHashSet
我们知道HashSet保证元素唯一,可是元素存放进去是没有顺序的,那么我们要保证有序,怎么办呢?
在HashSet下面有一个子类java.util.LinkedHashSet
,它是 链表 和 哈希表 组合的一个数据存储结构。
LinkedHashSet集合的特点
代码演示
public class LinkedHashSetDemo
public static void main(String[] args)
Set<String> set = new LinkedHashSet<String>();
set.add("bbb");
set.add("aaa");
set.add("abc");
set.add("bbc");
Iterator<String> it = set.iterator();
while (it.hasNext())
System.out.println(it.next());
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L1M6xkGO-1672475567268)(assets/image-20201119202807088.png)]
TreeSet
使用元素的自然排序对元素进行排序
或者根据创建set时提供的Comparable排序
具体取决于你用的构造方法
TreeSet自然排序
代码实现
public class TreeSetDemo
public static void main(String[] args)
//使用元素的自然顺序对元素进行排序,唯一
TreeSet<Integer> ts = new TreeSet<>();
ts.add(20);
ts.add(18);
ts.add(23);
ts.add(22);
ts.add(17);
ts.add(24);
ts.add(19);
ts.add(18);
ts.add(24);
for(Integer i : ts)
System.out.println(i);
System.out.println("=================");
TreeSet<String> ts2 = new TreeSet<>();
ts2.add("ab");
ts2.add("e");
ts2.add("r");
ts2.add("y");
ts2.add("c");
ts2.add("ac");
for(String s : ts2)
System.out.println(s);
TreeSet存储自定义对象
public class Demo
public static void main(String[] args)
// 创建集合对象
TreeSet<Student> ts = new TreeSet<Student>();
Student s1 = new Student("b",23);
Student s2 = new Student("a",23);
Student s3 = new Student("jack",27);
ts.add(s1);
ts.add(s2);
ts.add(s3);
for(Student s : ts)
System.out.println(s.getName()+"--"+s.getAge());
/**
* @Auther: yanqi
* @Date: 14:40
* @Desc 如果一个类的元素要想进行自然排序,就必须实现自然排序的接口
Comparable 可以看成是内部比较器,需要修改原有代码,不符合OCP原则
*/
public class Student implements Comparable<Student>
private String name;
private int age;
public Student()
public Student(String name, int age)
this.name = name;
this.age = age;
public String getName()
return name;
public void setName(String name)
this.name = name;
public int getAge()
return age;
public void setAge(int age)
this.age = age;
@Override
public String toString()
return "Student" +
"name='" + name + '\\'' +
", age=" + age +
'';
@Override
public int compareTo(Student s)
//按照年龄排序 ,主要条件
int num = this.age - s.age;//年龄相同就不存储
int num2 = num == 0 ? this.name.compareTo(s.name) : num ;//年龄相同的的时同,比较一下名是否相同
return num2;
比较器排序
Comparator 可以看成一个外部比较器,好处不用修改原代码直接实现
代码实现
package cn.yanqi_02;
import cn.yanqi_01.Student;
import cn.yanqi_02.MyComparator;
import java.util.TreeSet;
/*
* 需求:请按照姓名的长度排序
*
* TreeSet集合保证元素排序和唯一性的原理
* 唯一性:是根据比较的返回是否是0来决定。
* 排序:
* A:自然排序(元素具备比较性)
* 让元素所属的类实现自然排序接口 Comparable
* B:比较器排序(集合具备比较性)
* 让集合的构造方法接收一个比较器接口的子类对象 Comparator
*/
public class Demo
public static void main(String[] args)
// 创建集合对象
// TreeSet<Student> ts = new TreeSet<Student>(); //自然排序
// public TreeSet(Comparator comparator) //比较器排序
TreeSet<Student> ts = new TreeSet<Student>(new MyComparator());
// 创建元素
Student s1 = new Student("linqingxia", 27);
Student s2 = new Student("zhangguorong", 29);
Student s3 = new Student("wanglihong", 23);
Student s4 = new Student("linqingxia", 27);
Student s5 = new Student("liushishi", 22);
Student s6 = new Student("wuqilong", 40);
Student s7 = new Student("fengqingy", 22);
Student s8 = new Student("linqingxia", 29);
// 添加元素
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);
ts.add(s6);
ts.add(s7);
ts.add(s8);
// 遍历
for (Student s : ts)
System.out.println(s.getName() + "---" + s.getAge());
public class Student
private String name;
private int age;
public Student()
public Student(String name, int age)
this.name = name;
this.age = age;
public String getName()
return name;
public void setName(String name)
this.name = name;
public int getAge()
return age;
public void setAge(int age)
this.age = age;
@Override
public String toString()
return "Student" +
"name='" + name + '\\'' +
", age=" + age +
'';
public class MyComparator implements Comparator<Student>
@Override
public int compare(Student s1, Student s2)
// int num = this.name.length() - s.name.length();
// this -- s1
// s -- s2
// 姓名长度
int num = s1.getName().length() - s2.getName().length();
// 姓名内容
int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;
// 年龄
int num3 = num2 == 0 ? s1.getAge() - s2.getAge() : num2;
return num3;
Comparable<T> 内部比较器,需要修改原代码,不符合OCP原则
重写方法: public int compareTo(T t)
Comparator 可以看成一个外部比较器,好处不用修改原代码直接实现
重写方法: public int compare(Ojbect s1, Ojbect s2)
返回值类型:int 等于0 表示相等 大于0表示升序 小于0表示是降序
Map集合
什么是Map集合
现实生活中,我们常会看到这样的一种集合:IP地址与主机名,身份证号与个人,系统用户名与系统用户对象等&
以上是关于JAVA零基础小白学习免费教程day14-Set&HashMap的主要内容,如果未能解决你的问题,请参考以下文章
JAVA零基础小白学习免费教程day13-Collection&数据结构