关于java里面的集合,大家经常利用到Set集合没有重复数据的特性,来进行数据的去重,那么去重的原理是怎么样的呢?

最近面试了几个人,其间有聊到集合的东西,所以就顺便问了一下这个问题,但是都是只知道这么用,

而没有去看看底层代码的去重原理(而恰恰有可能这些基础原理会被用来设计其他一些场景实现),

所以在此文章记录一下,希望能帮助到一些人:

下面是Set集合的类图:

下面我们来跟踪一下执行的过程:

1. 首先我们实例化一个set对象

Set<8大基本类型> set = new HashSet<8大基本类型>();
set.add(8大基本类型);

2.add操作会调用HashSet中的add方法,实现如下:

public boolean add(E e) {return map.put(e, PRESENT)==null;}

3.HashSet中的add方法依赖了HashMap的put方法,实现如下:

public V put(K key, V value) {if (key == null)return putForNullKey(value);int hash = hash(key.hashCode());int i = indexFor(hash, table.length);for (Entry<K,V> e = table[i]; e != null; e = e.next) {//每添加一个,则循环判断是否与map中的元素相等Object k;// 先判断hashcode是否一致,然后再判断值是否相等if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {V oldValue = e.value;e.value = value;e.recordAccess(this);return oldValue;}}modCount++;addEntry(hash, key, value, i);return null;}

很明显上述操作对8种基本类型的数据+String型是有用的,但是如果想把去重的方式应用到复杂的对象呢,上述方式就还欠缺了一点了,

知道了执行顺序和原理了的话,就知道该如何去实现了!

下面就是重写对象User的实现,重写equals和hashCode方法!

测试类:

package com.test.set;import java.util.HashSet;
import java.util.Set;public class UniqueSet {/*** * @param args*/public static void main(String[] args) {User user1 = new User(1, "a");User user2 = new User(2, "b");User user3 = new User(3, "c");User user4 = new User(2, "b");Set<User> userSet = new HashSet<User>();userSet.add(user1);userSet.add(user2);userSet.add(user3);userSet.add(user4);// 输入结果 id=1 username=a  id=2 username=b  id=3 username=c  for (User u : userSet) {System.out.println("id=" + u.id + " " + "username=" + u.username);}}
}

实现类:

package com.test.set;/*** 类描述:set集合针对String 类型和8大基础数据类型  过滤掉重复数据,* 如果存放的是其他类型对象,则需要重写hashCode方法和equals方法,* 当hashcode相等时(先执行hashCode方法),则会去执行equals方法,比较每个属性的值* 如果一致的话,则不会存进set,否则加入set集合 * */
public class User {// idprotected Integer id;// 名称protected String  username;//构造方法public User(Integer id, String username) {this.id = id;this.username = username;}/** * 如果对象类型是User,先比较hashcode,一致的场合再比较每个属性的值*/@Overridepublic boolean equals(Object obj) {if (obj == null)return false;if (this == obj)return true;if (obj instanceof User) {User user = (User) obj;// if(user.id = this.id) return true; // 只比较id  // 比较每个属性的值 一致时才返回true if (user.id == this.id && user.username.equals(this.username))return true;}return false;}/** * 重写hashcode 方法,返回的hashCode不一样才再去比较每个属性的值*/@Overridepublic int hashCode() {// return id.hashCode();return id.hashCode() * username.hashCode();}
}

以上---------------------

Java Set集合去重机制相关推荐

  1. JAVA中集合去重的三种基本方式

    在学习JAVA的过程中,总是会碰见对集合中的元素进行去重的要求,在这里总结了三种基本的去重方法. 主要的思想就是:先取元素,后进行比较,最后放回去. 案例如下: package eliminate_d ...

  2. java List集合去重保持原顺序

    LinkedHashSet去重,去重后保持原有顺序(重复数据只保留一条) String[] arr = new String[] { "a", "c", &qu ...

  3. Python--几种set集合去重的方法

    1.set集合的去重机制 ps: set集合在内部执行时,首先会先对对象执行hash算法,存储到内存空间, (但在同一次运行过程中两个值相等的对象hash值一样)所以如果两个对象值相等,这时会做出第二 ...

  4. Java List去重 Lis集合去重 List去重效率对比 List去重复元素效率对比 List去重效率

    Java  List去重 Lis集合去重 List去重效率对比 List去重复元素效率对比 List去重效率 --- List 去重复元素的几种办法 一.概述 面试的时候,有个常见的问题:" ...

  5. java中给对象的List集合去重的几种方法(Lambda)

    java中给对象的List集合去重的几种方法 前言 一.lambda表达式的去重方式 二.Stream API中的collect去重方法 三.Stream API 中的distinct方法去重 前言 ...

  6. Java List<T>去重方法,引用类型集合去重

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程. 一.实体类中要重写比较方法equals,最好也重写hashcode方法 public class W ...

  7. 【Java】List集合去重的方式

    List集合去重的方式 方式一:利用TreeSet集合特性排序+去重(有序) 方式二:利用HashSet的特性去重(无序) 方式三:利用LinkedHashSet去重(有序) 方式四:迭代器去重(无序 ...

  8. java 数组合并 去重_Java集合与数组去重

    集合去重 方法一:利用集合的contains方法,创建临时集合组装数据去重 public void listTest1(){ System.out.println("方法一"); ...

  9. Java的List去重

    Java的List去重 1.contains()去重 ArrayList 的 contains() 方法的时间复杂度是O(n)O(n)O(n)的. 使用contains 进行判断去重的 时间复杂度是O ...

最新文章

  1. 腾讯首个AI开源项目完成3.0版本迭代,从顶级开源基金会毕业
  2. 数据库事务及锁机制介绍
  3. BAPI_ACC_GL_POSTING_POST生成财务预制凭证
  4. 【电脑使用经验】怎么查看无线网络中电脑的IP地址?
  5. idea如何安装lombok
  6. C语言%.2f四舍五入
  7. linux打开anaconda的jupyter_Linux Centos7安装anaconda3和jupyter
  8. 2015年9大优秀项目管理工具集锦
  9. 超级记忆/图像数字记忆 110位数字图像转换表 21-30
  10. Android 打包AAB+PAD(java篇)
  11. 53Java模拟器,515最好的java模拟器
  12. Laravel查询构造器的pluck方法第一个参数可选类型array的问题
  13. jzoj5234. 【NOIP2017模拟8.7A组】外星人的路径
  14. Android实现可录音/暂停录音/播放录音的录音软件
  15. Python爬取百度文库并存储为word文档
  16. IDT Source Code Running Guide(Linux+ffmpeg-0.11.1+opencv-2.4.2)
  17. 理解std::move和std::forward
  18. 小米手机、华为手机、一加手机、小米手环NFC刷门禁卡教程!
  19. display:flex 常用
  20. 关闭selinux的两种方法!

热门文章

  1. HP1007打印机死机打印队列出现‘’正在删除错误正在打印”错误
  2. 外贸公司为什么选择海外域名和海外空间?
  3. Python 提取信号的包络
  4. Linux内核中断号映射过程分析(三)
  5. 《Machine Learning in Action》—— 剖析支持向量机,优化SMO
  6. UPS电源怎么控制温度和维护保养
  7. 春暖花开powered by php,折纸龙舟船的详细制作图解
  8. 2022年高教社杯国赛B题--无人机遂行编队飞行中的纯方位无源定位参考代码及思路
  9. 水土不服的轻食,或注定是“一口风”
  10. 创客智造上的《DashgoD1底盘新指南-7.3 虚拟机搭建Dashgo运行环境》的问题解决方法