本博客地址 | GitHub | 更多资源免费下载
小伙伴们,大家早上好!今天我给大家带来Java集合框架Collection之Set集合讲解,今天主要讲解Set集合接口下的实现类HashSet集合,今天的讲解重要,请大家仔细看噢!
前面我们已经学过了List集合(不熟悉List集合的小伙伴点击:Java进阶-Java学习路线课程第一课:Java集合框架-ArrayList和LinkedList的使用),相信大家对List集合有所了解了吧!List集合是有索引,有序和不唯一,那Set集合有什么特征呢?当然有它的特征,没有索引,无序和唯一。下面我们来一一讲讲,当然,重点会讲一下HashSet去重。
特征(单列集合): 不唯一,无序
特征(单列集合): 不唯一,有序
特征(单列集合): 唯一,无序
特征(双列集合): 键值对
key --->value map.put("userName",uName);
key是拿的Set的特性,而value是拿的Collection的特性。
特征:底层由哈希表(实际上是一个 HashMap
实例)支持。它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用 null 元素。无索引,唯一,无序。最大的优势就是去重。
News.java 实例类
package com.javaxyz.entity;
/**
* @ClassName:News.java
* @Description:新闻实例类
* @Author:DongGaoYun
* @AuthorEnglishName:Andy
* @URL:www.javaxyz.com 或 www.gyun.org
* @Email:[email protected]
* @QQ:1050968899
* @WeiXin:QingYunJiao
* @WeiXinGongZhongHao: JavaForum
* @Date:2019-10-22 下午2:23:38
* @Version:1.0 完成以下基本代码: 1.属性 2.get和set方法 3.构造方法 4.toString
* 说明
1.这个新闻实例类没有重写equals和hashCode方法
2.没有用泛型,后面章节会介绍
*/
public class News {
//属性
private int id;
private String title;//标题
private String author;//作者
/**
* @return the id
*/
public int getId() {
return id;
}
/**
* @param id
* the id to set
*/
public void setId(int id) {
this.id = id;
}
/**
* @return the title
*/
public String getTitle() {
return title;
}
/**
* @param title
* the title to set
*/
public void setTitle(String title) {
this.title = title;
}
/**
* @return the author
*/
public String getAuthor() {
return author;
}
/**
* @param author
* the author to set
*/
public void setAuthor(String author) {
this.author = author;
}
// toString
@Override
public String toString() {
return "News [id=" + id + "," + " title=" + title + "," + " author="
+ author + "]\n";
}
/**
* 无参构造方法
*/
public News() {
}
/**
* 有参构造方法
* @param id
* @param title
* @param author
*/
public News(int id, String title, String author) {
super();
this.id = id;
this.title = title;
this.author = author;
}
}
package com.javaxyz.test;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.junit.Test;
import com.javaxyz.equals.News;
/**
* @ClassName:HashSetDemo.java
* @Description:Set的运用
* @Author:DongGaoYun
* @AuthorEnglishName:Andy
* @URL:www.javaxyz.com 或 www.gyun.org
* @Email:[email protected]
* @QQ:1050968899
* @WeiXin:QingYunJiao
* @WeiXinGongZhongHao: JavaForum
* @Date:2019-10-25
* @Version:1.0 HashSet 优势: 去重 特有功能:
*
*/
public class HashSetDemo1 {
// 需求:
// 增加新闻元素
// 获取新闻总数
// 操作HashSet容器,移除元素
// 判断是否包含此元素
// 打印输出四种方式
//忽略警告
@SuppressWarnings("all")
// public static void main(String[] args) {
@Test
public void testSet() {
// 创建对象
// 创建多态的形式,要注意的点:只能调用父类与子类重写的方法,子类特有方法无法调用
Set list = new HashSet();// 多态的形式。//1.父子关系 2.重写方法 3.父类的引用指向子类对象
News news1 = new News(1, "张卓1", "green1");
News news2 = new News(2, "张卓2", "green2");
News news11 = new News(2, "张卓2", "green2");
News news3 = new News(3, "张卓3", "green3");
News news4 = new News(4, "张卓4", "green4");
News news5 = new News(5, "张卓5", "green5");
News news6 = new News(6, "张卓6", "green6");
News news7 = new News(7, "张卓7", "green7");
News news8 = new News(8, "张卓8", "green8");
// 插入数据
list.add(news1);
list.add(news2);
list.add(news3);
// 注意set是无序的,没有索引,所以报错
// list.add(1,news4);
// 插入数据
list.add(news6);
list.add(news11);
// 总条数
System.out.println(list.size());
// 操作HashSet容器,移除元素
/*
* list.remove(0); list.remove(news1);
*/
// 判断是否包含此元素
System.out.println(list.contains(news7));
// list
System.out.println("-------第一种打印输出方法---start----");
System.out.print(list);
System.out.println("-------第一种打印输出方法---end----");
System.out.println();
//System.out.println("-------第二种打印输出方法-普通for--start----");
// 普通for不能用
/*
* for (int i = 0; i < list.size(); i++) { News newss = (News)
* list.get(i); System.out.println("News [id=" + newss.getId() + "," +
* " title=" + newss.getTitle() + "," + " author=" + newss.getAuthor() +
* "]"); }
*/
//System.out.println("-------第二种打印输出方法---end----");
System.out.println();
System.out.println("-------第二种打印输出方法-增强for--start----");
for (Object object : list) {
News newss = (News) object;
System.out.println("News [id=" + newss.getId() + "," + " title="
+ newss.getTitle() + "," + " author=" + newss.getAuthor()
+ "]");
}
System.out.println("-------第二种打印输出方法---end----");
System.out.println();
System.out.println("-------第三种打印输出方法-转换成数组--start----");
/**
* toArray Object[] toArray() 返回包含此 collection 中所有元素的数组。如果 collection
* 对其迭代器返回的元素顺序做出了某些保证,那么此方法必须以相同的顺序返回这些元素。 返回的数组将是“安全的”,因为此 collection
* 并不维护对返回数组的任何引用。(换句话说,即使 collection
* 受到数组的支持,此方法也必须分配一个新的数组)。因此,调用者可以随意修改返回的数组。
*
* 此方法充当了基于数组的 API 与基于 collection 的 API 之间的桥梁。
*
* 返回: 包含此 collection 中所有元素的数组
*/
Object[] obj = list.toArray();
for (Object object : obj) {
News newss = (News) object;
System.out.println("News [id=" + newss.getId() + "," + " title="
+ newss.getTitle() + "," + " author=" + newss.getAuthor()
+ "]");
}
System.out.println("-------第三种打印输出方法---end----");
System.out.println();
System.out.println("-------第四种打印输出方法-迭代方式--start----");
/**
* iterator Iterator iterator()
*
* boolean hasNext() 如果仍有元素可以迭代,则返回 true。
*
* E next() 返回迭代的下一个元素。
*
* void remove() 从迭代器指向的 collection 中移除迭代器返回的最后一个元素(可选操作)。
*/
Iterator it = list.iterator();
while (it.hasNext()) {
News newss = (News) it.next();
System.out.println("News [id=" + newss.getId() + "," + " title="
+ newss.getTitle() + "," + " author=" + newss.getAuthor()
+ "]");
}
System.out.println("-------第四种打印输出方法---end----");
}
}
5
false
-------第一种打印输出方法---start----
[News [id=1, title=张卓1, author=green1]
, News [id=2, title=张卓2, author=green2]
, News [id=3, title=张卓3, author=green3]
, News [id=2, title=张卓2, author=green2]
, News [id=6, title=张卓6, author=green6]
]-------第一种打印输出方法---end----
-------第二种打印输出方法-增强for--start----
News [id=1, title=张卓1, author=green1]
News [id=2, title=张卓2, author=green2]
News [id=3, title=张卓3, author=green3]
News [id=2, title=张卓2, author=green2]
News [id=6, title=张卓6, author=green6]
-------第二种打印输出方法---end----
-------第三种打印输出方法-转换成数组--start----
News [id=1, title=张卓1, author=green1]
News [id=2, title=张卓2, author=green2]
News [id=3, title=张卓3, author=green3]
News [id=2, title=张卓2, author=green2]
News [id=6, title=张卓6, author=green6]
-------第三种打印输出方法---end----
-------第四种打印输出方法-迭代方式--start----
News [id=1, title=张卓1, author=green1]
News [id=2, title=张卓2, author=green2]
News [id=3, title=张卓3, author=green3]
News [id=2, title=张卓2, author=green2]
News [id=6, title=张卓6, author=green6]
-------第四种打印输出方法---end----
public class HashSetDemo2_String {
// 需求:
// 增加新闻元素
// 获取新闻总数
// String类,如果在HashSet容器增加元素,如果增加的元素是相同的,就会去重。
@SuppressWarnings("all")
// public static void main(String[] args) {
@Test
public void testSet() {
// 创建对象
// 创建多态的形式,要注意的点:只能调用父类与子类重写的方法,子类特有方法无法调用
// Set list=new HashSet();//多态的形式。//1.父子关系 2.重写方法 3.父类的引用指向子类对象
HashSet list = new HashSet();
String s1 = new String("abc");
String s2 = new String("abc");
String s3 = new String("abc");
// 增加元素
list.add(s1);
// 注意:当向set集合中存储相同元素时,add(obj)方法返回的是false.
list.add(s2);
list.add(s3);
// 获取元素总数
System.out.println(list.size());
System.out.println();
//打印输出
System.out.println(list);
}
}
1
[abc]
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String) anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
HashSet list = new HashSet();
String s1 = new String("gdejicbegh");
String s2 = new String("hgebcijedg");
System.out.println(s1.hashCode()==s2.hashCode());
System.out.println(s1.hashCode());
System.out.println(s2.hashCode());
true
-801038016
-801038016
package com.javaxyz.equals;
/**
* @ClassName:News.java
* @Description:描述信息
* @Author:DongGaoYun
* @AuthorEnglishName:Andy
* @URL:www.javaxyz.com 或 www.gyun.org
* @Email:[email protected]
* @QQ:1050968899
* @WeiXin:QingYunJiao
* @WeiXinGongZhongHao: JavaForum
* @Date:2019-10-22 下午2:23:38
* @Version:1.0
* 完成以下基本代码: 1.属性 2.get和set方法 3.构造方法 4.toString
* 重写Object的两个方法
* 1.hashCode方法
* 2.equals方法
* Set集合即可去重。
*
*/
public class News {
// 属性
private int id;
private String title;// 标题
private String author;// 作者
/**
* @return the id
*/
public int getId() {
return id;
}
/**
* @param id
* the id to set
*/
public void setId(int id) {
this.id = id;
}
/**
* @return the title
*/
public String getTitle() {
return title;
}
/**
* @param title
* the title to set
*/
public void setTitle(String title) {
this.title = title;
}
/**
* @return the author
*/
public String getAuthor() {
return author;
}
/**
* @param author
* the author to set
*/
public void setAuthor(String author) {
this.author = author;
}
// toString
@Override
public String toString() {
return "News [id=" + id + "," + " title=" + title + "," + " author="
+ author + "]\n";
}
/**
* 无参构造方法
*/
public News() {
}
/**
* 有参构造方法
*
* @param id
* @param title
* @param author
*/
public News(int id, String title, String author) {
super();
this.id = id;
this.title = title;
this.author = author;
}
/*
* 为什么把prime变量值初始化为31,有以下几个原因:更多免费资料请加微信公众号:javaforum
* 1.31这个数字不大也不太小
* 2.31是一个奇数,也是一个质数,即只能被1和本身整除的数。
* 3.如果选择偶数,乘2相当于移位运算可能导致溢出,数据会丢失
* 4.31有个很好的特性,就是用移位和减法来代替乘法,可以得到更好的性能:31*i==(i<<5)-i。现在的JVM可以自动完成这种优化。 *
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((author == null) ? 0 : author.hashCode());
result = prime * result + id;
result = prime * result + ((title == null) ? 0 : title.hashCode());
System.out.println("执行的hashCode是:"+result);
return result;
}
/*
* 在我的博文中已经讲过: Java入门-Java学习路线扩展课程:equals的使用 更多免费资料请加微信公众号:javaforum
*/
@Override
public boolean equals(Object obj) {
//提升效率 判断传入的对象与本对象是否是同一个对象
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())//比较两个对象的字节码文件是否是同一个字节码
return false;
News other = (News) obj;//向下转型
if (author == null) {
if (other.author != null)
return false;
} else if (!author.equals(other.author))
return false;
if (id != other.id)
return false;
if (title == null) {
if (other.title != null)
return false;
} else if (!title.equals(other.title))
return false;
return true;
}
}
package com.javaxyz.test;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.junit.Test;
import com.javaxyz.equals.News;
/**
* @ClassName:HashSetDemo.java
* @Description:Set的运用
* @Author:DongGaoYun
* @AuthorEnglishName:Andy
* @URL:www.javaxyz.com 或 www.gyun.org
* @Email:[email protected]
* @QQ:1050968899
* @WeiXin:QingYunJiao
* @WeiXinGongZhongHao: JavaForum
* @Date:2019-10-25
* @Version:1.0 HashSet 优势: 去重 特有功能:
*
*/
public class HashSetDemo1 {
// 需求:
// 增加新闻元素
// 获取新闻总数
// 操作HashSet容器,移除元素
// 判断是否包含此元素
// 打印输出四种方式
// String类,如果在HashSet容器增加元素,如果增加的元素是相同的,就会去重。
@SuppressWarnings("all")
// public static void main(String[] args) {
@Test
public void testSet() {
// 创建对象
// 创建多态的形式,要注意的点:只能调用父类与子类重写的方法,子类特有方法无法调用
Set list = new HashSet();// 多态的形式。//1.父子关系 2.重写方法 3.父类的引用指向子类对象
String s1 = new String("gdejicbegh");
String s2 = new String("hgebcijedg");
System.out.println(s1.hashCode()==s2.hashCode());
System.out.println(s1.hashCode());
System.out.println(s2.hashCode());
// list.add(s1);
// list.add(s2);
//System.out.println(list.size());
News news1 = new News(1, "张卓1", "green1");
News news2 = new News(2, "张卓2", "green2");
News news11 = new News(2, "张卓2", "green2");
News news3 = new News(3, "张卓3", "green3");
News news4 = new News(4, "张卓4", "green4");
News news5 = new News(5, "张卓5", "green5");
News news6 = new News(6, "张卓6", "green6");
News news7 = new News(7, "张卓7", "green7");
News news8 = new News(8, "张卓8", "green8");
// 插入数据
list.add(news1);
list.add(news2);
list.add(news3);
// 注意set是无序的,没有索引,所以报错 更多免费资料请加微信公众号:javaforum
// list.add(1,news4);
// 插入数据
list.add(news6);
//注意:自定义对象重写equals和hashCode方法后,如果是重复元素,这时就会返回false
System.out.println(list.add(news11));
// 总条数
System.out.println(list.size());
// 操作HashSet容器,移除元素
/*
* list.remove(0); list.remove(news1);
*/
// 判断是否包含此元素
System.out.println(list.contains(news7));
// list
System.out.println("-------第一种打印输出方法---start----");
System.out.print(list);
System.out.println("-------第一种打印输出方法---end----");
System.out.println();
//System.out.println("-------第二种打印输出方法-普通for--start----");
// 普通for不能用
/*
* for (int i = 0; i < list.size(); i++) { News newss = (News)
* list.get(i); System.out.println("News [id=" + newss.getId() + "," +
* " title=" + newss.getTitle() + "," + " author=" + newss.getAuthor() +
* "]"); }
*/
//System.out.println("-------第二种打印输出方法---end----");
System.out.println();
System.out.println("-------第二种打印输出方法-增强for--start----");
for (Object object : list) {
News newss = (News) object;
System.out.println("News [id=" + newss.getId() + "," + " title="
+ newss.getTitle() + "," + " author=" + newss.getAuthor()
+ "]");
}
System.out.println("-------第二种打印输出方法---end----");
System.out.println();
System.out.println("-------第三种打印输出方法-转换成数组--start----");
/**
* toArray Object[] toArray() 返回包含此 collection 中所有元素的数组。如果 collection
* 对其迭代器返回的元素顺序做出了某些保证,那么此方法必须以相同的顺序返回这些元素。 返回的数组将是“安全的”,因为此 collection
* 并不维护对返回数组的任何引用。(换句话说,即使 collection
* 受到数组的支持,此方法也必须分配一个新的数组)。因此,调用者可以随意修改返回的数组。
*
* 此方法充当了基于数组的 API 与基于 collection 的 API 之间的桥梁。
*
* 返回: 包含此 collection 中所有元素的数组 更多免费资料请加微信公众号:javaforum
*/
Object[] obj = list.toArray();
for (Object object : obj) {
News newss = (News) object;
System.out.println("News [id=" + newss.getId() + "," + " title="
+ newss.getTitle() + "," + " author=" + newss.getAuthor()
+ "]");
}
System.out.println("-------第三种打印输出方法---end----");
System.out.println();
System.out.println("-------第四种打印输出方法-迭代方式--start----");
/**
* iterator Iterator iterator()
*
* boolean hasNext() 如果仍有元素可以迭代,则返回 true。
*
* E next() 返回迭代的下一个元素。 更多免费资料请加微信公众号:javaforum
*
* void remove() 从迭代器指向的 collection 中移除迭代器返回的最后一个元素(可选操作)。
*/
Iterator it = list.iterator();
while (it.hasNext()) {
News newss = (News) it.next();
System.out.println("News [id=" + newss.getId() + "," + " title="
+ newss.getTitle() + "," + " author=" + newss.getAuthor()
+ "]");
}
System.out.println("-------第四种打印输出方法---end----");
}
}
true
-801038016
-801038016
false
4
false
-------第一种打印输出方法---start----
[News [id=1, title=张卓1, author=green1]
, News [id=2, title=张卓2, author=green2]
, News [id=6, title=张卓6, author=green6]
, News [id=3, title=张卓3, author=green3]
]-------第一种打印输出方法---end----
-------第二种打印输出方法-增强for--start----
News [id=1, title=张卓1, author=green1]
News [id=2, title=张卓2, author=green2]
News [id=6, title=张卓6, author=green6]
News [id=3, title=张卓3, author=green3]
-------第二种打印输出方法---end----
-------第三种打印输出方法-转换成数组--start----
News [id=1, title=张卓1, author=green1]
News [id=2, title=张卓2, author=green2]
News [id=6, title=张卓6, author=green6]
News [id=3, title=张卓3, author=green3]
-------第三种打印输出方法---end----
-------第四种打印输出方法-迭代方式--start----
News [id=1, title=张卓1, author=green1]
News [id=2, title=张卓2, author=green2]
News [id=6, title=张卓6, author=green6]
News [id=3, title=张卓3, author=green3]
-------第四种打印输出方法---end----
16、由此可见,要想将自定义类的对象存入HashSet集合里去重,需要注意以下三点:
更多免费资源请关注微信公众号: