首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

Java进阶-Java学习路线课程第二课:Java集合框架-HashSet的使用及去重原理

  • 25-02-21 23:22
  • 2182
  • 8917
blog.csdn.net

本博客地址 | GitHub | 更多资源免费下载

        小伙伴们,大家早上好!今天我给大家带来Java集合框架Collection之Set集合讲解,今天主要讲解Set集合接口下的实现类HashSet集合,今天的讲解重要,请大家仔细看噢!

Java集合框架-HashSet的使用及去重原理

     前面我们已经学过了List集合(不熟悉List集合的小伙伴点击:Java进阶-Java学习路线课程第一课:Java集合框架-ArrayList和LinkedList的使用),相信大家对List集合有所了解了吧!List集合是有索引,有序和不唯一,那Set集合有什么特征呢?当然有它的特征,没有索引,无序和唯一。下面我们来一一讲讲,当然,重点会讲一下HashSet去重。

文章目录

          • 1、首先,还是让大家看看一个简洁的Java集合框架结构体系图:
          • 2、看看这些接口和类有什么特征。
          • 3、先给大家演示一下HashSet去重代码,能做到去重吗?代码如下:
          • 4、测试代码:
          • 5、输出结果:
          • 6、从上面的打印中可以看出:
          • 7、输出结果:
          • 8、很显然,java系统类在向Set或HashSet集合里增加元素时,已经完美的去重了。那我们就看看String类里重写了哪些方法,我们来借鉴一下!惊奇的发现了String重写Object超类中的两个方法:一个是equals方法(前面介绍过:[Java入门-Java学习路线扩展课程:equals的使用](http://iyenn.com/rec/1674755.html)),另一个是hashCode方法。源码如下:
          • 9、原来如此,String类用属性value值作为底层数据来计算hashCode的,即相同的value就一定会有相同的哈希值。如果value值相同,那么调用equals方法比较也是相等的;反过来不一定成立。它不保证相同的哈希值一定就是相同的对象。
          • 10、在Java中,String类有个别对象的属性值不同,但是哈希值相同,比如字符串"gdejicbegh"与字符串"hgebcijedg"具有相同的哈希值-801038016。代码如下:
          • 11、输出结果:
          • 12、结论如下:
          • 13、小伙伴们是不是有种豁然开朗的感觉?我们来改造一下News.java类,改造代码如下:
          • 14、测试代码:
          • 15、输出结果:
          • 17、HashSet去重原理:
            • 17.1、使用HashSet集合调用add()方法存储对象之前,应该注意尽量使重写的hashCode()方法返回的值不同,减少调用equals方法,提升性能;在调用add方法时,系统会先调用对象的hashCode()方法得到一个哈希值, 然后在HashSet集合中比较是否有哈希值相同的对象
        •        小伙伴们,本章已经结束,你们都懂了吗?我花了四个小时的时间编写,记得关注、点赞、分享和关注微信公众号(javaforum)噢!有疑问或好的建议请与我联系噢!持续更新!敬请关注!

1、首先,还是让大家看看一个简洁的Java集合框架结构体系图:
2、看看这些接口和类有什么特征。
  • Collection(接口)

特征(单列集合): 不唯一,无序

  • List(子接口)

特征(单列集合): 不唯一,有序

  • Set(子接口)

特征(单列集合): 唯一,无序

  • Map(接口)

特征(双列集合): 键值对

key --->value  map.put("userName",uName);
key是拿的Set的特性,而value是拿的Collection的特性。
  • 1
  • 2
  • HashSet

特征:底层由哈希表(实际上是一个 HashMap 实例)支持。它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用 null 元素。无索引,唯一,无序。最大的优势就是去重。

3、先给大家演示一下HashSet去重代码,能做到去重吗?代码如下:
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;
	}

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
4、测试代码:
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----");
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
5、输出结果:
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----
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
6、从上面的打印中可以看出:
  • Set的输出是无序的;
  • Set虽然说具有去重的功能,但是自定义对象增加到Set集合或HashSet集合中,还是有重复的对象,怎么办呢?有什么玄机呢?为什么没有去重呢?我们还是看看java的系统类String,我们在String类中把相同的对象增加进去会去重吗?我们来试试。具体代码如下:
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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
7、输出结果:
1

[abc]

  • 1
  • 2
  • 3
  • 4
8、很显然,java系统类在向Set或HashSet集合里增加元素时,已经完美的去重了。那我们就看看String类里重写了哪些方法,我们来借鉴一下!惊奇的发现了String重写Object超类中的两个方法:一个是equals方法(前面介绍过:Java入门-Java学习路线扩展课程:equals的使用),另一个是hashCode方法。源码如下:
  • 重写equals方法
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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 重写hashCode方法

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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
9、原来如此,String类用属性value值作为底层数据来计算hashCode的,即相同的value就一定会有相同的哈希值。如果value值相同,那么调用equals方法比较也是相等的;反过来不一定成立。它不保证相同的哈希值一定就是相同的对象。
10、在Java中,String类有个别对象的属性值不同,但是哈希值相同,比如字符串"gdejicbegh"与字符串"hgebcijedg"具有相同的哈希值-801038016。代码如下:
		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());
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
11、输出结果:
true
-801038016
-801038016
  • 1
  • 2
  • 3
12、结论如下:
  • 如果equals比较后相等,则hashCode一定会相等。   更多免费资料请加微信公众号:javaforum
  • 如果hashCode的哈希值相等,equals就不一定相等,注意:它不保证相同的哈希值一定就是相同的对象。
13、小伙伴们是不是有种豁然开朗的感觉?我们来改造一下News.java类,改造代码如下:
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;
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
14、测试代码:
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----");
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
15、输出结果:
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----

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

16、由此可见,要想将自定义类的对象存入HashSet集合里去重,需要注意以下三点:

  • 自定义类中必须同时重写equals()和hashCode()方法
  • hashCode(): 属性值相同的对象返回值必须相同, 属性值不同的返回值尽量不同(提高效率)
  • equals(): 属性值相同返回true, 属性值不同返回false,返回false的时候存储
17、HashSet去重原理:
17.1、使用HashSet集合调用add()方法存储对象之前,应该注意尽量使重写的hashCode()方法返回的值不同,减少调用equals方法,提升性能;在调用add方法时,系统会先调用对象的hashCode()方法得到一个哈希值, 然后在HashSet集合中比较是否有哈希值相同的对象
  • 如果没有哈希值相同的对象就会直接存入HashSet集合
  • 如果有哈希值相同的对象, 就和哈希值相同的对象逐个调用equals()方法进行比较,结果为false就直接存入, 为true则不存
       小伙伴们,本章已经结束,你们都懂了吗?我花了四个小时的时间编写,记得关注、点赞、分享和关注微信公众号(javaforum)噢!有疑问或好的建议请与我联系噢!持续更新!敬请关注!

———— 精 选 文 章 ————
  1. Java入门-Java学习路线课程第一课:初识JAVA
  2. Java入门-Java学习路线课程第二课:变量与数据类型
  3. Java入门-Java学习路线课程第三课:选择结构
  4. Java入门-Java学习路线课程第四课:循环结构
  5. Java入门-Java学习路线课程第五课:一维数组
  6. Java入门-Java学习路线课程第六课:二维数组
  7. Java入门-Java学习路线课程第七课:类和对象
  8. Java入门-Java学习路线课程第八课:方法和方法重载
  9. Java入门-Java学习路线扩展课程:equals的使用
  10. Java入门-Java学习路线课程面试篇:取商 / 和取余(模) % 符号的使用
  11. Java进阶-Java学习路线课程第一课:Java集合框架-ArrayList和LinkedList的使用
  12. Spring框架-Java学习路线课程第一课:Spring核心
  13. Spring框架-Java学习路线课程:Spring的扩展配置
  14. Springboot框架-Java学习路线课程:Springboot框架的搭建之maven的配置
  15. java学习:在给学生演示用Myeclipse10.7.1工具生成War时,意外报错:SECURITY: INTEGRITY CHECK ERROR
  16. 使用jquery发送Ajax请求的几种异步刷新方式
  17. idea Springboot启动时内嵌tomcat报错- An incompatible version [1.1.33] of the APR based Apache Tomcat Native
  18. 一个简单的SSM框架Demo(登录(包含拦截器)和注销

更多免费资源请关注微信公众号:

文章知识点与官方知识档案匹配,可进一步学习相关知识
Java技能树集合Set接口150366 人正在系统学习中
注:本文转载自blog.csdn.net的青云交的文章"https://blog.csdn.net/atgfg/article/details/102774785"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2491) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top