精华内容
下载资源
问答
  • HashSet

    2019-03-14 19:53:29
    与HashMap相同,...HashSet的应用场景: 1、 排重 2、 保存特殊值,比如保存用户黑白名单,来判断用户是否有某权限 3、集合运算,,set可以方便的进行交集,并集等运算 HashSet的内部实现 HashSet内部是用一个...

    与HashMap相同,HashSet也要求元素重写hashCode和equals方法,且对于两个对象如果equals相同,则hashCode也必须相同,如果元素是自定义类,需要注意这一点。
    HashSet的应用场景:
    1、 排重
    2、 保存特殊值,比如保存用户黑白名单,来判断用户是否有某权限
    3、集合运算,,set可以方便的进行交集,并集等运算

    HashSet的内部实现

    HashSet内部是用一个HashMap实现的:

        private transient HashMap<E,Object> map;
    

    HashSet相当于只有键,值都是相同的值:

        // Dummy value to associate with an Object in the backing Map
        private static final Object PRESENT = new Object();
    

    基于这个内部组成,他的实现就很好懂了:

        public HashSet(int initialCapacity, float loadFactor) {
            map = new HashMap<>(initialCapacity, loadFactor);
        }
    
        public HashSet(Collection<? extends E> c) {
            map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
            addAll(c);
        }
    

    c.size()/.75f 用来计算loadFactor的默认值;

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

    add方法就是直接调用map的put方法;

        public boolean contains(Object o) {
            return map.containsKey(o);
        }
    
    

    contains就是直接调用map的containsKey方法

        public boolean remove(Object o) {
            return map.remove(o)==PRESENT;
        }
    
        public Iterator<E> iterator() {
            return map.keySet().iterator();
        }
    
    

    remove和iterator方法也是直接是用的map的方法,简单的超乎想象。

    特点小结:
    1、 没有重复元素
    2、可以高效的添加、删除元素、判断元素是否存在,效率为O(1)
    3、 没有顺序
    如果要保持添加的顺序,可以是用HashSet的子类:LinkedHashSet。Set还有一个重要的实现类TreeSet,他可以进行排序。

    展开全文
  • 1.HashSet和HashMap在高并发场景下也会报java.util.ConcurrentModificationException异常 2.解决办法: Set s= new CopyOnWriteArraySet<>(); private final CopyOnWriteArrayList<E> al; /** * ...

    1.HashSet和HashMap在高并发场景下也会报java.util.ConcurrentModificationException异常
    2.解决办法:
    Set s= new CopyOnWriteArraySet<>();

        private final CopyOnWriteArrayList<E> al;
    
        /**
         * Creates an empty set.
         */
        public CopyOnWriteArraySet() {
            al = new CopyOnWriteArrayList<E>();
        }
    

    Map m= new ConcurrentHashMap<>();
    底层用到了Unsafe类的CAS操作

     /**
         * Maps the specified key to the specified value in this table.
         * Neither the key nor the value can be null.
         *
         * <p>The value can be retrieved by calling the {@code get} method
         * with a key that is equal to the original key.
         *
         * @param key key with which the specified value is to be associated
         * @param value value to be associated with the specified key
         * @return the previous value associated with {@code key}, or
         *         {@code null} if there was no mapping for {@code key}
         * @throws NullPointerException if the specified key or value is null
         */
        public V put(K key, V value) {
            return putVal(key, value, false);
        }
    
        /** Implementation for put and putIfAbsent */
        final V putVal(K key, V value, boolean onlyIfAbsent) {
            if (key == null || value == null) throw new NullPointerException();
            int hash = spread(key.hashCode());
            int binCount = 0;
            for (Node<K,V>[] tab = table;;) {
                Node<K,V> f; int n, i, fh;
                if (tab == null || (n = tab.length) == 0)
                    tab = initTable();
                else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
                    if (casTabAt(tab, i, null,
                                 new Node<K,V>(hash, key, value, null)))
                        break;                   // no lock when adding to empty bin
                }
                else if ((fh = f.hash) == MOVED)
                    tab = helpTransfer(tab, f);
                else {
                    V oldVal = null;
                    synchronized (f) {
                        if (tabAt(tab, i) == f) {
                            if (fh >= 0) {
                                binCount = 1;
                                for (Node<K,V> e = f;; ++binCount) {
                                    K ek;
                                    if (e.hash == hash &&
                                        ((ek = e.key) == key ||
                                         (ek != null && key.equals(ek)))) {
                                        oldVal = e.val;
                                        if (!onlyIfAbsent)
                                            e.val = value;
                                        break;
                                    }
                                    Node<K,V> pred = e;
                                    if ((e = e.next) == null) {
                                        pred.next = new Node<K,V>(hash, key,
                                                                  value, null);
                                        break;
                                    }
                                }
                            }
                            else if (f instanceof TreeBin) {
                                Node<K,V> p;
                                binCount = 2;
                                if ((p = ((TreeBin<K,V>)f).putTreeVal(hash, key,
                                                               value)) != null) {
                                    oldVal = p.val;
                                    if (!onlyIfAbsent)
                                        p.val = value;
                                }
                            }
                        }
                    }
                    if (binCount != 0) {
                        if (binCount >= TREEIFY_THRESHOLD)
                            treeifyBin(tab, i);
                        if (oldVal != null)
                            return oldVal;
                        break;
                    }
                }
            }
            addCount(1L, binCount);
            return null;
        }
    
    展开全文
  • HashSet使用

    2018-07-23 13:45:10
    HashSet使用 1.HashSet 特点:  1.无序,不可重复  2.容量自动增长。   2.存储原理:  向Set中添加对象时,首先调用此对象所在类的hashCode()方法,计算次对象的哈希值,  此哈希值决定了此对象在Set中存放的...

    HashSet使用
    1.HashSet 特点:
        1.无序,不可重复
        2.容量自动增长。
        
    2.存储原理:
        向Set中添加对象时,首先调用此对象所在类的hashCode()方法,计算次对象的哈希值,
        此哈希值决定了此对象在Set中存放的位置;若此位置没有被存储对象则直接存储,
        若已有对象则通过对象所在类的equals()比较两个对象是否相同,相同则不能被添加。
        
        添加进Set集合中的元素所在的类一定要重写equals() 和 hashCode()。
        要求重写equals() 和 hashCode()方法保持一致。

    3.使用场景:
       所有的技术都是为了转化为生产力,所以要知道如何取使用技术
       如购物车对象转化为订单对象,获取购物车不重复的库存地址
       
    4.hashSet没有get方法,所以遍历的时候,有两种方法,一种是通过迭代器,一种是通过增强for循环

    例子

    没有重写equals()和hashCode类添加相同元素,可以添加进去:

    package test;
    
    import java.util.HashSet;
    import java.util.Iterator;
    import java.util.Set;
    
    public class TestSet {
    	
         public static void main(String[] args){
        	  Set<Person> set = new HashSet<>();
        	  set.add(new Person(1, 1));
        	  set.add(new Person(1, 3));
        	  set.add(new Person(1, 1));
        	//  1.迭代器
        	  Iterator iterator = set.iterator();
        	  while (iterator.hasNext()) {
    			Person person = (Person) iterator.next();
    			System.out.println("迭代器:"+person);
    		} 	 
         }
    
    }
    

        结果:

               迭代器:Person [x=1, y=3]
               迭代器:Person [x=1, y=1]
              迭代器:Person [x=1, y=1]

    重写了equals()方法和hashCode()后

    package test;
    
    public class Person {
        private  int x;
        private  int y;
    	public int getX() {
    		return x;
    	}
    	public void setX(int x) {
    		this.x = x;
    	}
    	public int getY() {
    		return y;
    	}
    	public void setY(int y) {
    		this.y = y;
    	}
    	@Override
    	public String toString() {
    		return "Person [x=" + x + ", y=" + y + "]";
    	}
    	public Person(int x, int y) {
    		super();
    		this.x = x;
    		this.y = y;
    	}
    	@Override
    	public int hashCode() {
    		final int prime = 31;
    		int result = 1;
    		result = prime * result + x;
    		result = prime * result + y;
    		return result;
    	}
    	@Override
    	public boolean equals(Object obj) {
    		if (this == obj)
    			return true;
    		if (obj == null)
    			return false;
    		if (getClass() != obj.getClass())
    			return false;
    		Person other = (Person) obj;
    		if (x != other.x)
    			return false;
    		if (y != other.y)
    			return false;
    		return true;
    	}  
           
    	
    }
    
    package test;
    
    import java.util.HashSet;
    import java.util.Iterator;
    import java.util.Set;
    
    public class TestSet {
    	
         public static void main(String[] args){
        	  Set<Person> set = new HashSet<>();
        	  set.add(new Person(1, 1));
        	  set.add(new Person(1, 3));
        	  set.add(new Person(1, 1));
        	//  1.迭代器
        	  Iterator iterator = set.iterator();
        	  while (iterator.hasNext()) {
    			Person person = (Person) iterator.next();
    			System.out.println("迭代器:"+person);
    		} 	 
            /*  2.增强for循环
             * for(Person p:set){
            	 System.out.println(p);
             }*/
        	  
         }
    
    }
    

    结果:

           迭代器:Person [x=1, y=1]
           迭代器:Person [x=1, y=3]

    所以一定要重写equals()和hashCode()方法


    Set接口有两个子类:HashSet和TreeSet 。
    |-  HashSet
        |-  特点:在不存在重复元素的基础上,还可以进行高速的存取元素。
         |-  要求:需要为您的类重写hashCode()和equals()方法。
    |-  TreeSet
        |-  特点:在不存在重复元素的基础上,还可以将元素自动排序。
         |-  要求:需要为您的类实现Comparable接口,并重写compareTo方法。  
        |-  重写compareTo() 可以同时完成两份工作   排序和消除重复。

    展开全文
  • hashset踩坑

    2019-08-21 15:26:40
    业务场景: 在应用配置的时候需要给应用配置岗位信息,此时应用岗位可能会有重复的问题!虽然前端会进行校验,但是作为一个合格的后端我是不相信前端的! 使用hashset去重: 源码如上,可以看到hashSet的add方法...

    业务场景:

    在应用配置的时候需要给应用配置岗位信息,此时应用岗位可能会有重复的问题!虽然前端会进行校验,但是作为一个合格的后端我是不相信前端的!

    使用hashset去重:

    源码如上,可以看到hashSet的add方法调用的是HashMap的put的方法,而put方法返回的是上一个value值,把这个值是否为空作为方法返回!这样根据add的返回值就可以判断是否重复!

    但是每次调用的时候,多个不同岗位只有第一个返回true,之后全部返回false!此时严重怀疑自己理解错add方法了,分析原因是自己引用了一个类,这个类是数据库操作类,重写了hasdCode和equals方法,根据id来判断是否重复(对应数据库的自增主键)!由于现在每次的id都是null,所以就判断为同一个对象了

    重写hashCode和equals

    问题找到了,那我就根据职位id来重写hashCode和equals了,这边的业务是只要职位id不同就可以判断不是同一条数据了

    展开全文
  • HashSet源码

    2020-02-24 18:56:52
    1、HashSet介绍 与HashMap类似,字面上看,HashSet由两个单词组成:Hash和Set。其中,Set表示接口,实现Set接口也有多种方式,各有特点,HashSet实现的方式利用了Hash Set public interface Set<E> extends ...
  • 关于HashSet

    2018-06-09 14:33:00
    HashSet调用add方法时,有返回值,返回值是boolean类型,表示是否添加成功(如果对象不存在,则添加成功,否则添加失败)但是,添加的过程并不是一个个去遍历去判断是否已存在,这样效率太低(假设一种场景,...
  • java HashSet

    2019-08-22 11:37:38
    HashSet的源码并不长,因为底层是HashMap实现的,而HashMap的key值是不能重复的,可以直接实现Set保存非重复元素的特性 HashSet的变量不多,内部定义了一个HashMap用来保存数据,PRESENT 用来保存HashMap的只,这意味...
  • Java HashSet

    2017-02-28 09:37:16
    容器实现了Set接口,后端由hash table支持.每次在迭代的时候,容器不保证迭代遍历的顺序.可以存储null元素. ...因此,在性能非常重要的场景下,不适合于将HashSet的初始capacity设置的过大或者装载因子过低. 同样
  • 《java编程的逻辑》读书笔记 HashMap 主要实例变量: ...transient Entry,V>[] talbe = ...如果要保持添加的顺序,可以使用HashSet的一个子类,LinkedHashSet。Set还有一个重要的 实现类TreeSet,它可以排序。
  • 深度剖析HashSet

    万次阅读 2020-12-05 13:02:29
    HashSet是Java集合Set的一个实现类,Set是一个接口,其实现类除HashSet之外,还有TreeSet,并继承了Collection,HashSet集合很常用,同时也是程序员面试时经常会被问到的知识点 我就没见过这么不要脸的数据结构,...
  • 一般用于对健值对方式快速查询的使用场景。但是线程不安全,线程的安全的话可以使用tableMap,但tableMap的锁太重,因此可以使用ConcurretHashMap采取分段锁的方式性能更搞。 HashMap无序,如果要有序遍历的情况可以...
  • HashSet基本操作

    2019-09-18 00:04:46
    ** 1.HashSet的添加时的...**1.1 **重要:需要去重的对象必须做到覆盖Object的equals和hashcode方法,具体实现需要根据业务场景来定. **1.2 **HashSet 会首先调用 obj 的 hasCode 方法得到该对象的哈希码,HashSet 会...
  • Java集合之HashSet

    2017-08-04 14:58:14
    HashSet
  • HashSet 存储结构,应用场景,实现原理
  • HashSet学习笔记

    2021-08-09 21:48:08
    文章目录tips构造方法迭代器方法 tips HashSet是依赖于HashMap的一种Set接口的实现。不能保证在对set进行迭代时的顺序,...当再多线程场景下使用时,建议在创建对象时使用以下方法: Set s = Collections.synchroni
  • HashSet源码分析

    2011-12-03 10:39:03
    HashSet源码分析     HashSet是Set的一个实现,Set定义一个集合,集合的一个特征是不能包含重复的元素(可以包含null),HashSet底层使用HashMap作为存储结构来实现。    可知HashSet只用来存储对象,并不是...
  • ArrayList与LinkedList的区别和适用场景 Arraylist: 优点:ArrayList是实现了基于动态数组的数据结构,因为地址连续,一旦数据存储好了,查询操作效率会比较高(在内存里是连着放的)。 缺点:因为地址连续,...
  • HashSet 源码解析

    2018-01-08 00:22:27
    HashSet ,是在HashMap的基础之上保持这一特性,并且拥有自身的特点(如果对于HashMap忘了,或者不了解,可以先了解HashMap , 否则,是无法准确地了解HashSet的原理。所以此篇文章是基于了解一些HashMap特性的) ...
  • 应用场景:数据去重复 Application:Data removal duplication 继承关系:HashSet继承于AbstractSet,AbstractSet继承于AbstractCollection实现了Set,克隆,有序化接口. Extend relationship:HashSet extends ...
  • 之所以把HashSet和HashMap放在一起讲解,是因为二者在Java里有着相同的实现,前者仅仅是对后者做了一层包装,也就是说HashSet里面有一个HashMap(适配器模式)。因此本文将重点分析HashMap。 HashMap实现了Map...
  • HashMap和HashSet

    2019-11-23 22:12:48
    Map和Set都是接口,他们的定义都必须使用TreeMap,TreeSet或HashMap,HashSet来实现。 例: Map map = new HashMap(); Set set = new HashSet(); Map、Set与数组的区别 Map存储的是键值对,Set存储的是一个值,但是...
  • Java HashSet用法详解

    2020-09-07 10:35:17
    HashSet基于HashMap来实现的,是一个不允许有重复元素的集合。 HashSet允许有null值。它是无序的,即不会记录插入的顺序。它也不是线程安全,如果多个线程同时修改HashSet,则最终结果是不确定的。所以必须在多线程...
  • 深入理解java之HashSet

    2018-05-20 17:40:58
    深入理解java之HashSet 本文我们深入讨论HashSet,Set接口最常用的实现,也是java Collection Framework的一个组成部分。 HashSet简介 HashSet是java集合API中基础数据结构之一,我们回顾起实现中最基本的方面...
  • Java集合-HashSet

    2019-04-29 23:58:58
    Java集合-HashSet
  • HashSet 前言 HashSet是一个不可重复且元素无序的集合。内部使用HashMap实现。 我们可以从HashSet源码的类注释中获取到...线程不安全的集合,如果在多线程的场景下建议使用 //Collections#synchronizedSetCollections

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 33,667
精华内容 13,466
关键字:

hashset场景